Documents
Send a letter, a form or a piece of text into a case to be translated, and read the translation back into your own system.
This page is for the developer who sends letters, forms and other text from your system to be translated.
It covers sending a file or a piece of text into a case, and reading the document and its translation back.
Calls go to https://app.inmywords.chat/api/integrations/v1/, and every request carries Authorization: Bearer imw_<64 hex characters>, the key of a connection your organisation has made. To send a document the connection needs documents:write; to read it and its translation, it needs documents:read.
A document is sent into a case and translated into one language. When it has been translated, the document.translated webhook event is sent.
- Document translation must be on as well. It has to be switched on for your organisation, as well as integrations. When it is off, sending a document answers 403
module_off. A document already sent can still be read. - You read back only what you sent. Only documents sent through the API can be read through it. A document sent from the InMyWords screens answers 404.
- You see only your own organisation's documents. A document of another organisation answers 404, the same as one that does not exist.
- Translation is billed as usual. It is billed to your organisation, as it is when a document is sent from the screens.
Ids are strings of digits, such as "57". Times are ISO 8601 in UTC. Field names are snake_case.
Endpoints
| Method | Path | Scope |
|---|---|---|
| POST | /documents | documents:write |
| GET | /documents/{id} | documents:read |
What a document holds
| Field | Type | Meaning |
|---|---|---|
id | string | The document's id |
case_id | string | The case it was sent into |
file_name | string | The name of the file you sent |
status | string | queued, translating, waiting, translated or failed |
source_language | string or null | The language code it was written in; null until it has been read |
target_language | string or null | The language code it is translated into; null if none is recorded |
created_at | string | When it was sent |
translated_at | string or null | When it was translated; null until then |
blocks | array or null | The translated text; null until status is translated |
A document starts as queued, which means it has not been read yet. It moves to translating once it has been read and is being translated.
waiting means the document is over your organisation's word limit. A person must choose its sections in InMyWords before it is translated.
failed is final. To try again, send the document again.
How the translation comes back
| Field | Type | Meaning |
|---|---|---|
type | string | heading, paragraph, list_item or table_cell |
text | string | The translated text |
level | integer | For a heading or a list item only: its level, from 1 |
Blocks come in the document's own order. A table arrives as its cells, one block each, row by row.
Send a document
Send a multipart form, or a JSON body for text, with these fields.
| Field | Required | Meaning |
|---|---|---|
case_id | yes | The case to send it into |
file | one of file or text | The document, in a multipart form |
text | one of file or text | The words to translate, as a string, in a JSON body or a form field |
target_language | yes | The language code to translate it into |
- A file or text, not both. Text is translated just as a document is: in the background, read back with
GET /documents/{id}, and announced by thedocument.translatedwebhook. Itsfile_nameispasted.txt. - Size limits. A file can be up to 20 MB, and text up to 400,000 characters. Send longer text as a
.txtfile. - File types. Plain text (
.txt), Markdown (.md), Word (.docx) and OpenDocument (.odt). PDF, JPEG, PNG and HEIC as well, where reading by the model is switched on for your organisation. - Retrying safely. Send an
Idempotency-Keyheader, up to 255 characters. The same key with the same body within 24 hours answers the first result. The same key with a different body answers 422idempotency_key_reused.
The answer is 202, with the document in status queued.
curl -X POST https://app.inmywords.chat/api/integrations/v1/documents \
-H "Authorization: Bearer imw_3f9c..." \
-H "Idempotency-Key: 0c7e-doc-1207-notice" \
-F case_id=1207 \
-F target_language=so \
-F [email protected]
curl -X POST https://app.inmywords.chat/api/integrations/v1/documents \
-H "Authorization: Bearer imw_3f9c..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 0c7e-text-1207-1" \
-d '{"case_id": "1207", "target_language": "so", "text": "Your appointment is on Tuesday at 10am."}'
{
"data": {
"id": "1054",
"case_id": "1207",
"file_name": "notice.pdf",
"status": "queued",
"source_language": null,
"target_language": "so",
"created_at": "2026-10-02T10:05:12Z",
"translated_at": null,
"blocks": null
}
}
Read a document
curl https://app.inmywords.chat/api/integrations/v1/documents/1054 \
-H "Authorization: Bearer imw_3f9c..."
{
"data": {
"id": "1054",
"case_id": "1207",
"file_name": "notice.pdf",
"status": "translated",
"source_language": "en",
"target_language": "so",
"created_at": "2026-10-02T10:05:12Z",
"translated_at": "2026-10-02T10:06:40Z",
"blocks": [
{"type": "heading", "text": "Ogeysiis", "level": 1},
{"type": "paragraph", "text": "Waxaa lagaa codsanayaa inaad ka guurto hantida."},
{"type": "list_item", "text": "Taariikhda: 28 Oktoobar 2026", "level": 1},
{"type": "table_cell", "text": "Kirada"},
{"type": "table_cell", "text": "GBP 650"}
]
}
}
When something goes wrong
Every error comes back as {"error": {"code": "...", "message": "..."}} with the HTTP status.
| Status | Code | When |
|---|---|---|
| 401 | unauthorised | The key is missing, malformed or revoked |
| 403 | module_off | Integrations are not switched on for your organisation, or, when sending, document translation is not |
| 403 | scope_missing | The connection does not hold the scope |
| 404 | not_found | No such document or case, or one of another organisation |
| 413 | file_too_large | The file is over 20 MB |
| 413 | text_too_long | The text is over 400,000 characters |
| 415 | file_type_not_supported | The file is not a type your organisation can send |
| 422 | validation_failed | A field is missing or not valid, such as an unknown language code |
| 422 | idempotency_key_reused | The Idempotency-Key was used with a different body |
| 429 | rate_limited | Too many calls this minute; wait the seconds in Retry-After |
{"error": {"code": "validation_failed", "message": "target_language is not a language this organisation translates into."}}