Skip to main content

Outcome

The document is attached to the intended parent, has reached ready, and can be downloaded through the authenticated proxy. Failed or rejected attachments have been recovered without blocking a later review or handoff.

Prerequisites

  • A Bearer key.
  • A claim UUID, or the equivalent parent IDs for a message or request-to-client answer. Claim document commands never need an order ID.
  • A PDF, JPEG, or PNG no larger than 10 MiB.
  • A stable idempotency key for each upload command.

Lifecycle context

Documents are always resource-scoped and scan asynchronously through pending, then ready, rejected, or failed. Only the malware scan and page processing are asynchronous: the byte sniff, PDF structure checks, size, and base64 decoding run synchronously and answer 400 without creating a document. Order finalization does not wait. A failed or rejected attachment can be deleted and replaced while its parent remains editable; its bytes are no longer stored, so download_url is null and a download is 404. A ready attachment becomes visible downstream only at the parent workflow’s allowed handoff point.

1. Upload to the parent

For multipart upload, let curl set the multipart boundary:
For a JSON upload, send the base64 content and filename allowed by the operation. Remote url sources are no longer accepted. The stored filename is sanitised (no path components or control characters; the extension follows the detected content type), so read it back from the response rather than assuming your input. Use the same idempotency key only when retrying the same upload after a transport failure.

2. Read processing state

Poll this parent-scoped detail endpoint with backoff until status is ready, rejected, or failed. A failed document carries a failure_reason (page_limit_exceeded, encrypted, corrupt, unsupported, or processing_failed); it is null in every other state. The claim-scoped list also exposes status and timestamps. A titled claim’s title documents use /v2/claims/{claim_id}/enforceable-title/documents/…; they also remain stable if review moves the claim to another order. Document-processing webhook events have been retired.

Representative response

This is a complete response matching the DocumentRead response schema.

3. Replace a failed or rejected document

Remove the failed or rejected attachment from an editable parent, then upload a corrected file with a new idempotency key. There is no document-ingestion retry endpoint:
A successful delete returns 204 with no response body. Deleting an attachment whose parent review is closed returns 409; refetch the parent and escalate rather than retrying in a loop.

4. Download only a ready document

Use the documented download route. Do not persist or construct storage URLs.

Runnable Python workflow

Set DOCUMENT_FILE to a local PDF, JPEG, or PNG. The workflow verifies the sandbox, uploads the file, polls processing state, removes a failed or rejected attachment while its parent remains editable, and downloads a ready document. After removal, correct the source file and run a fresh upload command.
Python workflow

Failure and recovery

  • 400 or 415: fix the document type, source mode, size, or media type and start a new upload command. Encrypted PDFs (encrypted), PDFs above 100 pages (page_limit_exceeded), unparseable bytes (corrupt), and other content types (unsupported) are rejected synchronously on the file or base64 field — remove the password or split the file before uploading. A malware finding or a scanner that could not run is never a 400: it arrives asynchronously as rejected or failed.
  • 400 duplicate_part: a multipart body repeated type, filename, base64, or file; the error names the repeated part. A multipart body that is cut off before the file part is complete is reported as a missing file, so check the upload was sent in full before retrying.
  • 503 service_unavailable on an upload: document storage was briefly unavailable and nothing was created. Wait for Retry-After, then retry the same command with the same idempotency key.
  • 404 on DELETE: the claim, rental-agreement, or enforceable-title document does not exist under that parent. The response is neutral and does not reveal whether the ID exists elsewhere.
  • 406 not_acceptable on a download: send Accept: */*, application/octet-stream, application/pdf, image/*, or application/json; text/html is refused.
  • 404 not_found on a download: the document is not ready (including rejected/failed), or its object is missing in storage. 503 service_unavailable with Retry-After: 1 is a storage fault — retry after the interval.
  • 409 on DELETE …/enforceable-title/: the title still owns documents; the envelope lists them in document_ids[]. Delete those first.
  • 409: the document state or parent edit window changed. Refetch both; delete and replace failed or rejected content only when the parent still permits it.
  • 429: wait at least the integer seconds in Retry-After, then retry the same logical POST with the same idempotency key. Resume GET polling after the wait.
  • Timeout, 500, or 503: retry a POST with its same key; safe GET and download requests may be retried with backoff.

Verify

A mandate message or an answer to a request to client is handed to paywise case processing without waiting for scanning, like one submitted in the paywise portal: its attachments go along as they are, and files already failed or rejected are left out. Order review can resume while answer documents are still processing.