Endpoint reference
Every route an API key can call, and nothing else: this page is generated from the same list the service enforces. Send Authorization: Bearer <key> on each. The schema is at /docs/api/openapi.json.
Every route can also answer invalid_api_key, not_available_to_api_keys, too_many_requests, busy, invalid_request, account_suspended, internal_error. See Errors.
GET /healthz
Whether the service is up.
Response 200.
POST /v1/attestations
State that you are authorised to correct this document. Every correction carries one.
| Parameter | In | Required | Type |
|---|---|---|---|
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Request body:
{
"document_id": "\u2026",
"statement_version": "\u2026"
}
Response 201:
{
"attestation_id": "\u2026",
"statement_version": "\u2026",
"statement_text": "\u2026",
"created_at": "\u2026"
}
Can also answer: not_found.
GET /v1/audit
This account's record of what was done, newest first.
| Parameter | In | Required | Type |
|---|---|---|---|
subject_id | query | no | string or null |
limit | query | no | integer |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200:
[
{
"seq": 0,
"ts": "\u2026",
"actor_user_id": "\u2026",
"actor_kind": "\u2026",
"action": "\u2026",
"subject_type": "\u2026",
"subject_id": "\u2026",
"payload": {},
"entry_hash": "\u2026"
}
]
GET /v1/audit/export
The whole record as a file, with the chain's verdict inside it.
| Parameter | In | Required | Type |
|---|---|---|---|
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200.
Can also answer: business_plan_required.
GET /v1/audit/verify-chain
Recompute the record's hash chain and say where it breaks, if anywhere.
| Parameter | In | Required | Type |
|---|---|---|---|
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200.
POST /v1/certificates/verify
Check a certificate file's exact bytes. No key needed.
Request body: multipart/form-data.
Response 200:
{
"status": "\u2026",
"valid": true,
"reason": "\u2026",
"algorithm": "\u2026",
"certificate_id": "\u2026",
"issued_at": "\u2026",
"original_sha256": "\u2026",
"corrected_sha256": "\u2026",
"certificate_sha256": "\u2026",
"corrections": 0,
"key_id": "\u2026",
"statement": {}
}
GET /v1/certificates/{certificate_id}
Check a certificate by id: valid or not, its hashes and date. No key needed.
| Parameter | In | Required | Type |
|---|---|---|---|
certificate_id | path | yes | string |
Response 200:
{
"status": "\u2026",
"valid": true,
"reason": "\u2026",
"algorithm": "\u2026",
"certificate_id": "\u2026",
"issued_at": "\u2026",
"original_sha256": "\u2026",
"corrected_sha256": "\u2026",
"certificate_sha256": "\u2026",
"corrections": 0,
"key_id": "\u2026",
"statement": {}
}
Can also answer: not_found.
GET /v1/certificates/{certificate_id}/pdf
Download a certificate this account holds.
| Parameter | In | Required | Type |
|---|---|---|---|
certificate_id | path | yes | string |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200.
Can also answer: not_found, certificate_file_deleted.
POST /v1/documents
Upload a PDF. Send it as multipart field file; add password for a document that will not open without one.
| Parameter | In | Required | Type |
|---|---|---|---|
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Request body: multipart/form-data.
Response 201:
{
"document_id": "\u2026",
"tenant_id": "\u2026",
"state": "\u2026",
"page_count": 0,
"original_sha256": "\u2026",
"head_revision_id": "\u2026",
"filename_hint": "\u2026",
"pages": [
null
],
"issued_signals": {},
"concerns": [
"\u2026"
],
"protected": true,
"unlocked": true
}
Can also answer: file_too_large, too_many_pages, page_too_large, not_a_pdf, unreadable_pdf, no_pages, password_protected, password_required, password_incorrect, not_protected.
GET /v1/documents
List this account's documents, newest first.
| Parameter | In | Required | Type |
|---|---|---|---|
limit | query | no | integer |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200:
[
{
"document_id": "\u2026",
"tenant_id": "\u2026",
"state": "\u2026",
"page_count": 0,
"original_sha256": "\u2026",
"head_revision_id": "\u2026",
"filename_hint": "\u2026",
"pages": [
null
],
"issued_signals": {},
"concerns": [
null
],
"protected": true,
"unlocked": true
}
]
GET /v1/documents/{document_id}
One document, with its pages and state.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200:
{
"document_id": "\u2026",
"tenant_id": "\u2026",
"state": "\u2026",
"page_count": 0,
"original_sha256": "\u2026",
"head_revision_id": "\u2026",
"filename_hint": "\u2026",
"pages": [
null
],
"issued_signals": {},
"concerns": [
"\u2026"
],
"protected": true,
"unlocked": true
}
Can also answer: not_found.
DELETE /v1/documents/{document_id}
Delete a document, its corrections and every file made from it. The record keeps that it existed.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 204.
Can also answer: not_found, missing_capability.
POST /v1/documents/{document_id}/certificate
Issue a signed verification certificate for the document as it now stands.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Request body:
{
"name": "\u2026"
}
Response 201:
{
"certificate_id": "\u2026",
"document_id": "\u2026",
"issued_at": "\u2026",
"original_sha256": "\u2026",
"corrected_sha256": "\u2026",
"certificate_sha256": "\u2026",
"corrections": 0,
"key_id": "\u2026",
"pdf_available": true
}
Can also answer: business_plan_required, not_found, nothing_to_export, not_verified, verification_failed, nothing_to_certify, correction_not_verified, record_does_not_verify.
GET /v1/documents/{document_id}/certificates
The certificates issued for a document, newest first.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200:
[
{
"certificate_id": "\u2026",
"document_id": "\u2026",
"issued_at": "\u2026",
"original_sha256": "\u2026",
"corrected_sha256": "\u2026",
"certificate_sha256": "\u2026",
"corrections": 0,
"key_id": "\u2026",
"pdf_available": true
}
]
Can also answer: not_found.
POST /v1/documents/{document_id}/classify
Re-examine the pages: which carry text and which are scans.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200:
[
{
"index": 0,
"width_pt": 0.0,
"height_pt": 0.0,
"rotation": 0,
"kind": "\u2026",
"char_count": 0,
"image_count": 0,
"image_coverage": 0.0,
"confidence": 0.0,
"natural_dpi": 0
}
]
Can also answer: not_found.
GET /v1/documents/{document_id}/corrections
Every correction standing on the document, oldest first.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200:
[
{
"seq": 0,
"page_index": 0,
"box_render": [
null
],
"box_dpi": 0,
"changed_render": [
null
],
"changed_dpi": 0,
"text_before": "\u2026",
"text_after": "\u2026",
"visibility_cost": "\u2026",
"verified": true,
"failure_reason": "\u2026",
"outside_pixels": 0
}
]
Can also answer: not_found.
POST /v1/documents/{document_id}/edits
Apply a proposed correction. The answer is its verification.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Request body:
{
"request": {
"page_index": null,
"target": null,
"replacement": null,
"attestation_id": null,
"font_attempt": null
},
"apply": {
"proposal_id": null,
"confirm_token": null
}
}
Response 200:
{
"verification_id": "\u2026",
"revision_id": "\u2026",
"output_sha256": "\u2026",
"dpi": 0,
"passed": true,
"failure_reason": "\u2026",
"pages": [
null
],
"guards": [
{}
],
"stream_changes": {}
}
Can also answer: not_found, attestation_required, stale_or_invalid_confirmation, edit_refused, edit_failed, daily_limit_reached.
POST /v1/documents/{document_id}/edits:propose
Propose a correction and read what the engine would do, or why it refuses. Changes nothing.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Request body:
{
"page_index": 0,
"target": null,
"replacement": "\u2026",
"attestation_id": "\u2026",
"font_attempt": 0
}
Response 200:
{
"proposal_id": "\u2026",
"confirm_token": "\u2026",
"document_id": "\u2026",
"page_index": 0,
"tier": 0,
"tier_name": "\u2026",
"visibility_cost": "\u2026",
"explanation": "\u2026",
"measurements": {},
"warnings": [
"\u2026"
],
"refusal": "\u2026",
"advice": {
"code": null,
"what": null,
"why": null,
"do": null,
"worth_reporting": null
}
}
Can also answer: not_found, attestation_required, page_out_of_range.
POST /v1/documents/{document_id}/export
Pass the export gate: the document is released only if its latest verification is of these exact bytes and passed.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200:
{
"revision_id": "\u2026",
"output_sha256": "\u2026",
"verification_id": "\u2026",
"marking_applied": "\u2026",
"bytes_available": true
}
Can also answer: not_found, nothing_to_export, not_verified, verification_hash_mismatch, verification_failed, diff_outside_expected_region.
GET /v1/documents/{document_id}/export/download
Download the corrected PDF, through the same gate.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200.
Can also answer: not_found, nothing_to_export, not_verified, verification_hash_mismatch, verification_failed, diff_outside_expected_region, payment_required, email_required.
GET /v1/documents/{document_id}/manifest
The provenance record embedded in the corrected file.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200.
Can also answer: not_found, no_revision, no_manifest.
GET /v1/documents/{document_id}/pages/{page_index}/crop.png
Native-resolution pixels of one region, at most 4 megapixels. Until the document is paid for, a corrected page is marked and native only inside its corrections.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
page_index | path | yes | integer |
x | query | yes | integer |
y | query | yes | integer |
w | query | yes | integer |
h | query | yes | integer |
dpi | query | no | integer |
revision | query | no | string or null |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200.
Can also answer: not_found, crop_too_large, inspection_budget_spent.
POST /v1/documents/{document_id}/pages/{page_index}/ocr
Read a page and say where the words are, with their confidence.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
page_index | path | yes | integer |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Request body:
{
"find": "\u2026",
"box_render": [
0
],
"render_dpi": 0,
"lang": "\u2026",
"turn": 0
}
Response 200:
{
"page_index": 0,
"provider": "\u2026",
"lang": "\u2026",
"render_dpi": 0,
"word_count": 0,
"available": true,
"message": "\u2026",
"matches": [
null
],
"confirm_threshold": 0.0,
"selection_text": "\u2026",
"selection_confidence": 0.0,
"word_source": "text_layer"
}
Can also answer: not_found, page_out_of_range.
POST /v1/documents/{document_id}/pages/{page_index}/preflight
Find the words in a region that are already known to refuse, before trying them.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
page_index | path | yes | integer |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Request body:
{
"box_render": [
0
],
"render_dpi": 0,
"lang": "\u2026",
"turn": 0
}
Response 200:
{
"page_index": 0,
"render_dpi": 0,
"word_source": "text_layer",
"checked": 0,
"skipped": 0,
"regions": [
null
],
"applicable": true,
"message": "\u2026"
}
Can also answer: not_found, page_out_of_range.
GET /v1/documents/{document_id}/pages/{page_index}/preview.png
A page as a low-resolution image, to look at.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
page_index | path | yes | integer |
revision | query | no | string or null |
thumb | query | no | boolean |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200.
Can also answer: not_found.
POST /v1/documents/{document_id}/redo
Restore the correction last undone.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200:
{
"document": {
"document_id": null,
"tenant_id": null,
"state": null,
"page_count": null,
"original_sha256": null,
"head_revision_id": null,
"filename_hint": null,
"pages": null,
"issued_signals": null,
"concerns": null,
"protected": null,
"unlocked": null
},
"undone": {
"seq": null,
"page_index": null,
"box_render": null,
"box_dpi": null,
"changed_render": null,
"changed_dpi": null,
"text_before": null,
"text_after": null,
"visibility_cost": null,
"verified": null,
"failure_reason": null,
"outside_pixels": null
},
"corrections": [
null
]
}
Can also answer: not_found, nothing_to_redo.
GET /v1/documents/{document_id}/search
Where a phrase appears in the pages that carry text.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
q | query | no | string |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200:
{
"query": "\u2026",
"matches": [
null
],
"pages_searched": [
0
],
"pages_needing_recognition": [
0
],
"truncated": true
}
Can also answer: not_found.
POST /v1/documents/{document_id}/undo
Step back one correction. Nothing is deleted.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200:
{
"document": {
"document_id": null,
"tenant_id": null,
"state": null,
"page_count": null,
"original_sha256": null,
"head_revision_id": null,
"filename_hint": null,
"pages": null,
"issued_signals": null,
"concerns": null,
"protected": null,
"unlocked": null
},
"undone": {
"seq": null,
"page_index": null,
"box_render": null,
"box_dpi": null,
"changed_render": null,
"changed_dpi": null,
"text_before": null,
"text_after": null,
"visibility_cost": null,
"verified": null,
"failure_reason": null,
"outside_pixels": null
},
"corrections": [
null
]
}
Can also answer: not_found, nothing_to_undo.
GET /v1/documents/{document_id}/verification
The verification of the document as it now stands: the pixel comparison and every guard.
| Parameter | In | Required | Type |
|---|---|---|---|
document_id | path | yes | string |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200:
{
"verification_id": "\u2026",
"revision_id": "\u2026",
"output_sha256": "\u2026",
"dpi": 0,
"passed": true,
"failure_reason": "\u2026",
"pages": [
null
],
"guards": [
{}
],
"stream_changes": {}
}
Can also answer: not_found, not_verified, no_revision.
GET /v1/jobs/{job_id}
The progress of a queued job.
| Parameter | In | Required | Type |
|---|---|---|---|
job_id | path | yes | string |
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200:
{
"job_id": "\u2026",
"kind": "\u2026",
"status": "\u2026",
"progress": 0.0,
"stage": "\u2026",
"result": {},
"last_error": "\u2026"
}
Can also answer: not_found.
GET /v1/plans
Every plan side by side, in the numbers the service enforces. No key needed.
Response 200:
{
"currency": "\u2026",
"prices_include_vat": true,
"capabilities": [
"\u2026"
],
"plans": [
null
]
}
GET /v1/usage
What this account holds and may do today. Read-only.
| Parameter | In | Required | Type |
|---|---|---|---|
authorization | header | no | string or null |
x-tenant-id | header | no | string or null |
Response 200:
{
"limit": 0,
"used": 0.0,
"remaining": 0.0,
"resets_on": "\u2026",
"subscribed": true,
"confirmation_sent": true,
"checkout_open": true,
"signed_in_as": "\u2026",
"onboarded": true,
"plan": "\u2026",
"entitlement": {},
"upload_limit_mb": 0
}