Skip to main content
Adding a document to a case takes two API calls: upload the file, then save its reference in a case field. Uploading alone does not attach anything to the case — the second call is what places the document on it. Check these three points before you build on this sequence:
  • Uploading requires a workspace API token (pnbx_…). A user token obtained through OAuth is rejected on the upload endpoint.
  • Downloads have a lower size limit than uploads: 10 GB up, 50 MB back. Check the download limit before uploading documents you need to retrieve through the API.
  • Saving a document on a field does not run Document Intelligence. Extraction on this path is an explicit call — see Extract data from the document.

Before you start

You need: The examples below use these values:
1

Upload the file

Send the file as multipart/form-data:
Response 201, partial:
Keep id, name and type. The next call needs all three.The full response also returns the uploaded file itself, base64-encoded, in a data field. Read the three fields you need and discard the rest, and size your HTTP client’s response buffer for the file you are sending rather than for the fields you keep.The response does not carry the file size. Take it from the file on disk if you want to store one.
2

Save the reference in the case field

Write the reference into signed_contract. The same call sets any other field, so send the scalar values you already have in the same request:
id, name and type are the reference. size is optional.
Always send the complete { id, name, type } reference. The endpoint does not validate this value, so a bare id string, or an id that does not exist, can be saved successfully and then fail to display or download.
Response 200, partial:
3

Retrieve the document

GET /v1/cases/{id} returns the reference under schema.data[] | select(.key == "signed_contract") | .value.To get the file itself, call the attachment endpoint. It returns JSON with the content base64-encoded in data:
This response is limited to 50 MB. A larger document returns 400 and cannot currently be retrieved through the API. Keep documents you need to download under 50 MB, or deliver them to your recipients by another route.

Upload as JSON instead of multipart

Send the file base64-encoded in data:
Two differences from multipart:
  • The MIME type comes from the extension of name. A type field in the body is not used, and a name without an extension produces application/octet-stream. Use multipart when the MIME type matters.
  • Base64 inflates the payload by about a third, and the 10 GB limit applies to what is transmitted. The largest file you can send this way is roughly 7.5 GB.

Save several files on one field

A field configured with multiple: true takes an array of references:
The array replaces the previous value. Include the files already on the field to keep them.

Upload before the case exists

An attachment does not need a case, so you can upload first and pass the reference as a field value when you create the case:

Extract data from the document

The automatic extraction configured on a file field runs when a person uploads the document in the app or in a form. Saving a reference through the API does not trigger it. To extract from a document uploaded through the API, call POST /v1/document_intelligence with the same reference, then write the values it returns with a second POST /v1/cases/{id}/data.

The whole sequence in one script

Limits and behaviours

Create a Case via the API

Opening the case this document goes on

Upload Attachment

The endpoint reference, with every parameter

File Field

Configuring a file field in a case template

Document Intelligence

Extracting structured data from a document