Verafirma logo Verafirma

Envelopes

An envelope is one PDF sent to one or more recipients for signature. It’s the fundamental unit of work: when callers think about “send a contract” or “collect a signature on this document,” they’re thinking about an envelope.

The pieces

Envelope

The container. Carries:

  • A PDF. Either uploaded directly (multipart form on POST /v1/envelopes) or instantiated from a template.
  • A title. Free-text label for the customer side; appears in dashboards and notification emails.
  • A status. Tracks the envelope’s lifecycle.
  • A storage expiry. Optional; the underlying signing engine retains the completed PDF for the configured number of days, after which it’s purged.

Recipient

A person or role that interacts with the envelope. One envelope can have up to ten recipients in V1. Each recipient has:

  • Email. Where the signing-link notification is sent.
  • Name. Displayed in the signing UI.
  • Role. One of:
    • SIGNER — adds a binding signature.
    • APPROVER — must approve before signers can sign (sequenced workflows).
    • VIEWER — can read the envelope but doesn’t sign.
    • CC — receives a copy of the completed envelope but doesn’t interact.
    • ASSISTANT — fills fields on behalf of a signer (delegated data entry, no signature authority).

Field

A placeable element on the PDF. Coordinate-based (percentage of page) OR PDF-placeholder-marker-based ({{signature, r1}} literals embedded in the source PDF).

Field types:

SIGNATURE, INITIALS, NAME, EMAIL, DATE, TEXT, NUMBER, CHECKBOX, RADIO, DROPDOWN.

Each field is bound to one recipient via their email; only that recipient can fill the field.

Template

A saved envelope definition. PDFs + field placements + recipient roles, parameterized so a new envelope can be instantiated from the template with just-the-recipients-changed.

Templates are esignature-specific; they don’t surface on the lodestone path (which is single-shot by design). Created via POST /v1/templates; instantiated via POST /v1/templates/{id}/from-template.

Lifecycle

DRAFT → PENDING → SENT → PARTIALLY_SIGNED → COMPLETED

With three alternative terminal states:

SENT → REJECTED   (a signer rejected; flow halts; refund-on-terminal triggers)
SENT → EXPIRED    (the signing window closed without all signers; refund-on-terminal triggers)
SENT → CANCELLED  (the customer or operator cancelled; refund-on-terminal triggers)

The four terminal states (COMPLETED, REJECTED, EXPIRED, CANCELLED) are the only states from which an envelope cannot transition.

DRAFT is the initial status when POST /v1/envelopes is called without a fields array. Mutations on the draft (POST /:id/fields, DELETE /:id/fields/{fid}) only work while the envelope is DRAFT. Once POST /:id/send distributes the envelope, no more field changes are allowed.

For the simple workflow — one PDF, fields known up front — call POST /v1/envelopes with the fields array included in the payload, and the envelope skips DRAFT and goes straight to PENDING/SENT.

Sending and signing

Distribution

When an envelope transitions to SENT, each recipient gets a signing-link email from the underlying signing engine. The link carries a token bound to that recipient; opening it loads the signing UI with their fields pre-targeted.

Signing

The signing UI is hosted by the underlying signing engine (Documenso) at sign.verafirma.com. Signers fill their fields, click sign, and the engine generates a signed-PDF artifact bound to the envelope. When all SIGNER recipients have signed, the envelope transitions to COMPLETED.

The signing UI reflects the operator’s brand — the API consumer doesn’t supply a signing UI; the wrapped engine handles it.

Reminders

Recipients who haven’t signed get periodic reminder emails (cadence configured at the engine). The customer can also chase manually:

curl -X POST https://api.verafirma.com/v1/envelopes/{id}/resend \
  -H "Authorization: Bearer vf_live_..."

This re-sends the signing link to NOT_SIGNED recipients without changing the envelope’s state.

Cancellation

A SENT envelope can be cancelled before all signatures land:

curl -X DELETE https://api.verafirma.com/v1/envelopes/{id} \
  -H "Authorization: Bearer vf_live_..."

Cancellation transitions the envelope to CANCELLED and triggers the refund-on-terminal flow (the original charge is refunded up to the per-envelope cap).

Reading state

Cached vs. live

Two read endpoints with different freshness:

  • GET /v1/envelopes/{id} — returns the wrapper’s cached state. Fast (sub-100ms typically); reflects whatever the wrapper last persisted from a webhook event or read.
  • GET /v1/envelopes/{id}/status — fetches authoritative state from the underlying signing engine, reconciles the cache if it had drifted, and returns the live shape.

Use /status when accuracy matters (e.g. before completing a downstream action that depends on signature completion). Use the cached read for high-volume polling where eventual consistency is fine.

Listing

GET /v1/envelopes?limit=&offset=&status= returns paginated envelopes for the authenticated customer. The status filter is exact-match against the V1 status enum.

Downloading

GET /v1/envelopes/{id}/download?version=signed streams application/pdf. Only available when the envelope is COMPLETED. The version query is signed (default — the signed artifact) or original (the source PDF before signing).

Limits

V1 caps each envelope at:

  • ≤10 signers AND ≤10 documents. Anything larger returns 400 OUT_OF_SCOPE_V1.

These limits are tunable post-deploy (per the operator’s configuration surface) but the V1 defaults won’t move without explicit operator action. If you have a use case that needs >10 of either, contact the operator.

Pricing

$0.10 per envelope, charged at creation. Refunded on terminal failure (REJECTED, EXPIRED, CANCELLED) up to a configurable per-envelope cap. See /pricing for the per-mode breakdown.