{"openapi":"3.0.1","info":{"title":"Transkribus API","description":"The API accepts single images as base64-encoded string or by http(s) URLs in a `POST` request and turns them into structured text using Transkribus text recognition technology. Each job's response includes a `processId` that can be used to poll its status and retrieve the result.<br/><br/>You can apply any of your models trained in Transkribus as well as all public models by setting its `htrId` in the `JobConfig` section of the initial `POST` request. A list of public models including their ID can be found on the [Transkribus website](https://www.transkribus.org/models).<br/><br/>The API accepts the image MIME-types `image/jpeg`, `image/tiff` and `image/png` and file sizes up to 20 megabyte.","termsOfService":"https://readcoop.eu/terms-and-conditions/","contact":{"email":"help@transkribus.org"},"version":"2.0.0"},"servers":[{"url":"https://api-staging.transkribus.org","description":"Current server"}],"x-tagGroups":[{"name":"Files and documents","tags":["files-overview","export"]},{"name":"Processing","tags":["jobs","images","Transkribus API","layout","tables","fields","training"]},{"name":"Models","tags":["models-overview","model-types"]},{"name":"Platform","tags":["platform-overview","Authentication"]}],"tags":[{"name":"Authentication","description":"The Transkribus API uses the OpenID Connect protocol for authentication. Obtain an access token and include it as a Bearer token in all API requests.\n\nOpenID Connect configuration: https://account.readcoop.eu/auth/realms/readcoop/.well-known/openid-configuration\n\n## 1. Get an access token\n\nReplace `$USERNAME` and `$PASSWORD` with your Transkribus credentials.\n\n```bash\ncurl -X POST https://account.readcoop.eu/auth/realms/readcoop/protocol/openid-connect/token \\\n  -H 'Content-Type: application/x-www-form-urlencoded' \\\n  --data-urlencode grant_type=password \\\n  --data-urlencode client_id=processing-api-client \\\n  --data-urlencode username=$USERNAME \\\n  --data-urlencode password=$PASSWORD\n```\n\nUse the `access_token` from the response as the Bearer token in subsequent requests.\n\n## 2. Refresh the access token\n\nUse the `refresh_token` from the previous response to obtain a new access token without re-entering your credentials.\n\n```bash\ncurl -X POST https://account.readcoop.eu/auth/realms/readcoop/protocol/openid-connect/token \\\n  -H 'Content-Type: application/x-www-form-urlencoded' \\\n  --data-urlencode grant_type=refresh_token \\\n  --data-urlencode client_id=processing-api-client \\\n  --data-urlencode refresh_token=$REFRESH_TOKEN\n```\n\n## 3. End the session\n\nLog out and invalidate the refresh token.\n\n```bash\ncurl -X POST https://account.readcoop.eu/auth/realms/readcoop/protocol/openid-connect/logout \\\n  -H 'Content-Type: application/x-www-form-urlencoded' \\\n  --data-urlencode client_id=processing-api-client \\\n  --data-urlencode refresh_token=$REFRESH_TOKEN\n```"},{"name":"files-overview","x-displayName":"Overview","description":"Everything in this group works in the Transkribus app; API surfaces are announced in the changelog as they ship. This section covers how material organises into documents, collections and projects, and getting results back out. Images for processing travel inside job requests; see [Images](#tag/images) under Processing."},{"name":"models-overview","x-displayName":"Overview","description":"A model is what a processing job runs with. Every job that recognises, detects or extracts takes a model ID. This section explains the model families, which jobs they serve, and how to find model IDs. Models you train yourself in Transkribus are addressed exactly like public ones.\n\nYou can apply any of your own models as well as all public models by setting the model's `htrId` in the `config` section of the request. A list of public models including their IDs is on the [Transkribus website](https://www.transkribus.org/models)."},{"name":"platform-overview","x-displayName":"Overview","description":"Cross-cutting concerns: authentication, the legacy endpoints, and the changelog where every new API surface is announced."},{"name":"jobs","x-displayName":"Overview: how jobs work","description":"Processing is where work happens: every capability here is an asynchronous **job** that consumes credits and follows the contract on this page, regardless of type.\n\n## Lifecycle\n\nA job moves through these statuses:\n\n| Status | Meaning |\n|---|---|\n| `CREATED` | The job was accepted and registered. |\n| `WAITING` | The job is queued and waiting for a worker. |\n| `RUNNING` | The job is being processed. |\n| `FINISHED` | Terminal: the result is ready for download. |\n| `FAILED` | Terminal: processing failed; see the error message. |\n| `CANCELLED` | Terminal: the job was cancelled. |\n\n## Tracking a job\n\n- **Poll**: `GET /v2/processes/{processId}` returns the current status immediately; call it on an interval until the status is terminal.\n- **Longpoll**: `GET /v2/processes/longpoll/{processId}` waits until the status changes, then returns. Repeat on `408` timeout. The `longpoll` link disappears from the response once the job is terminal; its absence is the signal to stop.\n\n## Links\n\nEvery job response carries HATEOAS `links`. Use the `rel` field, not `title`, as the stable machine-readable identifier; titles are display text and may change.\n\n## Errors\n\nErrors are reported as JSON with `statusCode`, `reasonPhrase` and `message`. `400` malformed request, `401` missing/expired token, `404` unknown ID or referenced entity, `408` longpoll timeout (repeat the request), `429` processing volume depleted or account limit reached.\n\nPer-type sections describe only what is specific to that job type and do not restate this contract."},{"name":"Transkribus API","x-displayName":"Recognise text","description":"## How to process a document\n\n1. **Submit**: `POST /v2/processes` with your image and HTR model ID. The response contains a `processId` and HATEOAS links.\n2. **Check status**: Two options:\n   - `GET /v2/processes/{processId}` returns the current status immediately. Poll this on an interval until the status is `FINISHED`, `FAILED`, or `CANCELLED`.\n   - `GET /v2/processes/longpoll/{processId}` waits until the status changes, then returns. Repeat on 408 timeout. The `longpoll` link in the response disappears once the job is terminal; its absence is the signal to stop.\n3. **Download**: Once finished, retrieve results via:\n   - `GET /v2/processes/{processId}/result`: ZIP archive\n   - `GET /v2/processes/{processId}/page`: PAGE XML\n\n> **Tip:** Use the `rel` field of HATEOAS links as the stable identifier, not `title`. Link titles are display text and may change.\n\n```javascript\n// 1. Submit a job\nconst imageBase64 = '<base64-encoded-image>';\nconst createRes = await fetch('https://api-staging.transkribus.org/v2/processes', {\n  method: 'POST',\n  headers: { 'Authorization': 'Bearer <token>', 'Content-Type': 'application/json' },\n  body: JSON.stringify({ config: { textRecognition: { htrId: 38230 } }, image: { base64: imageBase64 } })\n});\nlet job = await createRes.json();\nconst { processId } = job;\n\n// 2a. Option A, plain polling: call the status endpoint on an interval\nconst POLL_INTERVAL_MS = 5000;\nconst TERMINAL = new Set(['FINISHED', 'FAILED', 'CANCELLED']);\nwhile (!TERMINAL.has(job.status)) {\n  await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL_MS));\n  job = await fetch(`https://api-staging.transkribus.org/v2/processes/${processId}`, {\n    headers: { 'Authorization': 'Bearer <token>' }\n  }).then(r => r.json());\n}\n\n// 2b. Option B, longpoll: follow the longpoll link, which waits until the status changes.\n//     The link disappears once the job reaches a terminal state.\nlet longpollLink = job.links.find(l => l.rel === 'longpoll');\nwhile (longpollLink) {\n  job = await fetch(longpollLink.href, {\n    headers: { 'Authorization': 'Bearer <token>' }\n  }).then(r => r.json());\n  longpollLink = job.links.find(l => l.rel === 'longpoll');\n}\n\n// 3. Job is terminal. Follow the result link if present (only on FINISHED)\nconst resultLink = job.links.find(l => l.rel === 'result');\nif (resultLink) {\n  const result = await fetch(resultLink.href, { headers: { 'Authorization': 'Bearer <token>' } });\n  console.log(await result.json());\n}\n```"},{"name":"images","x-displayName":"Images","description":"Jobs take a single image directly in the request. JPEG, PNG and TIFF are supported, up to 20 MB per image, one image per job.\n\nSend it as a base64-encoded string or as a public http(s) URL: base64 for local files and privacy, URL when the image is already hosted somewhere. See the `Image` schema and `POST /v2/processes`.\n\nThe image is used for that job only and is not stored. Persistent file storage works in the Transkribus app and its API surface is announced in the changelog when it ships."},{"name":"model-types","x-displayName":"Model types","description":"A model is what a processing job runs with. Every job that recognises, detects or extracts takes a model ID. The model families below are what those IDs refer to.\n\n## Text recognition models\n\nTwo families perform text recognition, and which you pick matters more than any parameter.\n\n**Super models** are large general-purpose models that work across many hands, languages and centuries without any training. Text Titan II is the current one. Use these when you have mixed or unfamiliar material, or when you have no ground truth. They are the right default.\n\n**PyLaia models** are small, fast models trained on a specific hand, collection or script. They decode in a single pass, which makes them considerably cheaper at volume, and a well-trained one will beat a general model on the material it was trained for. Use these when you have a large homogeneous collection and either an existing public model that fits it or enough ground truth to train your own.\n\nBoth are addressed the same way, by model ID (`htrId` in the job config). Model IDs come from the [public models list](https://www.transkribus.org/models) or from your own models in the Transkribus app.\n\n## Layout models\n\nLayout models produce baselines, regions and reading order. The API currently exposes them only inside text recognition jobs, through the `config.lineDetection` parameters; the field name is historical, the models are layout models. See [Layout](#tag/layout)."},{"name":"layout","x-displayName":"Analyse layout","description":"A layout job detects the structure of a page: text regions, baselines, line segmentation and reading order. Layout models produce this geometry independently of transcription.\n\nLayout works in Transkribus today as Layout Analysis. Via the API, layout models are currently exposed only inside text recognition jobs, through the `config.lineDetection` parameters.\n\nA standalone layout job surface is not yet exposed on the API. It will be announced in the changelog when it is."},{"name":"tables","x-displayName":"Recognise tables","description":"A table job detects table structure on a page and returns cells with their row and column positions, so tabular material comes back as data rather than as a flat sequence of lines.\n\nTable recognition works in Transkribus today.\n\nThe API surface is not yet exposed. It will be announced in the changelog when it is."},{"name":"fields","x-displayName":"Extract fields","description":"Fields detects regions of a page against a template you define once (its capability is segmentation) and returns those regions filled for every page of the same type. Suited to registers, forms and record series where the layout repeats.\n\nFields works in Transkribus today.\n\nThe API surface is not yet exposed. It will be announced in the changelog when it is."},{"name":"training","x-displayName":"Train models","description":"Model training trains a model from ground-truth material and registers the result so it can be used by ID like any other model.\n\nTraining works in Transkribus today.\n\nThe API surface is not yet exposed. It will be announced in the changelog when it is."},{"name":"export","x-displayName":"Export documents","description":"Export produces a downloadable artifact from recognized documents. Format is a parameter, not a separate job type: PAGE XML, ALTO, plain text, DOCX and others are the same export with a different value.\n\nExport works in Transkribus today.\n\nThe API surface is not yet exposed. It will be announced in the changelog when it is."}],"security":[{"bearerAuth":[]}],"paths":{"/v2/processes":{"post":{"tags":["Transkribus API"],"summary":"Submit a text recognition job for a single image (base64 or URL)","operationId":"startProcessing","x-codeSamples":[{"lang":"shell","label":"curl","source":"curl -X POST https://api-staging.transkribus.org/v2/processes \\\n  -H \"Authorization: Bearer $ACCESS_TOKEN\" \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"config\": { \"type\": \"e2eRecognition\", \"provider\": \"donut\", \"modelId\": 607929 },\n    \"image\": { \"imageUrl\": \"https://example.org/scan.jpg\" }\n  }'"},{"lang":"python","label":"Python","source":"import requests\n\nresp = requests.post(\n    \"https://api-staging.transkribus.org/v2/processes\",\n    headers={\"Authorization\": f\"Bearer {access_token}\"},\n    json={\n        \"config\": {\"type\": \"e2eRecognition\", \"provider\": \"donut\", \"modelId\": 607929},\n        \"image\": {\"imageUrl\": \"https://example.org/scan.jpg\"},\n    },\n)\nresp.raise_for_status()\nprocess_id = resp.json()[\"processId\"]"},{"lang":"javascript","label":"JavaScript","source":"const res = await fetch('https://api-staging.transkribus.org/v2/processes', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer ' + accessToken,\n    'Content-Type': 'application/json'\n  },\n  body: JSON.stringify({\n    config: { type: 'e2eRecognition', provider: 'donut', modelId: 607929 },\n    image: { imageUrl: 'https://example.org/scan.jpg' }\n  })\n});\nconst { processId } = await res.json();"}],"requestBody":{"description":"The image, the job configuration and optional layout information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessingRequestRepresentation"},"examples":{"base64Image":{"summary":"Image as base64","description":"Provide the image as a base64-encoded string.","value":{"config":{"type":"e2eRecognition","provider":"donut","modelId":607929},"image":{"base64":"/9j/4AAQSkZJRgABAQEASABIAAD..."}}},"urlImage":{"summary":"Image by URL","description":"Provide a URL to a publicly reachable image file instead of embedding the data.","value":{"config":{"type":"e2eRecognition","provider":"donut","modelId":607929},"image":{"imageUrl":"https://example.org/scan.jpg"}}}}}},"required":true},"responses":{"200":{"description":"The request was accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessingResponseRepresentation"},"example":{"processId":47725,"status":"CREATED","links":[{"rel":"status","href":"https://api-staging.transkribus.org/v2/processes/01927669-f207-7550-ba9f-05a14a5cb899","title":"Status"},{"rel":"longpoll","href":"https://api-staging.transkribus.org/v2/processes/longpoll/01927669-f207-7550-ba9f-05a14a5cb899","title":"Status Longpoll"},{"rel":"create","href":"https://api-staging.transkribus.org/v2/processes","title":"Create Job","method":"POST"}]}}},"links":{"PollStatus":{"operationId":"getProcessingStatus","parameters":{"processId":"$response.body#/processId"},"description":"Use the `processId` from the response to check job status."},"LongPollStatus":{"operationId":"longPollProcessingStatus","parameters":{"processId":"$response.body#/processId"},"description":"Long-poll for status waits until the job reaches a terminal state. Repeat on 408 timeout."},"DownloadResultArchive":{"operationId":"getProcessingResultArchive","parameters":{"processId":"$response.body#/processId"},"description":"Download the result ZIP once the job is FINISHED."},"DownloadPageXml":{"operationId":"getPageXmlProcessingResult","parameters":{"processId":"$response.body#/processId"},"description":"Retrieve the result as PAGE XML once the job is FINISHED."}}},"400":{"description":"The request body is malformed or misses information.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statusCode":400,"reasonPhrase":"Bad Request","message":"The processing request's textRecognition config does not include a htrId"}}}},"401":{"description":"The request is not authorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statusCode":401,"reasonPhrase":"Unauthorized","message":"The request is not authorized"}}}},"404":{"description":"A referenced entity in the request does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statusCode":404,"reasonPhrase":"Not Found","message":"A HTR model with ID = x does not exist"}}}},"429":{"description":"The number of requests exceeds a limit applying to the used account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statusCode":429,"reasonPhrase":"Too Many Requests","message":"Your processing volume is depleted."}}}}}}},"/v2/processes/{processId}":{"get":{"tags":["Transkribus API"],"summary":"Get the status of a job, identified by its processId","operationId":"getProcessingStatus","x-codeSamples":[{"lang":"shell","label":"curl","source":"curl https://api-staging.transkribus.org/v2/processes/$PROCESS_ID \\\n  -H \"Authorization: Bearer $ACCESS_TOKEN\""},{"lang":"python","label":"Python","source":"import requests\n\nresp = requests.get(\n    f\"https://api-staging.transkribus.org/v2/processes/{process_id}\",\n    headers={\"Authorization\": f\"Bearer {access_token}\"},\n)\njob = resp.json()\nprint(job[\"status\"])"},{"lang":"javascript","label":"JavaScript","source":"const job = await fetch('https://api-staging.transkribus.org/v2/processes/' + processId, {\n  headers: { 'Authorization': 'Bearer ' + accessToken }\n}).then(r => r.json());\nconsole.log(job.status);"}],"parameters":[{"name":"processId","in":"path","required":true,"description":"The UUID (v7) or integer processId of the job","schema":{"type":"string"}}],"responses":{"200":{"description":"The request was accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessingResponseRepresentation"},"example":{"processId":3866314,"status":"FINISHED","content":{"text":"Eisenschrott","regions":[{"id":"region_1","coords":{"points":"0,0 282,0 280,109 0,108"},"lines":[{"id":"line_1","coords":{"points":"0,109 55,89 79,91 96,106 131,100 152,109 196,75 243,73 254,82 281,70 281,13 242,11 228,-1 173,15 146,3 98,13 65,-2 1,8"},"baseline":{"points":"6,64 276,65"},"text":"Eisenschrott"}]}]},"links":[{"rel":"self","href":"https://api-staging.transkribus.org/v2/processes/01927669-f207-7550-ba9f-05a14a5cb899","title":"Status"},{"rel":"result","href":"https://api-staging.transkribus.org/v2/processes/01927669-f207-7550-ba9f-05a14a5cb899/result","title":"Multiple Pages Result"},{"rel":"cancel","href":"https://api-staging.transkribus.org/v2/processes/01927669-f207-7550-ba9f-05a14a5cb899/cancel","title":"Cancel","method":"POST"}]}}}},"400":{"description":"The request body is malformed or misses information.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The request is not authorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"A referenced entity in the request does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/processes/longpoll/{processId}":{"get":{"tags":["Transkribus API"],"summary":"Long-poll for job status","description":"Waits until the job status changes to a terminal state (FINISHED, FAILED, CANCELLED) or until the polling timeout expires. Returns the same response shape as `GET /v2/processes/{processId}`. Prefer this over repeated polling for efficient status tracking.","operationId":"longPollProcessingStatus","x-codeSamples":[{"lang":"shell","label":"curl","source":"curl https://api-staging.transkribus.org/v2/processes/longpoll/$PROCESS_ID \\\n  -H \"Authorization: Bearer $ACCESS_TOKEN\""},{"lang":"python","label":"Python","source":"import requests\n\nTERMINAL = {\"FINISHED\", \"FAILED\", \"CANCELLED\"}\nwhile True:\n    resp = requests.get(\n        f\"https://api-staging.transkribus.org/v2/processes/longpoll/{process_id}\",\n        headers={\"Authorization\": f\"Bearer {access_token}\"},\n        timeout=120,\n    )\n    if resp.status_code == 408:\n        continue  # no status change within the window; just repeat\n    job = resp.json()\n    if job[\"status\"] in TERMINAL:\n        break"},{"lang":"javascript","label":"JavaScript","source":"const TERMINAL = new Set(['FINISHED', 'FAILED', 'CANCELLED']);\nlet job;\ndo {\n  const res = await fetch('https://api-staging.transkribus.org/v2/processes/longpoll/' + processId, {\n    headers: { 'Authorization': 'Bearer ' + accessToken }\n  });\n  if (res.status === 408) continue; // timeout, repeat the request\n  job = await res.json();\n} while (!job || !TERMINAL.has(job.status));"}],"parameters":[{"name":"processId","in":"path","required":true,"description":"The UUID (v7) or integer processId of the job","schema":{"type":"string"}},{"name":"interval","in":"query","required":false,"description":"Polling interval in milliseconds","schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"The job reached a terminal status within the polling window","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessingResponseRepresentation"}}}},"401":{"description":"The request is not authorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No job found for the given processId.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"408":{"description":"Request timeout: no status change detected within the polling interval.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/processes/{processId}/result":{"get":{"tags":["Transkribus API"],"summary":"Download result archive for a job","description":"Downloads a ZIP archive containing the result files for a finished job.","operationId":"getProcessingResultArchive","x-codeSamples":[{"lang":"shell","label":"curl","source":"curl -o result.zip https://api-staging.transkribus.org/v2/processes/$PROCESS_ID/result \\\n  -H \"Authorization: Bearer $ACCESS_TOKEN\""},{"lang":"python","label":"Python","source":"import requests\n\nresp = requests.get(\n    f\"https://api-staging.transkribus.org/v2/processes/{process_id}/result\",\n    headers={\"Authorization\": f\"Bearer {access_token}\"},\n)\nresp.raise_for_status()\nwith open(\"result.zip\", \"wb\") as f:\n    f.write(resp.content)"},{"lang":"javascript","label":"JavaScript","source":"const res = await fetch('https://api-staging.transkribus.org/v2/processes/' + processId + '/result', {\n  headers: { 'Authorization': 'Bearer ' + accessToken }\n});\nconst zip = await res.arrayBuffer();"}],"parameters":[{"name":"processId","in":"path","required":true,"description":"The UUID (v7) or integer processId of the job","schema":{"type":"string"}}],"responses":{"200":{"description":"The result archive for the process","content":{"application/zip":{}}},"401":{"description":"The request is not authorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No result found for the given processId.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/processes/{processId}/alto":{"get":{"tags":["Transkribus API"],"summary":"Get the job result as ALTO XML","description":"Retrieves the result of a job, identified by its processId, as ALTO XML.","operationId":"getAltoProcessingResult","parameters":[{"name":"processId","in":"path","required":true,"description":"The UUID (v7) or integer processId of the job","schema":{"type":"string"}}],"responses":{"200":{"description":"The result as ALTO XML","content":{"application/xml":{}}},"401":{"description":"The request is not authorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The processId does not exist or the result is not yet available.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v2/processes/{processId}/page":{"get":{"tags":["Transkribus API"],"summary":"Get the job result as PAGE XML","description":"Retrieves the result of a job, identified by its processId, as PAGE XML (PRImA 2013-07-15 schema).","operationId":"getPageXmlProcessingResult","x-codeSamples":[{"lang":"shell","label":"curl","source":"curl https://api-staging.transkribus.org/v2/processes/$PROCESS_ID/page \\\n  -H \"Authorization: Bearer $ACCESS_TOKEN\" > page.xml"},{"lang":"python","label":"Python","source":"import requests\n\nresp = requests.get(\n    f\"https://api-staging.transkribus.org/v2/processes/{process_id}/page\",\n    headers={\"Authorization\": f\"Bearer {access_token}\"},\n)\nresp.raise_for_status()\npage_xml = resp.text"},{"lang":"javascript","label":"JavaScript","source":"const pageXml = await fetch('https://api-staging.transkribus.org/v2/processes/' + processId + '/page', {\n  headers: { 'Authorization': 'Bearer ' + accessToken }\n}).then(r => r.text());"}],"parameters":[{"name":"processId","in":"path","required":true,"description":"The UUID (v7) or integer processId of the job","schema":{"type":"string"}}],"responses":{"200":{"description":"The result as PAGE XML","content":{"application/xml":{}}},"401":{"description":"The request is not authorized.","content":{"application/xml":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The processId does not exist or the result is not yet available.","content":{"application/xml":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"Error":{"type":"object","properties":{"statusCode":{"type":"integer","format":"int32"},"reasonPhrase":{"type":"string"},"message":{"type":"string"}}},"Baseline":{"type":"object","properties":{"points":{"pattern":"^(\\d,\\d \\d,\\d){1} (\\d,\\d)*$","type":"string","description":"The pixel coordinates of the baseline's vertices"}},"description":"A line's baseline, i.e. the line on which the letters sit"},"JobConfig":{"type":"object","properties":{"lineDetection":{"$ref":"#/components/schemas/LineDetectionConfig"},"textRecognition":{"required":["htrId"],"type":"object","properties":{"languageModel":{"type":"string","description":"Enables a language model for generating the transcription","enum":["built-in"]},"htrId":{"type":"integer","description":"ID of the Transkribus HTR model to apply","format":"int32"}},"additionalProperties":{"type":"object"}}},"description":"Specifies how the submitted image shall be processed"},"Content":{"type":"object","properties":{"text":{"type":"string"},"regions":{"type":"array","items":{"$ref":"#/components/schemas/Region"}}},"description":"Optional preliminary layout information"},"Coords":{"type":"object","properties":{"points":{"pattern":"^(\\d,\\d \\d,\\d \\d,\\d){1} (\\d,\\d)*$","type":"string","description":"The pixel coordinates of the element's vertices"}},"description":"The bounding polygon of a layout element"},"TextRecognitionConfig":{"required":["htrId"],"type":"object","properties":{"languageModel":{"type":"string","description":"Enables a language model for generating the transcription","enum":["built-in"]},"htrId":{"type":"integer","description":"ID of the Transkribus HTR model to apply","format":"int32"}},"additionalProperties":{"type":"object"}},"LineDetectionConfig":{"type":"object","properties":{"modelId":{"type":"integer","description":"ID of the Transkribus layout model to apply if no lines were passed in the content section. The field name lineDetection is historical; the models are layout models producing baselines, regions and reading order.","format":"int32"},"minimalBaselineLength":{"type":"integer","description":"Minimal baseline length for the layout analysis - detected baselines below this length are dropped","format":"int32"},"baselineAccuracyThreshold":{"maximum":255,"minimum":0,"type":"integer","description":"Baseline accuracy threshold. The threshold for binarization of the baseline mask images. Higher values enforce higher accuracy in the detected baselines. Ranges between 0 and 255.","format":"int32"},"maxDistForMerging":{"type":"integer","description":"Max-dist for merging. The maximal distance between two baselines to be merged.","format":"int32"},"numTextRegions":{"type":"number","description":"Number of text regions. One: -1, Few: 1.6, Medium: 1.0, Many: 0.4","format":"float"}}},"Job":{"required":["processId","status"],"type":"object","properties":{"processId":{"type":"integer","description":"The integer ID of the job, used to query its status and results","format":"int32"},"uuid":{"type":"string","description":"The UUID (v7) of the associated processing job"},"status":{"type":"string","description":"The status of the associated processing job","enum":["CREATED","WAITING","RUNNING","FINISHED","FAILED","CANCELLED"]},"config":{"$ref":"#/components/schemas/JobConfig"},"content":{"$ref":"#/components/schemas/Content"},"links":{"type":"array","description":"HATEOAS navigation links. Use `rel`, not `title`, as the stable machine-readable identifier. `title` is display text only and may change. The `longpoll` link is present only while the job is non-terminal; its absence signals completion.","items":{"$ref":"#/components/schemas/Link"}}},"description":"A job and its current status"},"Link":{"type":"object","required":["rel","href","title"],"properties":{"rel":{"type":"string","description":"Link relation type. `self` = canonical URL of this resource. `longpoll` = waits until status changes, present only while non-terminal. `result` / `page-result` = downloadable output. `status` = status URL as a related link. `collection` = the jobs list. `create` = submit a new job. `cancel` = cancel this job.","enum":["self","collection","status","longpoll","page-result","result","create","cancel"]},"href":{"type":"string","description":"The absolute URL of the linked resource or operation."},"title":{"type":"string","description":"Human-readable name identifying the link target (e.g. `Status`, `Status Longpoll`, `Multiple Pages Result`, `Cancel`)."},"method":{"type":"string","description":"HTTP method to use when following this link. Omitted for GET links.","enum":["GET","POST","PUT","DELETE","PATCH"]}}},"TextLine":{"type":"object","properties":{"id":{"type":"string","description":"Identifier for this layout element. If set in a request it will be persisted for later reference in the response. If none is set, a value will be generated."},"coords":{"$ref":"#/components/schemas/Coords"},"baseline":{"$ref":"#/components/schemas/Baseline"},"text":{"type":"string"},"words":{"type":"array","items":{"$ref":"#/components/schemas/Word"}}}},"Region":{"type":"object","properties":{"id":{"type":"string","description":"Identifier for this layout element. If set in a request it will be persisted for later reference in the response. If none is set, a value will be generated."},"coords":{"$ref":"#/components/schemas/Coords"},"orientation":{"maximum":180,"minimum":-180,"exclusiveMinimum":true,"type":"number","description":"The angle the rectangle encapsulating the page (or its Border) has to be rotated in clockwise direction in order to correct the present skew (negative values indicate anti-clockwise rotation).","format":"float"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/TextLine"}}}},"Word":{"type":"object","properties":{"id":{"type":"string","description":"Identifier for this layout element. If set in a request it will be persisted for later reference in the response. If none is set, a value will be generated."},"coords":{"$ref":"#/components/schemas/Coords"},"text":{"type":"string"}}},"Image":{"maxProperties":1,"type":"object","properties":{"base64":{"type":"string","description":"base64-encoded image data","format":"base64"},"imageUrl":{"type":"string","description":"URL to a hosted image file","format":"url"}},"description":"The image to process: either the base64-encoded binary data or a reference to a publicly available image"},"JobRequest":{"required":["config","image"],"type":"object","properties":{"config":{"$ref":"#/components/schemas/JobConfig"},"content":{"$ref":"#/components/schemas/Content"},"image":{"$ref":"#/components/schemas/Image"}},"description":"Request data for a single-image job"},"ProcessingRequestRepresentation":{"required":["config","image"],"type":"object","properties":{"config":{"$ref":"#/components/schemas/ConfigRepresentation"},"content":{"$ref":"#/components/schemas/Content"},"image":{"$ref":"#/components/schemas/Image"}},"description":"Request data for a single-image processing job"},"ConfigRepresentation":{"type":"object","properties":{"lineDetection":{"$ref":"#/components/schemas/LineDetectionConfig"},"textRecognition":{"$ref":"#/components/schemas/TextRecognitionConfig"}},"description":"Specifies how the submitted image shall be processed"},"ProcessingResponseRepresentation":{"required":["processId","status"],"type":"object","properties":{"processId":{"type":"integer","description":"The integer ID of the job","format":"int32"},"status":{"type":"string","description":"The status of the job","enum":["CREATED","WAITING","RUNNING","FINISHED","FAILED","CANCELLED"]},"content":{"$ref":"#/components/schemas/Content"},"links":{"type":"array","description":"HATEOAS navigation links. Use `rel`, not `title`, as the stable machine-readable identifier.","items":{"$ref":"#/components/schemas/LinkRepresentation"}}},"description":"Response shape for a processing job"},"LinkRepresentation":{"type":"object","required":["rel","href","title"],"properties":{"rel":{"type":"string","description":"Link relation type."},"href":{"type":"string","description":"The absolute URL of the linked resource."},"title":{"type":"string","description":"Human-readable name for the link target."},"method":{"type":"string","description":"HTTP method to use when following this link. Omitted for GET links.","enum":["GET","POST","PUT","DELETE","PATCH"]}}}},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}}}