Outcome
Read the hash-verified signing PDF derived from the retained source in the exact granted workspace. The SDK returns contentType, contentLength and contentBase64.
Before you start
- Verify the environment, authenticated identity and specifically approved organization context.
- The published application permission is workspace:read. Resolve and bind the exact canonical Sign workspace. A supplied id or organization membership alone grants no workspace access.
- Session callers require read workspace access. API-key resource binding is verified by Auth; never treat a caller-supplied header as an independent grant.
Discover the target
topolo whoami --json
topolo actions get app_topolo_sign.documents.pdf.get --detail --json
topolo resources topolo-sign --json
topolo workspaces list topolo-sign --json
- Set SIGN_WORKSPACE_ID to the exact granted workspace returned by discovery.
- Discover documentId and documentRef from upload or authorized retained metadata; they are distinct identifiers.
Request
GET /api/documents/{documentId}/pdf
Inspect and test this action. Save the reviewed input as payload.json. Supply resource context separately.
Input fields
| Field | Required | Meaning | Constraints |
|---|---|---|---|
documentId | Required | Exact document.id returned by upload or retained metadata. This is different from documentRef. | {"minLength":1} |
Read the complete input schema.
Effects
- Reads retained bytes with existing workspace:read authorization. No agreement, consent or recipient data is changed.
- The server verifies stored object SHA-256 before returning bytes. Artifact download records an existing operational download event.
Interpret the response
Binary transport returns no resource identifier. Retain the authorized input documentId or envelopeId; decoded bytes are the downloaded artifact.
Read documents.get with the retained documentId in the same granted workspace. Base64-decode contentBase64 and compare its byte length with contentLength. SHA-256 the decoded bytes and compare with pdfSha256 from the authorized metadata read. Never hash the Base64 string. The SDK binary projection contains bytes and type, not a new document id or filename. Retain the input identifier and choose a local filename deliberately.
Inspect the success schema. CLI/MCP add their transport envelope; --detail requests the full CLI result. HTTP 204 contains no JSON payload.
Worked examples
Captured from the exported Sign Worker with the existing SQLite-backed D1 harness applying all core, envelope and audit migrations to one local database, in-memory R2 and synthetic Auth/workspace/archive/Notify transports. These examples prove local validation, persistence and artifact production. They do not prove separate deployed D1 topology, real recipient consent, provider delivery or a live signed agreement. All identities, signing links and documents are synthetic; replace identifiers through authorized discovery and never execute a fixture against a live organization. Binary download examples use the released SDK binary projection; tests Base64-decode and compare original bytes, lengths and server SHA-256 headers.
Supported request · Read signing PDF bytes and verify the retained SHA-256
Input · payload.json:
{
"documentId": "92c3741e-171c-439c-9419-597ffe485224"
}
CLI:
topolo actions validate app_topolo_sign.documents.pdf.get --data @payload.json --json
topolo actions plan app_topolo_sign.documents.pdf.get --resource-type workspace --resource-id "$SIGN_WORKSPACE_ID" --data @payload.json --json
topolo actions call app_topolo_sign.documents.pdf.get --resource-type workspace --resource-id "$SIGN_WORKSPACE_ID" --data @payload.json --detail --json
MCP tool and arguments:
{
"tool": "topolo_read_action",
"arguments": {
"actionId": "app_topolo_sign.documents.pdf.get",
"input": {
"documentId": "92c3741e-171c-439c-9419-597ffe485224"
},
"resourceType": "workspace",
"resourceId": "<exact granted id from discovery>",
"detail": true
}
}
Captured canonical SDK binary projection of the exported Worker response · HTTP 200:
{
"contentType": "application/pdf",
"contentLength": 861,
"contentBase64": "JVBERi0xLjcKJYGBgYEKCjYgMCBvYmoKPDwKL0ZpbHRlciAvRmxhdGVEZWNvZGUKL0xlbmd0aCAxMDYKPj4Kc3RyZWFtCnicHYqxCsJAEAX79xVbC+LuebfvDsRCECxshP0BkSQYYqFIvj9GBoYp5o1TQGXlM2B36aa5+z4f9y211VyVtYlliR7p5yvsv5owCVUlXjhk98bKzMLkJSnVzbnW3o4SI2KDc+CGBUGCF4sKZW5kc3RyZWFtCmVuZG9iagoKNyAwIG9iago8PAovRmlsdGVyIC9GbGF0ZURlY29kZQovVHlwZSAvT2JqU3RtCi9OIDUKL0ZpcnN0IDI2Ci9MZW5ndGggMzYxCj4+CnN0cmVhbQp4nNVS30vDMBB+z19xj/ogSdM2aWUMtrVVkKFsgqL40LVhVEYibSbzv/eu7SZ7EJ+lfCR3992v9AtAgIQoghB0AhHEoYQYVBDBZML449eHAf5Qbk3H+F1Td/CKUQEreGN84fbWQ8CmU/bDXZS+3LktG5IgIPKR8dC6el+ZFiZFXhRCaCGEihBKCJnhuUCkCIk2xmSCd4SORqBPh0KEM4wVA5Qecijec+MxP8cTuYo42cCNksE+9aVe+VBD/jVPOmV86eqs9AYusmsppAqEiIOEWr9c4nO0pvTu/y7Xz984++uGZ/+5cNYzvt5vfG+SM2B8XnaGIsBvze7T+KYqGc9t5erGboE/NXZmu+boOK9IgiHZtIZU1euGr0zn9m2FQiJeX5kup+JXWqQJbq6TFLU7So0/32/eTdVTycwP/mbtaavBQb6lqZty7g6oZ4GfCiToVJKqZ9Y6TzrvFW49TkOWGlWPyd+DGcXqCmVuZHN0cmVhbQplbmRvYmoKCjggMCBvYmoKPDwKL1NpemUgOQovUm9vdCAyIDAgUgovSW5mbyAzIDAgUgovRmlsdGVyIC9GbGF0ZURlY29kZQovVHlwZSAvWFJlZgovTGVuZ3RoIDQwCi9XIFsgMSAyIDIgXQovSW5kZXggWyAwIDkgXQo+PgpzdHJlYW0KeJwVxLERACAMA7G3wx0ts7MSgyVYhYBusyEpOVVa4oB4P18YYXADoAplbmRzdHJlYW0KZW5kb2JqCgpzdGFydHhyZWYKNjU4CiUlRU9G"
}
HTTP 200. Read documents.get with the retained documentId in the same granted workspace. Base64-decode contentBase64 and compare its byte length with contentLength. SHA-256 the decoded bytes and compare with pdfSha256 from the authorized metadata read. Never hash the Base64 string. The SDK binary projection contains bytes and type, not a new document id or filename. Retain the input identifier and choose a local filename deliberately.
Refused request · HTTP 401
Input · payload.json:
{
"documentId": "3314b7c7-66d1-4b67-83ca-b359421163a5"
}
CLI:
topolo actions validate app_topolo_sign.documents.pdf.get --data @payload.json --json
topolo actions plan app_topolo_sign.documents.pdf.get --resource-type workspace --resource-id "$SIGN_WORKSPACE_ID" --data @payload.json --json
Captured exported Worker response · HTTP 401:
{
"error": "Token validation failed"
}
HTTP 401. Resolve the exact refusal before retrying. This request is not a successful workflow.
Refused request · HTTP 403
Input · payload.json:
{
"documentId": "synthetic-unresolved-fixture"
}
CLI:
topolo actions validate app_topolo_sign.documents.pdf.get --data @payload.json --json
topolo actions plan app_topolo_sign.documents.pdf.get --resource-type workspace --resource-id "$SIGN_WORKSPACE_ID" --data @payload.json --json
Captured exported Worker response · HTTP 403:
{
"error": "You do not have access to this workspace",
"code": "workspace_forbidden"
}
HTTP 403. Resolve the exact refusal before retrying. This request is not a successful workflow.
Verify the result
- Read documents.get with the retained documentId in the same granted workspace.
- Base64-decode contentBase64 and compare its byte length with contentLength. SHA-256 the decoded bytes and compare with pdfSha256 from the authorized metadata read. Never hash the Base64 string.
- The SDK binary projection contains bytes and type, not a new document id or filename. Retain the input identifier and choose a local filename deliberately.
Errors and recovery
document_not_found(HTTP 404): Resolve document.id from the retained authorized upload; documentRef is a different identifier.document_asset_not_found(HTTP 404): Retained metadata exists but its stored object is unavailable. Preserve the request id and expected hash; do not replace an immutable source to mask missing storage.document_integrity_failed(HTTP 500): The stored source does not match its retained SHA-256. Stop using it and report the exact document and request id; do not accept or recompute a replacement hash.auth_error(HTTP 401): Reauthenticate in the same approved context before retrying.workspace_forbidden(HTTP 403): Discover the actual workspace grant and obtain the documented required access; do not retry with a guessed workspace or broader organization.
Some existing refusals return a human message as error rather than a stable code; preserve the actual response, status and request id. Platform validation, authentication and resource checks can refuse before the handler.
Recovery boundary
A download changes no agreement. Resolve the actual grant and artifact readiness, then repeat the same read. Never recreate or re-sign an agreement to make a download succeed.
Related actions
- Get Sign document metadata: Get metadata for an uploaded signing document: title, content type, size, original and signing-PDF SHA-256, version and predecessor, page count and page sizes, and upload provenance. The bytes are downloaded separately.
Evidence
Captured from the exported Sign Worker with the existing SQLite-backed D1 harness applying all core, envelope and audit migrations to one local database, in-memory R2 and synthetic Auth/workspace/archive/Notify transports. These examples prove local validation, persistence and artifact production. They do not prove separate deployed D1 topology, real recipient consent, provider delivery or a live signed agreement. All identities, signing links and documents are synthetic; replace identifiers through authorized discovery and never execute a fixture against a live organization. Binary download examples use the released SDK binary projection; tests Base64-decode and compare original bytes, lengths and server SHA-256 headers.