Skip to main content
POST
Send a document that is not a template, and optionally send it.

Authorizations

Authorization
string
header
required

Authorization: Bearer vsk_live_…. Chosen over a bespoke X-API-KEY header because every client, proxy and log-redaction rule already knows this one. What a key may DO is its scopes — see x-scopes at the root of this document and x-required-scope on each operation. The scope list is not written here because OpenAPI reserves a requirement’s scope array for oauth2 and openIdConnect and requires it to be empty for an http scheme.

Headers

Idempotency-Key
string
required

Any string that identifies this request; a UUID is the usual choice, and at most 255 characters. ⚠️ REQUIRED. Without it a timeout is unresolvable: you cannot learn whether the envelope was created, and retrying sends the same document a second time. The caller’s own request identifier.

Example:

"01960000-0000-4000-8000-00000000ffff"

Body

application/json

The documents, the people, and whether to send.

The request.

title
string
required

What the signers see naming the document. Required — there is no template to borrow a name from.

Example:

"Offer of employment — A. Dlamini"

documents
object[]
required

The documents, base64-encoded, in the order a signer meets them. They are stacked into one scroll on the signing screen, and each is sealed on its own with its own Certificate of Completion. ⚠️ A PDF OR A WORD .docx, DECIDED BY THE BYTES AND NOT BY THE FILENAME — a .docx is converted to PDF on our side, and the envelope is over the converted PDF. Text tags survive that render, which is now OUR render rather than a step you take first. A tag addresses a page of the document it is written on, so <<sig:Employee>> on the annexure places a box on the annexure.

Required array length: 1 - 10 elements
recipients
object[]
required

⚠️ THE ORDER OF THIS ARRAY IS THE ROUTING ORDER, and each role is a slot a text tag can name — <<sig:Employee>> finds the recipient whose role is Employee. A tag naming anything else is refused rather than creating a role nobody fills.

Required array length: 1 - 100 elements
sender
string<uuid>

Which member of this organisation the signer is asked BY — it becomes the name on the invitation and on the Certificate of Completion. Omitted means the user who minted the key, which is a fallback rather than a choice: when that person leaves, every document still arrives from them.

Example:

"01960000-0000-4000-8000-000000000021"

signing_mode
enum<string>

Whether everyone is asked at once, or each in turn. Defaults to parallel.

Available options:
parallel,
sequential
Example:

"sequential"

send
boolean

Optional, default false. False creates a draft and emails nobody; true sends it, consuming the plan’s allowance and delivering to whoever’s turn it is. Embedded recipients are never emailed either way.

Example:

false

expires_at
string<date-time> | null

When the envelope stops being signable. Omitted means it does not expire.

Example:

"2026-10-31T23:59:59Z"

completion_delivery
enum<string>

Who tells the recipients the envelope is done and sends them the executed document. vumasign (the default for a send from the dashboard) means we email the sender and every recipient we are able to email, with the sealed PDF attached. integrator (the default for a send made with an API key) means we send nothing at completion and you do it. Omit it and the origin of the send decides — an envelope created with send: false and then sent from the dashboard is vumasign. It cannot be changed once the envelope has been sent.

⚠️ AN embedded RECIPIENT IS NEVER EMAILED, WHATEVER THIS SAYS. We issue one no signing link and send them no invitation, because their address may be an identifier of yours rather than a mailbox — so they are not sent the completed document either, even under vumasign. Delivering the executed document to an embedded recipient is yours on every envelope, and this field only decides who tells everybody else.

⚠️ IF YOU TAKE THIS ON, SUBSCRIBE TO envelope.sealed RATHER THAN envelope.completed. envelope.completed fires when the last person signs, which is about a minute before the executed document exists, and envelope.sealing_failed tells you it never will.

Available options:
vumasign,
integrator

Response

The envelope, as it stands, with template_id null. Idempotency-Replayed says whether this request created it (false) or is being shown an earlier one’s result (true); the status is 201 either way, so a client branching on it behaves identically on a retry.

The envelope.

id
string<uuid>
required

The envelope’s id. A bare uuid.

status
string
required

draft or sent from this endpoint. Later states arrive as people act.

template_id
string<uuid> | null
required

The template this was made from, or null when there was none — an envelope created by POST /api/v1/envelopes/one-off carries the document itself and never had a template. Branch on null, never on the empty string.

title
string
required

What the signers see naming the document. Defaults to the template’s name.

created_at
string<date-time>
required

ISO 8601, UTC.

sent_at
string<date-time> | null
required

ISO 8601, UTC. Null while it is a draft.

expires_at
string<date-time> | null
required

ISO 8601, UTC. Null when this envelope has no deadline, which is the default. Read back from the stored value rather than echoed, so an offset you sent comes back as the same instant in UTC.

recipients
object[]
required

In routing order.