{
    "openapi": "3.1.0",
    "info": {
        "title": "DocuTract API",
        "version": "1.0.0",
        "description": "The outward-facing contour of DocuTract: create cases and documents, upload scans, read values with their sources and download the result.\n\nAuthenticate with a workspace token as `Authorization: Bearer dt_live_…`. Every route names the scope it needs; a token that authenticates but lacks the scope is answered 403 with the scope named, never 404.\n\nThe rate limit is per token (60 requests a minute by default); 429 carries `Retry-After`.\n\nNo-code platforms subscribe to the events described under `webhooks` with REST hooks: POST /api/v1/hooks to subscribe, DELETE /api/v1/hooks/{hook} to unsubscribe, and GET /api/v1/hooks/samples/{event} for an example payload."
    },
    "servers": [
        {
            "url": "https://docutract.online"
        }
    ],
    "components": {
        "securitySchemes": {
            "workspaceToken": {
                "type": "http",
                "scheme": "bearer",
                "description": "A workspace API token, created in the app under Settings → Integrations. Shown once when it is created and stored only as a hash."
            }
        }
    },
    "security": [
        {
            "workspaceToken": []
        }
    ],
    "paths": {
        "/api/v1/case-types": {
            "get": {
                "operationId": "caseTypes.index",
                "summary": "The case types a case can be opened from",
                "tags": [
                    "case-types"
                ],
                "responses": {
                    "200": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "cases:read"
                        ]
                    }
                ],
                "description": "The published case types of the workspace, by name: `id`, `name`, `description`.\n\nScope: `cases:read`."
            }
        },
        "/api/v1/cases": {
            "get": {
                "operationId": "cases.index",
                "summary": "The newest cases, optionally filtered by status",
                "tags": [
                    "cases"
                ],
                "responses": {
                    "200": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "cases:read"
                        ]
                    }
                ],
                "description": "Newest first, at most `limit` (default 25, at most 100); no paging. Each item has the shape of GET /api/v1/cases/{case}.\n\nScope: `cases:read`.",
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "enum": [
                                "draft",
                                "collecting",
                                "review",
                                "ready",
                                "failed"
                            ]
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100,
                            "default": 25
                        }
                    }
                ]
            },
            "post": {
                "operationId": "cases.store",
                "summary": "Open a case of a given case type",
                "tags": [
                    "cases"
                ],
                "responses": {
                    "201": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "cases:write"
                        ]
                    }
                ],
                "description": "The case type decides which documents the case produces and which scans it expects.\n\nScope: `cases:write`."
            }
        },
        "/api/v1/cases/{case}": {
            "get": {
                "operationId": "cases.show",
                "summary": "The case with its documents, scans and findings",
                "tags": [
                    "cases"
                ],
                "responses": {
                    "200": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "cases:read"
                        ]
                    }
                ],
                "description": "Scope: `cases:read`.",
                "parameters": [
                    {
                        "name": "case",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ]
            }
        },
        "/api/v1/cases/{case}/generate": {
            "post": {
                "operationId": "cases.generate",
                "summary": "Generate the documents of the case",
                "tags": [
                    "cases"
                ],
                "responses": {
                    "201": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "cases:write"
                        ]
                    }
                ],
                "description": "Starts the render of every document that is ready. Documents with a blocking finding are reported, not silently skipped.\n\nScope: `cases:write`.",
                "parameters": [
                    {
                        "name": "case",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ]
            }
        },
        "/api/v1/cases/{case}/scans": {
            "post": {
                "operationId": "cases.scans",
                "summary": "Upload a scan into the case",
                "tags": [
                    "cases"
                ],
                "responses": {
                    "201": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "cases:write"
                        ]
                    }
                ],
                "description": "Multipart. `doc_type` says what the file is (a passport, a certificate); the reading is queued and its values reach every document of the case.\n\nScope: `cases:write`.",
                "parameters": [
                    {
                        "name": "case",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ]
            }
        },
        "/api/v1/documents": {
            "get": {
                "operationId": "documents.index",
                "summary": "The newest documents, optionally filtered",
                "tags": [
                    "documents"
                ],
                "responses": {
                    "200": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "documents:read"
                        ]
                    }
                ],
                "description": "Newest first, at most `limit` (default 25, at most 100); no paging. Filter by the exact `reference` (DOC-…), by `status` or by `template_id`. Each item has the shape of GET /api/v1/documents/{document}.\n\nScope: `documents:read`.",
                "parameters": [
                    {
                        "name": "reference",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string"
                        },
                        "description": "The exact reference of a document, e.g. DOC-26-0001."
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "enum": [
                                "draft",
                                "uploading",
                                "ocr",
                                "review",
                                "generating",
                                "done",
                                "error"
                            ]
                        }
                    },
                    {
                        "name": "template_id",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100,
                            "default": 25
                        }
                    }
                ]
            },
            "post": {
                "operationId": "documents.store",
                "summary": "Create a document, optionally filled and generated",
                "tags": [
                    "documents"
                ],
                "responses": {
                    "201": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "documents:write"
                        ]
                    }
                ],
                "description": "Pass `values` keyed by placeholder to fill it, and `generate: true` to start the render in the same call. A placeholder the template does not have is ignored rather than refused, so a caller can send one payload shape to several templates.\n\nScope: `documents:write`."
            }
        },
        "/api/v1/documents/{document}": {
            "get": {
                "operationId": "documents.show",
                "summary": "Status, progress and open findings of a document",
                "tags": [
                    "documents"
                ],
                "responses": {
                    "200": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "documents:read"
                        ]
                    }
                ],
                "description": "The `findings` array is what an unattended integration watches: while it is non-empty, a human is expected to look before the result is used.\n\nScope: `documents:read`.",
                "parameters": [
                    {
                        "name": "document",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ]
            }
        },
        "/api/v1/documents/{document}/download": {
            "get": {
                "operationId": "documents.download",
                "summary": "A short-lived link to the finished file",
                "tags": [
                    "documents"
                ],
                "responses": {
                    "200": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "documents:read"
                        ]
                    }
                ],
                "description": "Answers 409 while the document is not generated yet. The link expires; ask again rather than storing it.\n\nScope: `documents:read`.",
                "parameters": [
                    {
                        "name": "document",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "format",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "enum": [
                                "docx",
                                "pdf"
                            ],
                            "default": "docx"
                        }
                    }
                ]
            }
        },
        "/api/v1/documents/{document}/values": {
            "get": {
                "operationId": "documents.values",
                "summary": "Every value of a document with the source it came from",
                "tags": [
                    "documents"
                ],
                "responses": {
                    "200": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "documents:read"
                        ]
                    }
                ],
                "description": "Each value names where it came from (which scan, which field of it, or that a person typed it) and how confident the reading was.\n\nScope: `documents:read`.",
                "parameters": [
                    {
                        "name": "document",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ]
            }
        },
        "/api/v1/hooks": {
            "get": {
                "operationId": "hooks.index",
                "summary": "List the webhook subscriptions made over the API",
                "tags": [
                    "hooks"
                ],
                "responses": {
                    "200": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "webhooks:read"
                        ]
                    }
                ],
                "description": "REST hooks for no-code platforms (Zapier, Make, n8n). Only subscriptions created with POST /api/v1/hooks are listed; endpoints added by hand in the app are managed there.\n\nScope: `webhooks:read`."
            },
            "post": {
                "operationId": "hooks.store",
                "summary": "Subscribe a URL to one event",
                "tags": [
                    "hooks"
                ],
                "responses": {
                    "201": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "webhooks:write"
                        ]
                    }
                ],
                "description": "Every time `event` happens we POST its payload (see `webhooks`) to `target_url`, signed with `X-DocuTract-Signature` using the `secret` returned here once. `target_url` must be https and public. The subscription ends when it is deleted, when the token that created it is revoked or expires, or when your endpoint answers a delivery with 410 Gone.\n\nScope: `webhooks:write`.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "event",
                                    "target_url"
                                ],
                                "properties": {
                                    "event": {
                                        "type": "string",
                                        "description": "One of the events listed by GET /api/v1/hooks/events."
                                    },
                                    "target_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "An https URL on a public host."
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/hooks/events": {
            "get": {
                "operationId": "hooks.events",
                "summary": "The events a subscription can listen to",
                "tags": [
                    "hooks"
                ],
                "responses": {
                    "200": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "webhooks:read"
                        ]
                    }
                ],
                "description": "Scope: `webhooks:read`."
            }
        },
        "/api/v1/hooks/samples/{event}": {
            "get": {
                "operationId": "hooks.samples",
                "summary": "An example payload of an event",
                "tags": [
                    "hooks"
                ],
                "responses": {
                    "200": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "webhooks:read"
                        ]
                    }
                ],
                "description": "A list with one invented payload, shaped exactly like a real delivery — for a platform's \"test trigger\" before any real event exists. It never contains data of the workspace.\n\nScope: `webhooks:read`.",
                "parameters": [
                    {
                        "name": "event",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "enum": [
                                "document.ready",
                                "document.failed",
                                "case.ready",
                                "finding.raised",
                                "intake.uploaded"
                            ]
                        }
                    }
                ]
            }
        },
        "/api/v1/hooks/{hook}": {
            "delete": {
                "operationId": "hooks.destroy",
                "summary": "Unsubscribe",
                "tags": [
                    "hooks"
                ],
                "responses": {
                    "204": {
                        "description": "Done; no body."
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "webhooks:write"
                        ]
                    }
                ],
                "description": "Deletes a subscription made with POST /api/v1/hooks. Answers 204, and 404 for an id this workspace does not have.\n\nScope: `webhooks:write`.",
                "parameters": [
                    {
                        "name": "hook",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ]
            }
        },
        "/api/v1/me": {
            "get": {
                "operationId": "me",
                "summary": "The workspace, plan and token behind the credential",
                "tags": [
                    "me"
                ],
                "responses": {
                    "200": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "description": "The cheapest authenticated call: which workspace the token belongs to (`workspace.id`, `workspace.name`), its plan (`plan.key`, `plan.name`) and the token itself (`token.name`, `token.scopes`, `token.expires_at`). No scope is needed. No-code platforms call it to test a connection and to label it with the workspace name."
            }
        },
        "/api/v1/templates": {
            "get": {
                "operationId": "templates.index",
                "summary": "List the templates of the workspace",
                "tags": [
                    "templates"
                ],
                "responses": {
                    "200": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "templates:read"
                        ]
                    }
                ],
                "description": "Every active template with the placeholders an integration has to supply. `name` narrows the list to the templates whose name contains it, ignoring case.\n\nScope: `templates:read`.",
                "parameters": [
                    {
                        "name": "name",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "maxLength": 200
                        },
                        "description": "Only templates whose name contains this text, ignoring case."
                    }
                ]
            }
        },
        "/api/v1/templates/{template}": {
            "get": {
                "operationId": "templates.show",
                "summary": "One template with its fields",
                "tags": [
                    "templates"
                ],
                "responses": {
                    "200": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "templates:read"
                        ]
                    }
                ],
                "description": "The fields carry their placeholder and where the value normally comes from (a scan, a list, typed in).\n\nScope: `templates:read`.",
                "parameters": [
                    {
                        "name": "template",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ]
            }
        },
        "/api/v1/templates/{template}/fields": {
            "get": {
                "operationId": "templates.fields",
                "summary": "The fields of a template as a flat list of inputs",
                "tags": [
                    "templates"
                ],
                "responses": {
                    "200": {
                        "description": "The result, under `data`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "The token is missing, unknown, revoked or expired."
                    },
                    "403": {
                        "description": "The token lacks the scope this route needs, or the workspace plan does not include the API."
                    },
                    "404": {
                        "description": "No such row in this token's workspace."
                    },
                    "422": {
                        "description": "The request body did not validate; `errors` names the fields."
                    },
                    "429": {
                        "description": "Rate limit exceeded; `Retry-After` says when to come back."
                    }
                },
                "security": [
                    {
                        "workspaceToken": [
                            "templates:read"
                        ]
                    }
                ],
                "description": "One entry per placeholder: `key` (what `values` in POST /api/v1/documents is keyed by), a human `label`, where the value normally comes from, and whether a form needs to ask for it (`fillable`: false for the fields we fill ourselves). Meant for the dynamic fields of a no-code platform.\n\nScope: `templates:read`.",
                "parameters": [
                    {
                        "name": "template",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ]
            }
        }
    },
    "webhooks": {
        "document.ready": {
            "post": {
                "summary": "We POST this to your endpoint when `document.ready` happens.",
                "description": "Verify `X-DocuTract-Signature: t=<unix seconds>,v1=<hex hmac-sha256 of \"<t>.<body>\" with the endpoint secret>` before trusting the body, and refuse a timestamp older than five minutes. Answer 2xx to acknowledge; anything else is retried on a widening schedule and then given up on, with the response body kept in the delivery log.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "event": {
                                        "type": "string",
                                        "const": "document.ready"
                                    },
                                    "occurred_at": {
                                        "type": "string",
                                        "format": "date-time"
                                    }
                                },
                                "required": [
                                    "event",
                                    "occurred_at"
                                ]
                            },
                            "example": {
                                "document_id": "00000000-0000-4000-8000-000000000001",
                                "reference": "DOC-26-0001",
                                "template_id": "00000000-0000-4000-8000-000000000002",
                                "template_version": 1,
                                "event": "document.ready",
                                "occurred_at": "2026-01-15T10:30:00+00:00"
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Acknowledged; the delivery is marked delivered."
                    }
                }
            }
        },
        "document.failed": {
            "post": {
                "summary": "We POST this to your endpoint when `document.failed` happens.",
                "description": "Verify `X-DocuTract-Signature: t=<unix seconds>,v1=<hex hmac-sha256 of \"<t>.<body>\" with the endpoint secret>` before trusting the body, and refuse a timestamp older than five minutes. Answer 2xx to acknowledge; anything else is retried on a widening schedule and then given up on, with the response body kept in the delivery log.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "event": {
                                        "type": "string",
                                        "const": "document.failed"
                                    },
                                    "occurred_at": {
                                        "type": "string",
                                        "format": "date-time"
                                    }
                                },
                                "required": [
                                    "event",
                                    "occurred_at"
                                ]
                            },
                            "example": {
                                "document_id": "00000000-0000-4000-8000-000000000001",
                                "reference": "DOC-26-0001",
                                "reason": "Document generation failed.",
                                "event": "document.failed",
                                "occurred_at": "2026-01-15T10:30:00+00:00"
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Acknowledged; the delivery is marked delivered."
                    }
                }
            }
        },
        "case.ready": {
            "post": {
                "summary": "We POST this to your endpoint when `case.ready` happens.",
                "description": "Verify `X-DocuTract-Signature: t=<unix seconds>,v1=<hex hmac-sha256 of \"<t>.<body>\" with the endpoint secret>` before trusting the body, and refuse a timestamp older than five minutes. Answer 2xx to acknowledge; anything else is retried on a widening schedule and then given up on, with the response body kept in the delivery log.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "event": {
                                        "type": "string",
                                        "const": "case.ready"
                                    },
                                    "occurred_at": {
                                        "type": "string",
                                        "format": "date-time"
                                    }
                                },
                                "required": [
                                    "event",
                                    "occurred_at"
                                ]
                            },
                            "example": {
                                "case_id": "00000000-0000-4000-8000-000000000003",
                                "title": "Sample case",
                                "documents": [
                                    {
                                        "id": "00000000-0000-4000-8000-000000000001",
                                        "reference": "DOC-26-0001"
                                    }
                                ],
                                "event": "case.ready",
                                "occurred_at": "2026-01-15T10:30:00+00:00"
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Acknowledged; the delivery is marked delivered."
                    }
                }
            }
        },
        "finding.raised": {
            "post": {
                "summary": "We POST this to your endpoint when `finding.raised` happens.",
                "description": "Verify `X-DocuTract-Signature: t=<unix seconds>,v1=<hex hmac-sha256 of \"<t>.<body>\" with the endpoint secret>` before trusting the body, and refuse a timestamp older than five minutes. Answer 2xx to acknowledge; anything else is retried on a widening schedule and then given up on, with the response body kept in the delivery log.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "event": {
                                        "type": "string",
                                        "const": "finding.raised"
                                    },
                                    "occurred_at": {
                                        "type": "string",
                                        "format": "date-time"
                                    }
                                },
                                "required": [
                                    "event",
                                    "occurred_at"
                                ]
                            },
                            "example": {
                                "document_id": "00000000-0000-4000-8000-000000000001",
                                "finding_id": "00000000-0000-4000-8000-000000000004",
                                "severity": "warn",
                                "message": "The date of birth differs between the two scans.",
                                "event": "finding.raised",
                                "occurred_at": "2026-01-15T10:30:00+00:00"
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Acknowledged; the delivery is marked delivered."
                    }
                }
            }
        },
        "intake.uploaded": {
            "post": {
                "summary": "We POST this to your endpoint when `intake.uploaded` happens.",
                "description": "Verify `X-DocuTract-Signature: t=<unix seconds>,v1=<hex hmac-sha256 of \"<t>.<body>\" with the endpoint secret>` before trusting the body, and refuse a timestamp older than five minutes. Answer 2xx to acknowledge; anything else is retried on a widening schedule and then given up on, with the response body kept in the delivery log.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "event": {
                                        "type": "string",
                                        "const": "intake.uploaded"
                                    },
                                    "occurred_at": {
                                        "type": "string",
                                        "format": "date-time"
                                    }
                                },
                                "required": [
                                    "event",
                                    "occurred_at"
                                ]
                            },
                            "example": {
                                "document_id": "00000000-0000-4000-8000-000000000001",
                                "scan_id": "00000000-0000-4000-8000-000000000005",
                                "channel": "link",
                                "original_name": "sample-scan.pdf",
                                "event": "intake.uploaded",
                                "occurred_at": "2026-01-15T10:30:00+00:00"
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Acknowledged; the delivery is marked delivered."
                    }
                }
            }
        }
    }
}