Attestation API Reference
Authenticate with an API key and submit documents for attestation on the Canton Network, poll batch status, retrieve failures, and list what has been anchored.
The attestation API lets a system submit documents for anchoring on the Canton Network in batches, either synchronously or through a background queue, and read back status and results. Authentication is by API key. Requests and responses are JSON.
Base URL
Coming soon
A separate devnet base URL is available for integration testing. Ask your account contact.
Authentication
Every request to a protected route carries your API key in a header:
x-api-key: <your key>
Keys are issued once and shown once. We store only a hash. A request without a valid key receives 401 Unauthorized. Each key is bound to a Canton party, which becomes the originator of every document it submits. Treat keys as secrets, rotate them on a schedule, and request a new key immediately if one is exposed.
Choosing a submission mode
| Mode | Endpoint | Use when |
|---|---|---|
| Synchronous | POST /api/batch | You have a handful of documents and want the result in the response. The request blocks until every document is anchored. |
| Queued | POST /api/batch-worker | You have up to 100 documents and want an acknowledgment before they are processed, then poll for progress. The normal choice for integrations. |
| Bulk | POST /api/bulk-worker | Same payload and response as queued, processed as a single bulk job. Use for large scheduled runs. |
Queued and bulk submissions return a batchId. Poll GET /api/batch-status/{id} until the status is terminal, then fetch any failures with GET /api/failed-batch/{id}.
The document object
Every submission is an array of documents.
| Field | Type | Required | Description |
|---|---|---|---|
signersList | string[] | yes | Canton party IDs of the parties who signed the document. Each becomes a stakeholder in the signed-document contract. |
content | string | yes | The document content. For queued and bulk submissions the maximum is 2,000 characters. |
metadata | string | yes | Free-form metadata recorded with the document. |
filename | string | no | A name for the document. If omitted, the document's hash is used as its name. |
observers | string[] | no | Canton party IDs granted read visibility of the document's metadata contract. Each observer sees the contract. Observers do not see each other. |
Party IDs take the form name::fingerprint, for example acme-legal::1220ab....
Endpoints
POST /api/batch
Anchors every document in the batch before responding.
Request body:
{
"batch": [
{
"signersList": ["acme-legal::1220ab..."],
"content": "Master services agreement, executed 2026-09-01.",
"metadata": "MSA / Acme / 2026",
"filename": "acme-msa-2026.txt",
"observers": ["acme-audit::1220cd..."]
}
]
}
Response 200:
| Field | Type | Description |
|---|---|---|
received | integer | Documents received |
processed | integer | Documents processed, successes and failures |
completed | integer | Documents anchored successfully |
status | ok, partial, failed | Overall result |
createdMetadata | string[] | Contract IDs of the created metadata contracts, one per anchored document |
signedContracts | string[] | Contract IDs of the created signed-document contracts |
observersAdded | string[] | Observer party IDs that were granted visibility |
errorMsgs | string[] | One message per failed document |
Errors: 400 malformed request, 401 missing or invalid key, 500 server error.
POST /api/batch-worker
Queues the batch and responds before processing it. Maximum 100 documents. Content up to 2,000 characters each.
Request body: as for /api/batch.
Response 200:
| Field | Type | Description |
|---|---|---|
batchId | uuid | Identifier to poll |
receivedDocs | integer | Documents accepted into the queue |
statusBatch | string | Initial status, normally queued |
errors | string[] | Validation messages, if any |
Errors: 400 malformed request, 401 missing or invalid key, 500 server error, including a batch larger than 100 documents.
POST /api/bulk-worker
Identical request and response to /api/batch-worker, processed as a single bulk job.
GET /api/batch-status/{id}
Returns the current state of a queued or bulk batch.
Response 200: the same object as the queued response, with statusBatch advancing through these values:
statusBatch | Meaning |
|---|---|
queued | Waiting to be processed |
in-progress N/M | N of M documents processed so far |
ok | Every document anchored |
finished with errors: ok -> N; failed -> M | Some documents failed; fetch them from /api/failed-batch/{id} |
failed | Every document failed |
Errors: 404 unknown batch, 500 server error.
Poll no more often than every few seconds. A batch is terminal when statusBatch is ok, failed, or begins with finished with errors.
GET /api/failed-batch/{id}
Returns the documents that failed in a batch, each with its original inputs, so you can correct and resubmit them.
Response 200:
{
"batch": [
{ "signersList": ["..."], "content": "...", "metadata": "...", "filename": "...", "observers": [] }
]
}
Response 404 when the batch exists but no documents failed, or when the batch is unknown.
GET /api/list-status
Returns the last 20 batch statuses.
Response 200: an array of objects with batchIdFront (the batch UUID) and batchStatusFront (its status string).
GET /page/{id}
Returns anchored documents for the calling party, 20 per page, starting at page 1.
Response 200:
| Field | Type | Description |
|---|---|---|
originator | string | The party ID the documents were anchored under |
found | integer | Total documents found |
documents[] | object | One per document: contractId, documentHash (SHA-256), documentName |
Errors: 404 page beyond the last, 503 server still initializing.
GET /api/download/{contractId}
Returns the stored content of a document by its metadata contract ID as text/plain. Requires a valid API key bound to a party with access to the document.
Errors: 401 missing or invalid key, 404 unknown contract, 500 retrieval failed.
Errors
Every error response has the shape:
{ "error": "human-readable message" }
| Status | Meaning |
|---|---|
400 | The request body did not validate. The message says which field. |
401 | Missing or invalid x-api-key. |
404 | The batch, page or document does not exist, or no failures were recorded for the batch. |
500 | The server could not complete the request. Safe to retry queued submissions. Check /api/list-status first to avoid duplicates. |
503 | The service is starting. Retry after a short delay. |
What is anchored, and where the content goes
For each document the service records a metadata contract on the Canton Network containing the document's hash and its originator, and a signed-document contract linking the parties in signersList. Observers are granted visibility of the metadata contract only. The document content is encrypted and stored off-chain, and is never written to the ledger. Parties that store the document do not see the signers.
Rate and size limits
| Limit | Value |
|---|---|
| Documents per queued or bulk batch | 100 |
| Content length, queued and bulk | 2,000 characters per document |
Batch statuses returned by /api/list-status | 20 most recent |
Page size for /page/{id} | 20 documents |
Retries and idempotency
Queued submissions are acknowledged before processing, so a network failure after you send but before you receive the batchId can leave a batch you cannot reference. Before resubmitting, call /api/list-status and look for a batch matching your expected document count and time. Synchronous submissions either complete or return an error. On a timeout, check /page/{id} for the documents' hashes before resubmitting.
Webhooks from DocuSign
The service also receives DocuSign Connect events at POST /webhook, which is unauthenticated by design because DocuSign must be able to reach it. It is not part of the customer API. See DocuSign Integration.