{"openapi":"3.1.0","info":{"title":"arText Reports API","description":"Envia un text, consulta l’informe asíncron i utilitza suggeriments lingüístics estructurats en els teus productes.","version":"1.0.0"},"paths":{"/v1/reports":{"post":{"tags":["Reports"],"summary":"Crear un informe d’anàlisi","description":"Valida i posa un text a la cua. La resposta 202 inclou recursos d’estat i d’esdeveniments; no implica que l’anàlisi hagi acabat.","operationId":"create_public_report_v1_reports_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":255},{"type":"null"}],"title":"Idempotency-Key"},"description":"Recommended unique key for safely retrying this creation request. It is scoped to the authenticated caller, retained for 24 hours, and must not be reused with a different payload.","example":"document-123-analysis-v1"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportRequest"},"examples":{"basic":{"summary":"Create a report","value":{"language":"ca","domain_slug":"llenguatge-clar","text_type_slug":"text-juridic-administratiu-dirigit-a-la-ciutadania","text":"En el dia d’avui es durà a terme la revisió de la sol·licitud.","external_id":"document-123"}}}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportAccepted"},"examples":{"queued":{"summary":"Report accepted and queued","value":{"report_id":"rep_7f12a4c8","external_id":"document-123","status":"queued","status_url":"/v1/reports/rep_7f12a4c8","events_url":"/v1/reports/rep_7f12a4c8/events"}}}}},"headers":{"Location":{"description":"Canonical status resource for the accepted report.","schema":{"type":"string","example":"/v1/reports/rep_7f12a4c8"}},"Retry-After":{"description":"Minimum number of seconds before the first status poll.","schema":{"type":"integer","minimum":1,"example":2}},"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"401":{"description":"Missing, invalid, inactive or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"409":{"description":"Idempotency-Key was reused with a different payload.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"413":{"description":"Text exceeds the configured word limit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"422":{"description":"Request validation failed, including an unknown domain_slug/text_type_slug pair.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}},"Retry-After":{"description":"Seconds to wait before a retry can be attempted.","schema":{"type":"integer","minimum":1,"example":2}}}},"503":{"description":"The analysis queue is unavailable.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}},"Retry-After":{"description":"Seconds to wait before a retry can be attempted.","schema":{"type":"integer","minimum":1,"example":2}}}}},"security":[{"ApiKey":[]}]}},"/v1/reports/{report_id}":{"get":{"tags":["Reports"],"summary":"Consultar l’estat i el resultat","description":"Retorna l’estat actual. En queued/running cal respectar Retry-After; completed i failed són terminals.","operationId":"get_public_report_v1_reports__report_id__get","parameters":[{"name":"report_id","in":"path","required":true,"schema":{"type":"string","title":"Report Id"},"description":"Unique report identifier returned by POST /v1/reports."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Report"},"examples":{"queued":{"summary":"Report queued","value":{"report_id":"rep_7f12a4c8","external_id":"document-123","status":"queued","status_url":"/v1/reports/rep_7f12a4c8","events_url":"/v1/reports/rep_7f12a4c8/events"}},"completed":{"summary":"Report completed","value":{"report_id":"rep_7f12a4c8","external_id":"document-123","status":"completed","position_in_queue":null,"result":{"schema_version":"1.0","offset_unit":"unicode_code_points","language":"ca","genre":{"domain":{"slug":"llenguatge-clar","name":"Llenguatge clar"},"text_type":{"slug":"text-juridic-administratiu-dirigit-a-la-ciutadania","name":"Text juridicoadministratiu dirigit a la ciutadania"}},"measurements":[{"metric_id":"word-count","value":12,"unit":"words","implementation_version":"1.0"}],"suggestions":[{"id":"sug_1","metric_id":"redundant-expressions","implementation_version":"1.0","metric_title":"Eliminació d’expressions redundants","category":"lexical","severity":"warning","summary":"Convé formular el fragment d’una manera més directa.","explanation":null,"occurrences":[{"id":"occ_1","text":"En el dia d’avui","paragraph_index":0,"sentence_index":0,"start":0,"end":16,"replacement":null,"alternatives":[],"edits":[{"start":0,"end":16,"text":""}]}],"recommendations":["Elimina l’expressió si el context ho permet."]}]},"error":null}},"failed":{"summary":"Report failed","value":{"report_id":"rep_7f12a4c8","external_id":"document-123","status":"failed","position_in_queue":null,"result":null,"error":{"code":"analysis_failed","message":"The analysis could not be completed."}}}}}},"headers":{"Retry-After":{"description":"Present for queued/running reports; wait at least this many seconds before polling again.","schema":{"type":"integer","minimum":1,"example":5}},"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"401":{"description":"Missing, invalid, inactive or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"404":{"description":"Report not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"429":{"description":"Status rate limit or minimum polling interval exceeded.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}},"Retry-After":{"description":"Seconds to wait before a retry can be attempted.","schema":{"type":"integer","minimum":1,"example":2}}}},"503":{"description":"Request protection is temporarily unavailable.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}},"Retry-After":{"description":"Seconds to wait before a retry can be attempted.","schema":{"type":"integer","minimum":1,"example":2}}}},"422":{"description":"Validation Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}}},"security":[{"ApiKey":[]}]}},"/v1/reports/{report_id}/events":{"get":{"tags":["Reports"],"summary":"Rebre transicions per SSE","description":"Canal SSE opcional amb l’estat inicial, canvis i heartbeats. Es tanca en acabar; el polling continua sent el mecanisme de reserva.","operationId":"stream_public_report_events_v1_reports__report_id__events_get","parameters":[{"name":"report_id","in":"path","required":true,"schema":{"type":"string","title":"Report Id"},"description":"Unique report identifier returned by POST /v1/reports."}],"responses":{"200":{"description":"SSE status stream.","content":{"text/event-stream":{"schema":{"type":"string"},"examples":{"transitions":{"summary":"A stream closes after completed or failed","value":"event: status\\ndata: {\"report_id\":\"rep_7f12a4c8\",\"status\":\"running\",\"updated_at\":\"2026-07-15T10:00:02Z\"}\\n\\nevent: status\\ndata: {\"report_id\":\"rep_7f12a4c8\",\"status\":\"completed\",\"updated_at\":\"2026-07-15T10:00:06Z\"}\\n\\n"}}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"401":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"description":"Unauthorized","headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"description":"Not Found","headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"429":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"description":"Too Many Requests","headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}},"Retry-After":{"description":"Seconds to wait before a retry can be attempted.","schema":{"type":"integer","minimum":1,"example":2}}}},"503":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"description":"Service Unavailable","headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}},"Retry-After":{"description":"Seconds to wait before a retry can be attempted.","schema":{"type":"integer","minimum":1,"example":2}}}},"422":{"description":"Validation Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}}},"security":[{"ApiKey":[]}]}},"/v1/metrics":{"get":{"tags":["Metrics"],"summary":"List metric implementations","description":"Returns measurement and suggestion implementations, including inactive variants and localized documentation. Narrowing the request to a genre reports which metrics that genre actually evaluates.","operationId":"list_metrics_v1_metrics_get","parameters":[{"name":"analysis_language","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Analysis Language"},"description":"Language implementation to return: es, ca or en."},{"name":"documentation_language","in":"query","required":false,"schema":{"type":"string","default":"es","title":"Documentation Language"},"description":"Language used for titles and documentation: es, ca or en."},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(measurement|suggestion)$"},{"type":"null"}],"title":"Kind"},"description":"Filter by measurement or suggestion."},{"name":"enabled","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"},"description":"Filter by the current implementation status."},{"name":"domain_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional genre filter. domain_slug and text_type_slug go together and must name a genre listed by GET /v1/text-types; each metric then reports whether that genre evaluates it and with which thresholds.","title":"Domain Slug"},"description":"Text domain of a genre, as listed by GET /v1/text-types."},{"name":"text_type_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional genre filter. domain_slug and text_type_slug go together and must name a genre listed by GET /v1/text-types; each metric then reports whether that genre evaluates it and with which thresholds.","title":"Text Type Slug"},"description":"Text type (genre) inside domain_slug, as listed by GET /v1/text-types."}],"responses":{"200":{"description":"Metric implementations and their documentation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricCatalog"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"401":{"description":"Missing, invalid, inactive or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"422":{"description":"Incomplete or unknown genre filter.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}}},"security":[{"ApiKey":[]}]}},"/v1/metrics/{metric_id}":{"get":{"tags":["Metrics"],"summary":"Get one metric implementation","description":"Returns the status, category and localized documentation for one language variant, optionally narrowed to a genre.","operationId":"get_metric_v1_metrics__metric_id__get","parameters":[{"name":"metric_id","in":"path","required":true,"schema":{"type":"string","title":"Metric Id"},"description":"Stable conceptual metric identifier."},{"name":"analysis_language","in":"query","required":true,"schema":{"type":"string","title":"Analysis Language"},"description":"Language implementation to return: es, ca or en."},{"name":"documentation_language","in":"query","required":false,"schema":{"type":"string","default":"es","title":"Documentation Language"},"description":"Language used for titles and documentation: es, ca or en."},{"name":"domain_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional genre filter. domain_slug and text_type_slug go together and must name a genre listed by GET /v1/text-types; each metric then reports whether that genre evaluates it and with which thresholds.","title":"Domain Slug"},"description":"Text domain of a genre, as listed by GET /v1/text-types."},{"name":"text_type_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional genre filter. domain_slug and text_type_slug go together and must name a genre listed by GET /v1/text-types; each metric then reports whether that genre evaluates it and with which thresholds.","title":"Text Type Slug"},"description":"Text type (genre) inside domain_slug, as listed by GET /v1/text-types."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Metric"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"401":{"description":"Missing, invalid, inactive or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"404":{"description":"Metric implementation not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"422":{"description":"Incomplete or unknown genre filter.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}}},"security":[{"ApiKey":[]}]}},"/v1/text-types":{"get":{"tags":["Text types"],"summary":"List text domains and genres","description":"Returns the domains (ámbitos) and the genres (text types) available for a language. The slug pair of a genre is what POST /v1/reports expects.","operationId":"list_public_text_types_v1_text_types_get","parameters":[{"name":"language","in":"query","required":false,"schema":{"type":"string","default":"es","title":"Language"},"description":"Catalog language: es, ca or en."}],"responses":{"200":{"description":"Editorial catalog for the requested language.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTextTypeCatalog"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"401":{"description":"Missing, invalid, inactive or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"422":{"description":"Unsupported language.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}}},"security":[{"ApiKey":[]}]}},"/v1/text-types/{domain_slug}/{text_type_slug}":{"get":{"tags":["Text types"],"summary":"Get one genre","description":"Returns the sections and contents recommended for a genre, plus the exact report_defaults to forward to POST /v1/reports.","operationId":"get_public_text_type_v1_text_types__domain_slug___text_type_slug__get","parameters":[{"name":"domain_slug","in":"path","required":true,"schema":{"type":"string","title":"Domain Slug"},"description":"Text domain of a genre, as listed by GET /v1/text-types."},{"name":"text_type_slug","in":"path","required":true,"schema":{"type":"string","title":"Text Type Slug"},"description":"Text type (genre) inside domain_slug, as listed by GET /v1/text-types."},{"name":"language","in":"query","required":false,"schema":{"type":"string","default":"es","title":"Language"},"description":"Catalog language: es, ca or en."}],"responses":{"200":{"description":"Genre detail and its report defaults.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTextTypeDetail"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"401":{"description":"Missing, invalid, inactive or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"404":{"description":"Genre not found for this language.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}},"422":{"description":"Unsupported language.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiProblem"}}},"headers":{"X-Request-ID":{"description":"Identifier to retain for support and tracing.","schema":{"type":"string","example":"req_4adf8f2c"}}}}},"security":[{"ApiKey":[]}]}}},"components":{"schemas":{"ApiProblem":{"properties":{"type":{"type":"string","title":"Type","description":"URI reference identifying the problem type."},"title":{"type":"string","title":"Title","description":"Short, stable problem title."},"status":{"type":"integer","title":"Status","description":"HTTP status code."},"detail":{"type":"string","title":"Detail","description":"Human-readable explanation for this occurrence."},"instance":{"type":"string","title":"Instance","description":"Request path for this occurrence."},"code":{"type":"string","title":"Code","description":"Stable machine-readable arText error code."},"request_id":{"type":"string","title":"Request Id","description":"Identifier to retain for support and tracing."},"retry_after_seconds":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Retry After Seconds"},"errors":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Errors"}},"type":"object","required":["type","title","status","detail","instance","code","request_id"],"title":"ApiProblem"},"Genre":{"properties":{"domain":{"$ref":"#/components/schemas/TextDomain"},"text_type":{"$ref":"#/components/schemas/TextType"}},"type":"object","required":["domain","text_type"],"title":"Genre","description":"Genre the report was analyzed with.\n\nIt names both coordinates because a text type slug is only unique inside\nits domain, and the pair is what determined the rules, the thresholds and\nthe glossaries used. Resubmitting these two slugs reproduces the analysis."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"Measurement":{"properties":{"metric_id":{"type":"string","title":"Metric Id","description":"Stable metric identifier documented by GET /v1/metrics/{metric_id}."},"value":{"anyOf":[{"type":"integer"},{"type":"number"}],"title":"Value","description":"Calculated numeric value."},"unit":{"type":"string","title":"Unit","description":"Semantic unit defined by the metric catalog."},"implementation_version":{"type":"string","title":"Implementation Version","description":"Calculator version used for this report."}},"type":"object","required":["metric_id","value","unit","implementation_version"],"title":"Measurement"},"Metric":{"properties":{"id":{"type":"string","title":"Id"},"kind":{"type":"string","enum":["measurement","suggestion"],"title":"Kind"},"analysis_language":{"type":"string","title":"Analysis Language"},"enabled":{"type":"boolean","title":"Enabled","description":"Whether reports for analysis_language currently evaluate this variant."},"genre_scope":{"anyOf":[{"$ref":"#/components/schemas/MetricGenreScope"},{"type":"null"}],"description":"Genre-specific status, present only when the request selects a genre."},"available":{"type":"boolean","title":"Available","description":"False when the variant can never produce output for analysis_language with the current linguistic runtime; see availability_note.","default":true},"availability_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Availability Note","description":"Localized explanation present only when available is false."},"implementation_version":{"type":"string","title":"Implementation Version"},"category":{"type":"string","title":"Category"},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit"},"documentation_language":{"type":"string","title":"Documentation Language","description":"Language actually used by the returned documentation."},"documentation":{"$ref":"#/components/schemas/MetricDocumentation"},"references":{"items":{"type":"string"},"type":"array","title":"References"},"example":{"additionalProperties":true,"type":"object","title":"Example","description":"Example conforming to the public report contract."}},"type":"object","required":["id","kind","analysis_language","enabled","implementation_version","category","documentation_language","documentation"],"title":"Metric"},"MetricCatalog":{"properties":{"genre":{"anyOf":[{"$ref":"#/components/schemas/Genre"},{"type":"null"}],"description":"Genre the genre_scope of every metric refers to, when one was requested."},"metrics":{"items":{"$ref":"#/components/schemas/Metric"},"type":"array","title":"Metrics"}},"type":"object","required":["metrics"],"title":"MetricCatalog"},"MetricDocumentation":{"properties":{"title":{"type":"string","title":"Title","default":""},"summary":{"type":"string","title":"Summary","default":""},"methodology":{"type":"string","title":"Methodology","default":""},"limitations":{"type":"string","title":"Limitations","default":""},"interpretation":{"type":"string","title":"Interpretation","default":""}},"type":"object","title":"MetricDocumentation"},"MetricGenreScope":{"properties":{"enabled":{"type":"boolean","title":"Enabled","description":"Whether reports for this genre evaluate the metric."},"params":{"additionalProperties":true,"type":"object","title":"Params","description":"Thresholds this genre configures for the metric; empty means the defaults."}},"type":"object","required":["enabled"],"title":"MetricGenreScope","description":"How a metric behaves for one genre.\n\nPresent only when the request narrows the catalog with domain_slug and\ntext_type_slug. `enabled` is the intersection of the language variant and\nthe genre configuration: a variant enabled for the language still does not\nrun unless the genre opts into it."},"Occurrence":{"properties":{"id":{"type":"string","title":"Id","description":"Identifier unique within its parent suggestion."},"text":{"type":"string","title":"Text","description":"Fragment identified by the metric."},"paragraph_index":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Paragraph Index","description":"Zero-based paragraph index when available."},"sentence_index":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Sentence Index","description":"Zero-based sentence index when available."},"start":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Start","description":"Inclusive offset in the original input text."},"end":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"End","description":"Exclusive offset in the original input text."},"replacement":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Replacement","description":"Preferred direct replacement, or null when none is available."},"alternatives":{"items":{"type":"string"},"type":"array","title":"Alternatives","description":"Additional reviewed replacement candidates, excluding replacement."},"edits":{"items":{"$ref":"#/components/schemas/TextEdit"},"type":"array","title":"Edits","description":"Validated edits for the preferred deterministic change, ordered from the highest offset to the lowest."}},"type":"object","required":["id","text"],"title":"Occurrence"},"PublicPhraseology":{"properties":{"value":{"type":"string","title":"Value","description":"Suggested wording for the content it belongs to."}},"type":"object","required":["value"],"title":"PublicPhraseology"},"PublicTextContent":{"properties":{"name":{"type":"string","title":"Name","description":"Content the section is expected to cover."},"occurrence":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Occurrence","description":"How many times the content usually appears in the section, when the catalog states it."},"phraseology":{"items":{"$ref":"#/components/schemas/PublicPhraseology"},"type":"array","title":"Phraseology","description":"Wordings the editorial team proposes for this content."}},"type":"object","required":["name"],"title":"PublicTextContent"},"PublicTextDomain":{"properties":{"slug":{"type":"string","title":"Slug","description":"Domain identifier. Send it as domain_slug in POST /v1/reports."},"name":{"type":"string","title":"Name","description":"Domain name in the requested language."},"clear_language":{"type":"boolean","title":"Clear Language","description":"True when the whole domain is plain-language.","default":false},"text_types":{"items":{"$ref":"#/components/schemas/PublicTextType"},"type":"array","title":"Text Types","description":"Genres available inside this domain."}},"type":"object","required":["slug","name"],"title":"PublicTextDomain"},"PublicTextSection":{"properties":{"name":{"type":"string","title":"Name","description":"Section of the document, in reading order."},"contents":{"items":{"$ref":"#/components/schemas/PublicTextContent"},"type":"array","title":"Contents"}},"type":"object","required":["name"],"title":"PublicTextSection"},"PublicTextType":{"properties":{"slug":{"type":"string","title":"Slug","description":"Genre identifier. Send it as text_type_slug in POST /v1/reports."},"name":{"type":"string","title":"Name","description":"Genre name in the requested language."},"clear_language":{"type":"boolean","title":"Clear Language","description":"True when the genre is written in plain language for the general public.","default":false}},"type":"object","required":["slug","name"],"title":"PublicTextType"},"PublicTextTypeCatalog":{"properties":{"language":{"type":"string","title":"Language","description":"Language the catalog is returned in."},"domains":{"items":{"$ref":"#/components/schemas/PublicTextDomain"},"type":"array","title":"Domains"}},"type":"object","required":["language","domains"],"title":"PublicTextTypeCatalog"},"PublicTextTypeDetail":{"properties":{"language":{"type":"string","title":"Language"},"domain":{"$ref":"#/components/schemas/PublicTextDomain","description":"Domain the genre belongs to, without its sibling genres."},"text_type":{"$ref":"#/components/schemas/PublicTextType"},"structure":{"items":{"$ref":"#/components/schemas/PublicTextSection"},"type":"array","title":"Structure","description":"Sections and contents the editorial team recommends for this genre."},"report_defaults":{"$ref":"#/components/schemas/ReportDefaults","description":"Exact payload fragment to forward to POST /v1/reports."}},"type":"object","required":["language","domain","text_type","report_defaults"],"title":"PublicTextTypeDetail"},"Report":{"properties":{"report_id":{"type":"string","title":"Report Id"},"external_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Id"},"status":{"$ref":"#/components/schemas/ReportStatus"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At","description":"UTC acceptance timestamp."},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At","description":"UTC last-transition timestamp."},"started_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Started At","description":"UTC processing start timestamp."},"finished_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Finished At","description":"UTC terminal timestamp."},"position_in_queue":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Position In Queue","description":"Approximate queue position while waiting."},"phase":{"anyOf":[{"$ref":"#/components/schemas/ReportPhase"},{"type":"null"}],"description":"Pipeline stage while the report is running: `analyzing` (linguistic analysis, by far the longest part) or `building` (applying rules). Not a percentage: it marks what the server is doing, not how far along it is."},"estimated_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Estimated Seconds","description":"Rough estimate of the analysis duration, derived from the text length when the report was accepted. Indicative only: it excludes queue wait and does not react to server load."},"result":{"anyOf":[{"$ref":"#/components/schemas/ReportResult"},{"type":"null"}],"description":"Analysis result, present only when completed."},"error":{"anyOf":[{"$ref":"#/components/schemas/ReportFailure"},{"type":"null"}],"description":"Safe failure information, present only when failed."}},"type":"object","required":["report_id","status"],"title":"Report"},"ReportAccepted":{"properties":{"report_id":{"type":"string","title":"Report Id","description":"Unique arText report identifier."},"external_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Id","description":"Caller-provided correlation identifier."},"status":{"$ref":"#/components/schemas/ReportStatus","description":"Initial queue status; always queued for a newly accepted report."},"status_url":{"type":"string","title":"Status Url","description":"Relative URL of the report status resource."},"events_url":{"type":"string","title":"Events Url","description":"Relative URL of the optional SSE status stream."},"estimated_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Estimated Seconds","description":"Rough estimate of how long the analysis will take, derived from the length of the submitted text. Indicative only: it excludes queue wait and does not react to server load."}},"type":"object","required":["report_id","status","status_url","events_url"],"title":"ReportAccepted"},"ReportDefaults":{"properties":{"language":{"type":"string","title":"Language","description":"Analysis language the slugs below belong to."},"domain_slug":{"type":"string","title":"Domain Slug","description":"Value for the domain_slug field of a report request."},"text_type_slug":{"type":"string","title":"Text Type Slug","description":"Value for the text_type_slug field of a report request."}},"type":"object","required":["language","domain_slug","text_type_slug"],"title":"ReportDefaults","description":"Exact fields to forward to POST /v1/reports for this genre."},"ReportFailure":{"properties":{"code":{"type":"string","const":"analysis_failed","title":"Code","default":"analysis_failed"},"message":{"type":"string","title":"Message","description":"Safe failure description suitable for API clients."}},"type":"object","required":["message"],"title":"ReportFailure"},"ReportPhase":{"type":"string","enum":["analyzing","building"],"title":"ReportPhase","description":"Punto de la tubería mientras el estado es `running`.\n\nNo es un porcentaje y no debe presentarse como tal: `analyzing` se lleva el\n94 % del tiempo (una única llamada a FreeLing, que no informa de su avance),\nasí que una barra basada en esto se quedaría clavada casi todo el rato. Sirve\npara decir qué está pasando y que sigue vivo; para «cuánto queda» está\n`estimated_seconds`."},"ReportRequest":{"properties":{"language":{"type":"string","title":"Language","description":"Language used for analysis: es, ca or en.","default":"es"},"domain_slug":{"type":"string","minLength":1,"title":"Domain Slug","description":"Text domain (ámbito) the genre belongs to, as listed by GET /v1/text-types.","examples":["lenguaje-claro"]},"text_type_slug":{"type":"string","minLength":1,"title":"Text Type Slug","description":"Text type (genre) inside domain_slug, as listed by GET /v1/text-types. The pair selects the rules, thresholds and glossaries applied to the text.","examples":["texto-juridico-administrativo-dirigido-a-la-ciudadania"]},"text":{"type":"string","minLength":1,"title":"Text","description":"Plain text to analyze."},"external_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Id","description":"Optional caller-owned correlation identifier returned unchanged."}},"additionalProperties":false,"type":"object","required":["domain_slug","text_type_slug","text"],"title":"ReportRequest","description":"Stable input accepted from API integrations."},"ReportResult":{"properties":{"schema_version":{"type":"string","const":"1.0","title":"Schema Version","description":"Version of this public result contract.","default":"1.0"},"offset_unit":{"type":"string","const":"unicode_code_points","title":"Offset Unit","description":"Unit used by every start and end offset in the result.","default":"unicode_code_points"},"language":{"type":"string","title":"Language","description":"Language actually used for analysis."},"genre":{"$ref":"#/components/schemas/Genre"},"measurements":{"items":{"$ref":"#/components/schemas/Measurement"},"type":"array","title":"Measurements"},"suggestions":{"items":{"$ref":"#/components/schemas/Suggestion"},"type":"array","title":"Suggestions"}},"type":"object","required":["language","genre"],"title":"ReportResult"},"ReportStatus":{"type":"string","enum":["queued","running","completed","failed"],"title":"ReportStatus"},"Suggestion":{"properties":{"id":{"type":"string","title":"Id","description":"Identifier unique within this report."},"metric_id":{"type":"string","title":"Metric Id","description":"Stable metric identifier documented by GET /v1/metrics/{metric_id}."},"implementation_version":{"type":"string","title":"Implementation Version","description":"Detector version used for this report."},"metric_title":{"type":"string","title":"Metric Title","description":"Localized human-readable metric title captured for this report."},"category":{"type":"string","title":"Category","description":"Stable linguistic category used by the metric catalog."},"severity":{"type":"string","title":"Severity","description":"Review priority; it is not a confidence score."},"summary":{"type":"string","title":"Summary","description":"Explanation of the issue found in this report."},"explanation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Explanation","description":"Optional extended contextual explanation."},"recommendations":{"items":{"type":"string"},"type":"array","title":"Recommendations","description":"Human-readable review guidance."},"examples":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Examples","description":"Optional worked examples illustrating the recommendation, as plain text with meaningful line breaks. Editorial copy attached to the metric: it never quotes the analysed text and does not vary between reports. Null when the metric's copy has no examples."},"occurrences":{"items":{"$ref":"#/components/schemas/Occurrence"},"type":"array","title":"Occurrences","description":"Concrete appearances of this issue in the submitted text."}},"type":"object","required":["id","metric_id","implementation_version","metric_title","category","severity","summary"],"title":"Suggestion"},"TextDomain":{"properties":{"slug":{"type":"string","title":"Slug","description":"Stable text domain identifier accepted by POST /v1/reports."},"name":{"type":"string","title":"Name","description":"Localized text domain name."}},"type":"object","required":["slug","name"],"title":"TextDomain"},"TextEdit":{"properties":{"start":{"type":"integer","minimum":0.0,"title":"Start","description":"Inclusive offset in the original input text."},"end":{"type":"integer","minimum":0.0,"title":"End","description":"Exclusive offset in the original input text."},"text":{"type":"string","title":"Text","description":"Text to splice into the range. Empty text deletes it; start == end inserts text."}},"type":"object","required":["start","end","text"],"title":"TextEdit"},"TextType":{"properties":{"slug":{"type":"string","title":"Slug","description":"Stable text type identifier accepted by POST /v1/reports."},"name":{"type":"string","title":"Name","description":"Localized text type name."}},"type":"object","required":["slug","name"],"title":"TextType"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"ApiKey":{"type":"http","scheme":"bearer","bearerFormat":"art_live_…"}}},"servers":[{"url":"http://uned.tail9cc3dd.ts.net"}],"x-artext-metrics":[{"id":"average-sentence-words","kind":"measurement","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.0","category":"readability","unit":"words","documentation_language":"ca","documentation":{"title":"Average sentence words","summary":"Mitjana de paraules per oració.","methodology":"Divideix word-count per sentence-count i arrodoneix a dos decimals; retorna 0 si no hi ha oracions.","limitations":"El valor depèn de la normalització i segmentació de l'analitzador; cal interpretar-lo juntament amb les altres mètriques i el gènere textual.","interpretation":"`value` conté el resultat numèric i `unit` és `words`. L'absència indica que la variant estava desactivada."},"references":[],"example":{"metric_id":"average-sentence-words","value":24,"unit":"words","implementation_version":"1.0"}},{"id":"maximum-paragraph-words","kind":"measurement","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.0","category":"readability","unit":"words","documentation_language":"ca","documentation":{"title":"Maximum paragraph words","summary":"Longitud, en paraules, del paràgraf més extens.","methodology":"Obté el màxim de word_count entre els paràgrafs detectats; retorna 0 si no n'hi ha cap.","limitations":"El valor depèn de la normalització i segmentació de l'analitzador; cal interpretar-lo juntament amb les altres mètriques i el gènere textual.","interpretation":"`value` conté el resultat numèric i `unit` és `words`. L'absència indica que la variant estava desactivada."},"references":[],"example":{"metric_id":"maximum-paragraph-words","value":24,"unit":"words","implementation_version":"1.0"}},{"id":"maximum-sentence-words","kind":"measurement","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.0","category":"readability","unit":"words","documentation_language":"ca","documentation":{"title":"Maximum sentence words","summary":"Longitud, en paraules, de l'oració més extensa.","methodology":"Obté el màxim de word_count entre les oracions segmentades; retorna 0 si no n'hi ha cap.","limitations":"El valor depèn de la normalització i segmentació de l'analitzador; cal interpretar-lo juntament amb les altres mètriques i el gènere textual.","interpretation":"`value` conté el resultat numèric i `unit` és `words`. L'absència indica que la variant estava desactivada."},"references":[],"example":{"metric_id":"maximum-sentence-words","value":24,"unit":"words","implementation_version":"1.0"}},{"id":"paragraph-count","kind":"measurement","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.0","category":"document","unit":"count","documentation_language":"ca","documentation":{"title":"Paragraph count","summary":"Nombre de paràgrafs no buits detectats.","methodology":"Segmenta el text en paràgrafs i compta les unitats amb contingut analitzable.","limitations":"El valor depèn de la normalització i segmentació de l'analitzador; cal interpretar-lo juntament amb les altres mètriques i el gènere textual.","interpretation":"`value` conté el resultat numèric i `unit` és `count`. L'absència indica que la variant estava desactivada."},"references":[],"example":{"metric_id":"paragraph-count","value":24,"unit":"count","implementation_version":"1.0"}},{"id":"segment-count","kind":"measurement","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.0","category":"document","unit":"count","documentation_language":"ca","documentation":{"title":"Segment count","summary":"Nombre de segments interns d'oració reconeguts.","methodology":"Suma els segments sintacticodiscursius produïts per DiSeg per a totes les oracions.","limitations":"El valor depèn de la normalització i segmentació de l'analitzador; cal interpretar-lo juntament amb les altres mètriques i el gènere textual.","interpretation":"`value` conté el resultat numèric i `unit` és `count`. L'absència indica que la variant estava desactivada."},"references":[],"example":{"metric_id":"segment-count","value":24,"unit":"count","implementation_version":"1.0"}},{"id":"sentence-count","kind":"measurement","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.0","category":"document","unit":"count","documentation_language":"ca","documentation":{"title":"Sentence count","summary":"Nombre d'oracions segmentades per l'analitzador.","methodology":"Compta les oracions reconegudes per FreeLing/DiSeg, no només els punts del text.","limitations":"El valor depèn de la normalització i segmentació de l'analitzador; cal interpretar-lo juntament amb les altres mètriques i el gènere textual.","interpretation":"`value` conté el resultat numèric i `unit` és `count`. L'absència indica que la variant estava desactivada."},"references":[],"example":{"metric_id":"sentence-count","value":24,"unit":"count","implementation_version":"1.0"}},{"id":"token-count","kind":"measurement","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.0","category":"document","unit":"count","documentation_language":"ca","documentation":{"title":"Token count","summary":"Nombre d'unitats lèxiques produïdes per l'analitzador.","methodology":"Compta els tokens de FreeLing/DiSeg; la puntuació i les contraccions poden fer que difereixi de word-count.","limitations":"El valor depèn de la normalització i segmentació de l'analitzador; cal interpretar-lo juntament amb les altres mètriques i el gènere textual.","interpretation":"`value` conté el resultat numèric i `unit` és `count`. L'absència indica que la variant estava desactivada."},"references":[],"example":{"metric_id":"token-count","value":24,"unit":"count","implementation_version":"1.0"}},{"id":"word-count","kind":"measurement","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.0","category":"document","unit":"count","documentation_language":"ca","documentation":{"title":"Word count","summary":"Nombre de paraules del text normalitzat.","methodology":"Normalitza els espais del text i compta cada element no buit separat per espais.","limitations":"El valor depèn de la normalització i segmentació de l'analitzador; cal interpretar-lo juntament amb les altres mètriques i el gènere textual.","interpretation":"`value` conté el resultat numèric i `unit` és `count`. L'absència indica que la variant estava desactivada."},"references":[],"example":{"metric_id":"word-count","value":24,"unit":"count","implementation_version":"1.0"}},{"id":"acronym-consistency","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"lexical","unit":null,"documentation_language":"ca","documentation":{"title":"Sistematicitat en l'ús de sigles","summary":"Detecta repeticions del terme desenvolupat després que ja s'hagi introduït la sigla.","methodology":"Després d'identificar sigla i desenvolupament a la primera aparició, cerca si el desenvolupament complet torna a aparèixer més endavant.","limitations":"És un senyal de revisió, no una correcció automàtica ni una avaluació completa de la qualitat del text.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"acronym-consistency","implementation_version":"1.2","metric_title":"Sistematicitat en l'ús de sigles","category":"lexical","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"acronym-introduction","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"lexical","unit":null,"documentation_language":"ca","documentation":{"title":"Introducció de sigles","summary":"Detecta la primera aparició de sigles en majúscules que no semblen acompanyades pel seu desenvolupament.","methodology":"Extreu candidats en majúscules, ignora paraules buides, conserva la primera aparició i cerca un desenvolupament adjacent abans o després.","limitations":"És un senyal de revisió, no una correcció automàtica ni una avaluació completa de la qualitat del text.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"acronym-introduction","implementation_version":"1.2","metric_title":"Introducció de sigles","category":"lexical","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"archaic-verb-forms","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"morphosyntax","unit":null,"documentation_language":"ca","documentation":{"title":"Eliminació de formes verbals arcaiques","summary":"Detecta formes etiquetades com a futur de subjuntiu, considerades arcaiques en l'ús general actual.","methodology":"Cerca etiquetes FreeLing que comencen per VSSF, VASF o VMSF, també a vaux-cat, excloent auxiliars.","limitations":"Depèn de l'etiquetatge de FreeLing/DiSeg i pot produir falsos positius o perdre construccions ambigües.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"archaic-verb-forms","implementation_version":"1.2","metric_title":"Eliminació de formes verbals arcaiques","category":"morphosyntax","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"connector-variety","kind":"suggestion","analysis_language":"ca","enabled":false,"genre_scope":null,"available":false,"availability_note":"No disponible en aquesta llengua: la detecció es basa en els marcadors discursius (disc_mk) que només produeix la gramàtica DiSeg de l'espanyol.","implementation_version":"1.2","category":"discourse","unit":null,"documentation_language":"ca","documentation":{"title":"Variació de connectors","summary":"Detecta connectors discursius repetits per sobre del llindar i ofereix alternatives de la mateixa relació.","methodology":"Compta nodes disc_mk de l'XML, en normalitza les formes i assenyala connectors del model amb freqüència superior a n_variacion_conectores. La detecció utilitza el catàleg editorial actiu per a l'idioma.","limitations":"Depèn de la cobertura i la qualitat del catàleg actiu per a l'idioma; cada coincidència requereix revisió contextual.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"connector-variety","implementation_version":"1.2","metric_title":"Variació de connectors","category":"discourse","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"definition-usage","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"lexical","unit":null,"documentation_language":"ca","documentation":{"title":"Ús de definicions","summary":"Compara el nombre d'indicadors de definició del text amb el valor de referència del gènere textual.","methodology":"Compta els marcadors de definició del text i els compara amb el valor de referència del gènere; el paràmetre de mode decideix si l'avís s'emet per excés o per defecte. La detecció utilitza el catàleg editorial actiu per a l'idioma.","limitations":"Depèn de la cobertura i la qualitat del catàleg actiu per a l'idioma; cada coincidència requereix revisió contextual.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"definition-usage","implementation_version":"1.2","metric_title":"Ús de definicions","category":"lexical","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"difficult-expressions","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"lexical","unit":null,"documentation_language":"ca","documentation":{"title":"Substitució d'expressions difícils d'entendre","summary":"Localitza expressions difícils d'entendre incloses al catàleg i retorna alternatives quan n'hi ha.","methodology":"Cerca expressions completes directament sobre el text, sense distingir majúscules ni accents i respectant límits de paraula. La detecció utilitza el catàleg editorial actiu per a l'idioma.","limitations":"Depèn de la cobertura i la qualitat del catàleg actiu per a l'idioma; cada coincidència requereix revisió contextual.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"difficult-expressions","implementation_version":"1.2","metric_title":"Substitució d'expressions difícils d'entendre","category":"lexical","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"gerunds","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"morphosyntax","unit":null,"documentation_language":"ca","documentation":{"title":"Revisió de gerundis","summary":"Localitza gerundis independents que convé revisar, excloent auxiliars i construccions compostes reconegudes.","methodology":"Usa etiquetes verbals de gerundi (VBG en EN) i atributs auxiliars per excloure perífrasis ja reconegudes.","limitations":"Depèn de l'etiquetatge de FreeLing/DiSeg i pot produir falsos positius o perdre construccions ambigües.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"gerunds","implementation_version":"1.2","metric_title":"Revisió de gerundis","category":"morphosyntax","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"imprecise-words","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"lexical","unit":null,"documentation_language":"ca","documentation":{"title":"Substitució de paraules poc precises","summary":"Localitza paraules o seqüències poc precises incloses al catàleg editable i n'ofereix alternatives.","methodology":"Normalitza els lemes dels tokens i cerca seqüències completes del catàleg actiu; retorna terme, alternativa i posicions de text quan estan disponibles. La detecció utilitza el catàleg editorial actiu per a l'idioma.","limitations":"Depèn de la cobertura i la qualitat del catàleg actiu per a l'idioma; cada coincidència requereix revisió contextual.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"imprecise-words","implementation_version":"1.2","metric_title":"Substitució de paraules poc precises","category":"lexical","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"list-usage","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"discourse","unit":null,"documentation_language":"ca","documentation":{"title":"Inclusió de llistes","summary":"Avisa, amb una única ocurrència de document, quan no s'ha reconegut cap llista estructurada al text.","methodology":"Retorna un únic suggeriment de document, sense posicions de text, quan has_list és fals; has_list s'obté del text i de l'HTML estructurat.","limitations":"Depèn de la segmentació del text pla i que els marcadors estructurals siguin recognoscibles; no implica per si sola un error de redacció.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"list-usage","implementation_version":"1.2","metric_title":"Inclusió de llistes","category":"discourse","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"long-paragraphs","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"discourse","unit":null,"documentation_language":"ca","documentation":{"title":"Revisió de paràgrafs llargs","summary":"Assenyala paràgrafs que superen el límit de paraules configurat per al gènere textual.","methodology":"Compara word_count de cada paràgraf amb n_palabras_por_parrafo del gènere; només informa valors estrictament superiors.","limitations":"Depèn de la segmentació del text pla i que els marcadors estructurals siguin recognoscibles; no implica per si sola un error de redacció.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"long-paragraphs","implementation_version":"1.2","metric_title":"Revisió de paràgrafs llargs","category":"discourse","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"long-segmented-sentences","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"discourse","unit":null,"documentation_language":"ca","documentation":{"title":"Divisió d'oracions llargues","summary":"Assenyala oracions llargues amb diversos segments i proposa punts estructurals on es podrien dividir.","methodology":"Selecciona oracions amb més de n_division_oraciones paraules i diversos segments; retorna segments, connectors i possibles límits de divisió.","limitations":"Depèn de la segmentació del text pla i que els marcadors estructurals siguin recognoscibles; no implica per si sola un error de redacció.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"long-segmented-sentences","implementation_version":"1.2","metric_title":"Divisió d'oracions llargues","category":"discourse","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"long-sentences","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"discourse","unit":null,"documentation_language":"ca","documentation":{"title":"Revisió d'oracions llargues","summary":"Assenyala oracions que superen el límit de paraules configurat per al gènere textual i, quan l'oració admet divisió, els punts on es podria partir.","methodology":"Selecciona oracions amb més de n_division_oraciones paraules; en les que tenen diversos segments retorna a més segments, connectors i possibles límits de divisió.","limitations":"Depèn de la segmentació del text pla i que els marcadors estructurals siguin recognoscibles; no implica per si sola un error de redacció.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"long-sentences","implementation_version":"1.2","metric_title":"Revisió d'oracions llargues","category":"discourse","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"long-unsegmented-sentences","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"discourse","unit":null,"documentation_language":"ca","documentation":{"title":"Revisió d'oracions llargues","summary":"Assenyala oracions llargues que DiSeg no ha dividit en segments interns.","methodology":"Selecciona oracions amb més de n_division_oraciones paraules i com a màxim un segment DiSeg.","limitations":"Depèn de la segmentació del text pla i que els marcadors estructurals siguin recognoscibles; no implica per si sola un error de redacció.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"long-unsegmented-sentences","implementation_version":"1.2","metric_title":"Revisió d'oracions llargues","category":"discourse","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"long-words","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"lexical","unit":null,"documentation_language":"ca","documentation":{"title":"Revisió de paraules llargues","summary":"Localitza paraules llargues incloses al catàleg editorial i proposa alternatives més breus quan n'hi ha.","methodology":"Normalitza els lemes dels tokens i cerca seqüències completes del catàleg actiu; retorna terme, alternativa i posicions de text quan estan disponibles. La detecció utilitza el catàleg editorial actiu per a l'idioma.","limitations":"Depèn de la cobertura i la qualitat del catàleg actiu per a l'idioma; cada coincidència requereix revisió contextual.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"long-words","implementation_version":"1.2","metric_title":"Revisió de paraules llargues","category":"lexical","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"missing-definitions","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"lexical","unit":null,"documentation_language":"ca","documentation":{"title":"Manca de definicions","summary":"Avisa quan el text no conté cap indicador de definició i el gènere textual acostuma a incloure definicions.","methodology":"Cerca marcadors de definició (un verb definitori al costat d'una paraula de contorn) i retorna un avís documental si el text no en conté cap. La detecció utilitza el catàleg editorial actiu per a l'idioma.","limitations":"Depèn de la cobertura i la qualitat del catàleg actiu per a l'idioma; cada coincidència requereix revisió contextual.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"missing-definitions","implementation_version":"1.2","metric_title":"Manca de definicions","category":"lexical","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"negative-formulations","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"morphosyntax","unit":null,"documentation_language":"ca","documentation":{"title":"Reformulació d'idees expressades en negatiu","summary":"Localitza paraules o seqüències negatives catalogades per afavorir formulacions afirmatives i directes.","methodology":"Normalitza els lemes dels tokens i cerca seqüències completes del catàleg actiu; retorna terme, alternativa i posicions de text quan estan disponibles. La detecció utilitza el catàleg editorial actiu per a l'idioma.","limitations":"Depèn de la cobertura i la qualitat del catàleg actiu per a l'idioma; cada coincidència requereix revisió contextual.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"negative-formulations","implementation_version":"1.2","metric_title":"Reformulació d'idees expressades en negatiu","category":"morphosyntax","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"paragraph-initial-connectors","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"discourse","unit":null,"documentation_language":"ca","documentation":{"title":"Introducció de connectors a l'inici de paràgrafs","summary":"Detecta paràgrafs que no comencen amb un connector discursiu reconegut.","methodology":"Descarta paràgrafs buits o amb has_initial_connector; per a la resta retorna el paràgraf i els grups de connectors editables. La detecció utilitza el catàleg editorial actiu per a l'idioma.","limitations":"Depèn de la cobertura i la qualitat del catàleg actiu per a l'idioma; cada coincidència requereix revisió contextual.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"paragraph-initial-connectors","implementation_version":"1.2","metric_title":"Introducció de connectors a l'inici de paràgrafs","category":"discourse","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"participles","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"morphosyntax","unit":null,"documentation_language":"ca","documentation":{"title":"Revisió de participis","summary":"Localitza participis independents i evita els que formen temps compostos o passives reconegudes.","methodology":"Usa etiquetes de participi (VBN en EN) i exclou auxiliars, temps compostos, passives i lemes auxiliars.","limitations":"Depèn de l'etiquetatge de FreeLing/DiSeg i pot produir falsos positius o perdre construccions ambigües.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"participles","implementation_version":"1.2","metric_title":"Revisió de participis","category":"morphosyntax","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"passive-voice","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"morphosyntax","unit":null,"documentation_language":"ca","documentation":{"title":"Ús de la veu passiva","summary":"Localitza construccions que l'anàlisi morfosintàctica identifica com a possibles veus passives.","methodology":"En ES/CA usa nodes verb_pass o ger_pas i, com a suport, seqüències ser/ésser + participi. En EN cerca be + VBN a vb_chunk i després als tokens.","limitations":"Depèn de l'etiquetatge de FreeLing/DiSeg i pot produir falsos positius o perdre construccions ambigües.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"passive-voice","implementation_version":"1.2","metric_title":"Ús de la veu passiva","category":"morphosyntax","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"redundant-expressions","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"lexical","unit":null,"documentation_language":"ca","documentation":{"title":"Eliminació d'expressions redundants","summary":"Localitza expressions redundants del catàleg per eliminar-les o reformular-les.","methodology":"Cerca expressions completes directament sobre el text, sense distingir majúscules ni accents i respectant límits de paraula. La detecció utilitza el catàleg editorial actiu per a l'idioma.","limitations":"Depèn de la cobertura i la qualitat del catàleg actiu per a l'idioma; cada coincidència requereix revisió contextual.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"redundant-expressions","implementation_version":"1.2","metric_title":"Eliminació d'expressions redundants","category":"lexical","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"single-sentence-paragraphs","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"discourse","unit":null,"documentation_language":"ca","documentation":{"title":"Revisió de paràgrafs-oració","summary":"Localitza paràgrafs formats per una sola oració per revisar si concentren massa informació o necessiten desenvolupament.","methodology":"Selecciona cada paràgraf no buit amb sentence_count exactament igual a 1.","limitations":"Depèn de la segmentació del text pla i que els marcadors estructurals siguin recognoscibles; no implica per si sola un error de redacció.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"single-sentence-paragraphs","implementation_version":"1.2","metric_title":"Revisió de paràgrafs-oració","category":"discourse","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"subjectivity-markers","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"lexical","unit":null,"documentation_language":"ca","documentation":{"title":"Ús d'indicadors de subjectivitat","summary":"Combina lèxic, seqüències, categories morfològiques i exclamacions per localitzar possibles marques de subjectivitat.","methodology":"Uneix coincidències de lemes simples, seqüències compostes, categories morfològiques configurades i fragments entre signes d'exclamació; després elimina duplicats.","limitations":"Depèn de la cobertura i la qualitat del catàleg actiu per a l'idioma; cada coincidència requereix revisió contextual.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"subjectivity-markers","implementation_version":"1.2","metric_title":"Ús d'indicadors de subjectivitat","category":"lexical","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"transparent-terms","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"lexical","unit":null,"documentation_language":"ca","documentation":{"title":"Utilització de termes més transparents","summary":"Detecta termes difícils catalogats i proposa denominacions més transparents.","methodology":"Normalitza els lemes dels tokens i cerca seqüències completes del catàleg actiu; retorna terme, alternativa i posicions de text quan estan disponibles. La detecció utilitza el catàleg editorial actiu per a l'idioma.","limitations":"Depèn de la cobertura i la qualitat del catàleg actiu per a l'idioma; cada coincidència requereix revisió contextual.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"transparent-terms","implementation_version":"1.2","metric_title":"Utilització de termes més transparents","category":"lexical","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"verb-person-consistency","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"morphosyntax","unit":null,"documentation_language":"ca","documentation":{"title":"Sistematicitat en l'ús de verbs","summary":"Avisa quan conviuen verbs en primera persona singular i plural al mateix document.","methodology":"Extreu persona i nombre de les etiquetes verbals; només genera resultat si troba almenys una forma 1S i una 1P.","limitations":"Depèn de l'etiquetatge de FreeLing/DiSeg i pot produir falsos positius o perdre construccions ambigües.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"verb-person-consistency","implementation_version":"1.2","metric_title":"Sistematicitat en l'ús de verbs","category":"morphosyntax","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"verbal-nominalizations","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"morphosyntax","unit":null,"documentation_language":"ca","documentation":{"title":"Revisió de nominalitzacions verbals","summary":"Detecta substantius amb patrons productius de nominalització verbal i exclou les excepcions catalogades.","methodology":"Filtra substantius en minúscula: -ción/-ciones en ES, -ció/-cions en CA i -tion/-tions en EN; elimina entrades del catàleg d'excepcions.","limitations":"Depèn de l'etiquetatge de FreeLing/DiSeg i pot produir falsos positius o perdre construccions ambigües.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"verbal-nominalizations","implementation_version":"1.2","metric_title":"Revisió de nominalitzacions verbals","category":"morphosyntax","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}},{"id":"word-repetition","kind":"suggestion","analysis_language":"ca","enabled":true,"genre_scope":null,"available":true,"availability_note":null,"implementation_version":"1.2","category":"lexical","unit":null,"documentation_language":"ca","documentation":{"title":"Repetició de paraules","summary":"Assenyala les paraules amb contingut lèxic que es repeteixen al text per sobre del llindar configurat per al gènere.","methodology":"Compta quantes vegades apareix cada lema, descartant els lemes auxiliars i copulatius, i assenyala els lemes de nom, adjectiu, adverbi o verb amb una freqüència superior al llindar del gènere.","limitations":"És un senyal de revisió, no una correcció automàtica ni una avaluació completa de la qualitat del text.","interpretation":"Cada element d'`occurrences` identifica un fragment afectat. `start` és inclusiu i `end` exclusiu, tots dos mesurats en punts de codi Unicode sobre el text enviat. `replacement`, `alternatives` i `edits` només contenen valors quan hi ha un canvi segur; l'absència del suggeriment significa que no hi ha coincidències, no que el text sigui necessàriament correcte."},"references":[],"example":{"id":"sug_1","metric_id":"word-repetition","implementation_version":"1.2","metric_title":"Repetició de paraules","category":"lexical","severity":"warning","summary":"Example detection returned by this metric.","explanation":null,"recommendations":["Review the detected fragment in context."],"examples":null,"occurrences":[{"id":"occ_1","text":"example","paragraph_index":0,"sentence_index":0,"start":18,"end":25,"replacement":null,"alternatives":[],"edits":[]}]}}],"x-artext-guides":{"language":"ca","examples":{"curl":"# Desa la clau fora del codi i carrega-la des de l’entorn.\n# Requereix curl i jq.\n# export ARTEXT_API_KEY='art_live_...'\nset -euo pipefail\nAPI_BASE='http://uned.tail9cc3dd.ts.net'\nIDEMPOTENCY_KEY=\"report-$(date +%s)-$RANDOM\"\nheaders_file=$(mktemp)\ntrap 'rm -f \"$headers_file\"' EXIT\n\n# Crea l’informe una sola vegada. Idempotency-Key permet repetir el POST amb seguretat després d’un error de xarxa.\ncreated=$(curl --fail-with-body --silent --show-error --dump-header \"$headers_file\" \\\n  --request POST \"$API_BASE/v1/reports\" \\\n  --header \"Authorization: Bearer $ARTEXT_API_KEY\" \\\n  --header \"Idempotency-Key: $IDEMPOTENCY_KEY\" \\\n  --header 'Content-Type: application/json' \\\n  --data-binary '{\"language\":\"ca\",\"domain_slug\":\"llenguatge-clar\",\"text_type_slug\":\"text-juridic-administratiu-dirigit-a-la-ciutadania\",\"text\":\"En el dia d’avui es durà a terme la revisió de la sol·licitud.\",\"external_id\":\"document-123\"}')\n\n# status_url és relatiu: resol-lo contra API_BASE.\nstatus_url=\"$API_BASE$(jq -r '.status_url' <<<\"$created\")\"\nretry_after=$(awk 'BEGIN { IGNORECASE=1 } /^Retry-After:/ { gsub(\"\\r\", \"\", $2); print $2 }' \"$headers_file\" | tail -1)\nretry_after=${retry_after:-2}\n\n# Consulta el mateix informe respectant Retry-After i amb un límit total.\nfor attempt in $(seq 1 90); do\n  sleep \"$retry_after\"\n  report=$(curl --fail-with-body --silent --show-error --dump-header \"$headers_file\" \\\n    --header \"Authorization: Bearer $ARTEXT_API_KEY\" \\\n    \"$status_url\")\n  status=$(jq -r '.status' <<<\"$report\")\n  case \"$status\" in\n    completed) break ;;\n    failed) jq -r '.error.message // \"Analysis failed\"' <<<\"$report\" >&2; exit 1 ;;\n    queued|running)\n      retry_after=$(awk 'BEGIN { IGNORECASE=1 } /^Retry-After:/ { gsub(\"\\r\", \"\", $2); print $2 }' \"$headers_file\" | tail -1)\n      retry_after=${retry_after:-2}\n      ;;\n    *) echo \"Unknown status: $status\" >&2; exit 1 ;;\n  esac\ndone\n\n# Processa el resultat només després de completed.\ntest \"$status\" = completed || { echo 'Polling timed out' >&2; exit 1; }\njq '.result.measurements, .result.suggestions' <<<\"$report\"","python":"import os\nimport time\nimport uuid\nfrom urllib.parse import urljoin\n\nimport requests\n\n# Desa la clau fora del codi i carrega-la des de l’entorn.\nAPI_BASE = 'http://uned.tail9cc3dd.ts.net'\nAPI_KEY = os.environ[\"ARTEXT_API_KEY\"]\nHEADERS = {\"Authorization\": f\"Bearer {API_KEY}\"}\npayload = {'language': 'ca', 'domain_slug': 'llenguatge-clar', 'text_type_slug': 'text-juridic-administratiu-dirigit-a-la-ciutadania', 'text': 'En el dia d’avui es durà a terme la revisió de la sol·licitud.', 'external_id': 'document-123'}\n\n# Crea l’informe una sola vegada. Idempotency-Key permet repetir el POST amb seguretat després d’un error de xarxa.\nresponse = requests.post(\n    f\"{API_BASE}/v1/reports\",\n    headers={**HEADERS, \"Idempotency-Key\": str(uuid.uuid4())},\n    json=payload,\n    timeout=30,\n)\nresponse.raise_for_status()\ncreated = response.json()\n# status_url és relatiu: resol-lo contra API_BASE.\nstatus_url = urljoin(f\"{API_BASE}/\", created[\"status_url\"])\nretry_after = int(response.headers.get(\"Retry-After\", \"2\"))\n\n# Consulta el mateix informe respectant Retry-After i amb un límit total.\ndeadline = time.monotonic() + 180\nwhile True:\n    time.sleep(retry_after)\n    response = requests.get(status_url, headers=HEADERS, timeout=30)\n    retry_after = int(response.headers.get(\"Retry-After\", \"2\"))\n    if response.status_code == 429:\n        continue\n    response.raise_for_status()\n    report = response.json()\n    status = report[\"status\"]\n    if status == \"completed\":\n        break\n    if status == \"failed\":\n        raise RuntimeError((report.get(\"error\") or {}).get(\"message\") or \"Analysis failed\")\n    if status not in {\"queued\", \"running\"}:\n        raise RuntimeError(f\"Unknown report status: {status}\")\n    if time.monotonic() >= deadline:\n        raise TimeoutError(\"Report polling timed out\")\n\n# Processa el resultat només després de completed.\nresult = report[\"result\"]\nfor measurement in result[\"measurements\"]:\n    print(measurement[\"metric_id\"], measurement[\"value\"], measurement[\"unit\"])\nfor index, suggestion in enumerate(result[\"suggestions\"]):\n    print(index, suggestion[\"metric_id\"], len(suggestion[\"occurrences\"]))","javascript":"// Node.js 18+. Executa aquest codi al servidor; no exposis mai la clau al navegador.\nconst API_BASE = \"http://uned.tail9cc3dd.ts.net\";\nconst API_KEY = process.env.ARTEXT_API_KEY;\nif (!API_KEY) throw new Error(\"ARTEXT_API_KEY is required\");\n\nconst headers = {\n  \"Authorization\": `Bearer ${API_KEY}`,\n  \"Content-Type\": \"application/json\"\n};\nconst api = async (path, options = {}) => {\n  const response = await fetch(new URL(path, `${API_BASE}/`), {\n    ...options,\n    headers: { ...headers, ...options.headers },\n    signal: AbortSignal.timeout(30_000)\n  });\n  if (!response.ok && response.status !== 429) {\n    throw new Error(`${response.status}: ${await response.text()}`);\n  }\n  return response;\n};\nconst delay = (milliseconds) =>\n  new Promise((resolve) => setTimeout(resolve, milliseconds));\n\n// Crea l’informe una sola vegada. Idempotency-Key permet repetir el POST amb seguretat després d’un error de xarxa.\nconst createdResponse = await api(\"v1/reports\", {\n  method: \"POST\",\n  headers: { \"Idempotency-Key\": crypto.randomUUID() },\n  body: JSON.stringify({\"language\":\"ca\",\"domain_slug\":\"llenguatge-clar\",\"text_type_slug\":\"text-juridic-administratiu-dirigit-a-la-ciutadania\",\"text\":\"En el dia d’avui es durà a terme la revisió de la sol·licitud.\",\"external_id\":\"document-123\"})\n});\nconst created = await createdResponse.json();\nconst deadline = Date.now() + 180_000;\nlet retryAfter = Number(createdResponse.headers.get(\"Retry-After\") || 2);\nlet report;\n\n// Consulta el mateix informe respectant Retry-After i amb un límit total.\nwhile (Date.now() < deadline) {\n  await delay(retryAfter * 1_000);\n  const statusResponse = await api(created.status_url);\n  retryAfter = Number(statusResponse.headers.get(\"Retry-After\") || 2);\n  if (statusResponse.status === 429) continue;\n  report = await statusResponse.json();\n  if (report.status === \"completed\") break;\n  if (report.status === \"failed\") {\n    throw new Error(report.error?.message || \"Analysis failed\");\n  }\n  if (![\"queued\", \"running\"].includes(report.status)) {\n    throw new Error(`Unknown report status: ${report.status}`);\n  }\n}\nif (report?.status !== \"completed\") {\n  throw new Error(\"Report polling timed out\");\n}\n\n// Processa el resultat només després de completed.\nfor (const item of report.result.measurements) {\n  console.log(item.metric_id, item.value, item.unit);\n}\nfor (const [index, item] of report.result.suggestions.entries()) {\n  console.log(index, item.metric_id, item.occurrences.length);\n}"},"sdk":{"python":"# Instal·la el client oficial: pip install artext\n# Executa aquest codi al servidor; no exposis mai la clau al navegador.\nimport os\n\nfrom artext import Artext\n\nclient = Artext(\n    api_key=os.environ[\"ARTEXT_API_KEY\"],\n    base_url=\"http://uned.tail9cc3dd.ts.net\",\n)\n\n# analyze crea l'informe, espera respectant Retry-After i retorna el resultat.\n# Una anàlisi fallida llança una excepció amb el detall de l'error.\nreport = client.analyze(\n    \"En el dia d’avui es durà a terme la revisió de la sol·licitud.\",\n    language=\"ca\",\n    domain_slug=\"llenguatge-clar\",\n    text_type_slug=\"text-juridic-administratiu-dirigit-a-la-ciutadania\",\n)\n\nprint(report.result.measurement(\"word-count\").value)\nfor suggestion in report.result.suggestions:\n    print(suggestion.metric_id, suggestion.summary)\n    for occurrence in suggestion.occurrences:\n        print(\"  \", occurrence.text, \"->\", occurrence.replacement)\n","javascript":"// Instal·la el client oficial: npm install artext\n// Executa aquest codi al servidor; no exposis mai la clau al navegador.\nimport { Artext } from \"artext\";\n\nconst client = new Artext({\n  apiKey: process.env.ARTEXT_API_KEY,\n  baseUrl: \"http://uned.tail9cc3dd.ts.net\",\n});\n\n// analyze crea l'informe, espera respectant Retry-After i retorna el resultat.\n// Una anàlisi fallida llança una excepció amb el detall de l'error.\nconst report = await client.analyze({\n  text: \"En el dia d’avui es durà a terme la revisió de la sol·licitud.\",\n  language: \"ca\",\n  domainSlug: \"llenguatge-clar\",\n  textTypeSlug: \"text-juridic-administratiu-dirigit-a-la-ciutadania\",\n});\n\nfor (const suggestion of report.result.suggestions) {\n  console.log(suggestion.metric_id, suggestion.summary);\n  for (const occurrence of suggestion.occurrences) {\n    console.log(\"  \", occurrence.text, \"->\", occurrence.replacement);\n  }\n}\n"},"request":{"language":"ca","domain_slug":"llenguatge-clar","text_type_slug":"text-juridic-administratiu-dirigit-a-la-ciutadania","text":"En el dia d’avui es durà a terme la revisió de la sol·licitud.","external_id":"document-123"},"responses":{"queued":{"report_id":"rep_7f12a4c8","external_id":"document-123","status":"queued","status_url":"/v1/reports/rep_7f12a4c8","events_url":"/v1/reports/rep_7f12a4c8/events"},"completed":{"report_id":"rep_7f12a4c8","external_id":"document-123","status":"completed","position_in_queue":null,"result":{"schema_version":"1.0","offset_unit":"unicode_code_points","language":"ca","genre":{"domain":{"slug":"llenguatge-clar","name":"Llenguatge clar"},"text_type":{"slug":"text-juridic-administratiu-dirigit-a-la-ciutadania","name":"Text juridicoadministratiu dirigit a la ciutadania"}},"measurements":[{"metric_id":"word-count","value":12,"unit":"words","implementation_version":"1.0"}],"suggestions":[{"id":"sug_1","metric_id":"redundant-expressions","implementation_version":"1.0","metric_title":"Eliminació d’expressions redundants","category":"lexical","severity":"warning","summary":"Convé formular el fragment d’una manera més directa.","explanation":null,"occurrences":[{"id":"occ_1","text":"En el dia d’avui","paragraph_index":0,"sentence_index":0,"start":0,"end":16,"replacement":null,"alternatives":[],"edits":[{"start":0,"end":16,"text":""}]}],"recommendations":["Elimina l’expressió si el context ho permet."]}]},"error":null},"failed":{"report_id":"rep_7f12a4c8","external_id":"document-123","status":"failed","position_in_queue":null,"result":null,"error":{"code":"analysis_failed","message":"The analysis could not be completed."}}}}}