Signatures

Envelope Attachment Upload

POST
/signatures/envelope/{envelopeId}/attachment/upload

Uploads one or more supporting files onto an envelope. Attachments are normally added by a recipient during their signing session rather than by the sender up front — supporting evidence, a counter-signed copy, identification, whatever the agreement calls for. Depending on the envelope configuration they are either embedded into the completed PDF or delivered alongside it as email attachments, and either way the upload is recorded in the audit trail.

That is why this operation has two authentication modes, and exactly one applies per call. Supply a Guid-parseable tid query parameter and the request is anonymous — no Authorization header is needed, because the transaction token already identifies one recipient on one envelope. Supply no valid tid and a bearer token is required instead, and the caller must be the envelope's creator or a signer on it. This mirrors the signatures-envelope-attachment-download.

The request must be multipart/form-data; there is no raw-body or JSON alternative. No extension or content-type validation is performed, so any file type is accepted — this is the only upload operation in the API without a format restriction. Maximum file size is 20 MB in Production and 10 MB in Staging. A file over that limit is rejected by the web server before the operation runs, so it surfaces as a 500 rather than a validation error.

Each stored file is assigned an id, returned in form-data order, which the signatures-envelope-attachment-download uses to fetch it back.

Authorization

AuthorizationBearer <token>

JWT token to authenticate the request.

In: header

X-Api-Key<token>

API key, sent as a request header.

In: header

Path Parameters

envelopeId*string

GUID of the envelope to attach the file(s) to.

Formatuuid

Query Parameters

tid?string

Transaction token identifying a specific recipient+envelope pair. When present and Guid-parseable, selects anonymous mode and no Authorization header is required. When absent or not Guid-parseable, authenticated mode applies and Authorization is required instead.

Formatuuid

Request Body

multipart/form-data

TypeScript Definitions

Use the request body type in TypeScript.

body?unknown

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/signatures/envelope/3fa85f64-5717-4562-b3fc-2c963f66afa6/attachment/upload" \  -F file="[]"
{  "result": {    "data": {      "files": [        {          "id": "76bb2621-b1b1-4d47-9132-c4d1e5f60abc",          "fileName": "SampleAttachment.jpg"        }      ]    },    "statusCode": 201,    "message": "Created"  },  "origin": "POST https://api.doctavian.com/v1/signatures/envelope/{envelopeId}/attachment/upload",  "dateTime": "2025-11-03T06:48:58.000Z",  "operationId": "0aec7252e3f0188d6d433f64597b9b04",  "userId": "671207fd-8f02-46ef-9c80-d5f1c7cb8812"}
{  "error": {    "statusCode": 400,    "message": "Request must be multipart/form-data.",    "innerErrors": [      {        "code": "FORM_DATA_EXPECTED",        "message": "Request must be multipart/form-data.",        "userMessage": "Request must be multipart/form-data."      }    ]  },  "origin": "POST https://api.doctavian.com/v1/signatures/envelope/{envelopeId}/attachment/upload",  "dateTime": "2026-07-14T09:32:15.000Z",  "operationId": "3a4b5c6d7e8f90112233445566778899",  "userId": "90b58cca-d752-41be-8586-75f8317feedb"}
{  "error": {    "statusCode": 401,    "message": "The request could not be authenticated.",    "innerErrors": [      {        "code": "UNAUTHORIZED",        "message": "The request could not be authenticated.",        "userMessage": "Your session has expired or is invalid. Please sign in again."      }    ]  },  "origin": "POST https://api.doctavian.com/v1/signatures/envelope/{envelopeId}/attachment/upload",  "dateTime": "2026-07-14T09:32:15.000Z",  "operationId": "3a4b5c6d7e8f90112233445566778899",  "userId": "1cbfbdf9-f08a-4fc3-b08c-b06f6c7f06a8"}
{  "error": {    "statusCode": 403,    "message": "The envelope owner's subscription is not active.",    "innerErrors": [      {        "code": "ENVELOPE_OWNER_INVALID_SUBSCRIPTION",        "message": "The envelope owner's subscription is not active.",        "userMessage": "This envelope can't accept uploads right now."      }    ]  },  "origin": "POST https://api.doctavian.com/v1/signatures/envelope/{envelopeId}/attachment/upload",  "dateTime": "2026-07-14T09:32:15.000Z",  "operationId": "3a4b5c6d7e8f90112233445566778899",  "userId": "ecc29b8d-28a3-4d85-8a33-eb6452c2b680"}
{  "error": {    "statusCode": 404,    "message": "Envelope not found for the supplied user and envelope id.",    "innerErrors": [      {        "code": "ENVELOPE_NOT_FOUND_USER_AND_ENVELOPE_ID",        "message": "Envelope not found for the supplied user and envelope id.",        "userMessage": "We couldn't find that envelope, or you don't have access to it."      }    ]  },  "origin": "POST https://api.doctavian.com/v1/signatures/envelope/{envelopeId}/attachment/upload",  "dateTime": "2026-07-14T09:32:15.000Z",  "operationId": "3a4b5c6d7e8f90112233445566778899",  "userId": "065f3725-a4d0-494b-b2f7-1b81bf93c61f"}
{  "error": {    "statusCode": 500,    "message": "Failed to persist the uploaded file to storage.",    "innerErrors": [      {        "code": "FILE_UPLOAD_FAILED",        "message": "Failed to persist the uploaded file to storage.",        "userMessage": "Something went wrong while uploading. Please try again or contact support."      }    ]  },  "origin": "POST https://api.doctavian.com/v1/signatures/envelope/{envelopeId}/attachment/upload",  "dateTime": "2026-07-14T09:32:15.000Z",  "operationId": "3a4b5c6d7e8f90112233445566778899",  "userId": "13d5b65f-91f5-4748-8d47-bbc8768c99cb"}