Skip to content

Envelopes

The envelope lifecycle: create one from a PDF, add recipients, place fields with page coordinates, send, track and download the signed result.

On this page

An envelope is one or more PDFs sent to one or more recipients. It carries the recipients, the fields they fill, your message and metadata, and — once complete — the signed PDF and a certificate of completion.

Lifecycle

draft
created, editable
sent
out for signature
completed
everyone finished
declined
a recipient declined
voided
you cancelled it
expired
expiry date passed
A sent envelope ends as completed, declined, voided or expired. Only drafts can be edited or deleted.

Recipients have their own status: pending (not their turn yet) → sent (invited) → viewed → completed, or declined / delegated.

Create from a PDF

POST/v1/envelopes takes up to 10 PDFs (merged in order) plus everything else in one request. With send: true it goes out straight away; without it you get a draft to finish later.

curl -X POST https://signkoi.com/api/v1/envelopes \
  -H "Authorization: Bearer $SIGNKOI_API_KEY" \
  -H "Idempotency-Key: 5f1d7c1e-0b8a-4c2e-9f3d-61a2b7e4c905" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Consulting agreement — Acme Ltd",
    "files": [
      {
        "name": "agreement.pdf",
        "content_base64": "JVBERi0xLjcKJcfsj6IK…"
      }
    ],
    "message": {
      "subject": "Please sign: Consulting agreement",
      "body": "Hi Maya, here is the agreement we discussed."
    },
    "recipients": [
      {
        "key": "client",
        "name": "Maya Patel",
        "email": "maya@example.com",
        "verification": "email_otp"
      },
      {
        "key": "ceo",
        "name": "Rina Koh",
        "email": "rina@acme.example",
        "routing_order": 2
      },
      {
        "name": "Jonas Weber",
        "email": "jonas@example.com",
        "role": "cc",
        "routing_order": 3
      }
    ],
    "fields": [
      {
        "recipient_key": "client",
        "type": "signature",
        "page": 3,
        "x": 0.12,
        "y": 0.78,
        "width": 0.3,
        "height": 0.06
      },
      {
        "recipient_key": "client",
        "type": "date",
        "page": 3,
        "x": 0.12,
        "y": 0.86,
        "width": 0.2,
        "height": 0.04
      },
      {
        "recipient_key": "ceo",
        "type": "signature",
        "page": 3,
        "x": 0.58,
        "y": 0.78,
        "width": 0.3,
        "height": 0.06
      }
    ],
    "metadata": {
      "crm_deal_id": "D-10492"
    },
    "expires_in_days": 30,
    "reminders": {
      "delay_days": 2,
      "frequency_days": 3
    },
    "send": true
  }'
  • JSON: put each PDF in files[].content_base64. A data:application/pdf;base64, prefix and line breaks are fine; name is optional (defaults to document-1.pdf, …).
  • Multipart: upload file (one) or files[] (several), and pass recipients, fields, metadata, message and reminders as JSON strings.
  • title defaults to the first file name without its extension. Files have the same size limit as uploads on the website.
  • expires_in_days is one of 1, 3, 7 or 30 (or null for never); reminders take delay_days and frequency_days between 1 and 60.
  • Every envelope counts against the monthly allowance. Requests rejected by validation use none; if something fails after the upload, the envelope is removed and the allowance refunded.
Multipart upload
curl https://signkoi.com/api/v1/envelopes \
  -H "Authorization: Bearer $SIGNKOI_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -F "files[]=@agreement.pdf" \
  -F "files[]=@annex.pdf" \
  -F 'recipients=[{"key":"client","name":"Maya Patel","email":"maya@example.com"}]' \
  -F 'fields=[{"recipient_key":"client","type":"signature","page":3,"x":0.12,"y":0.78,"width":0.3,"height":0.06}]'

Recipients and routing

Recipient roles
RoleWhat they do
signerSigns remotely through an emailed link (default).
in_person_signerSigns on your device; no email. See embedded signing.
approverApproves the document without signing.
viewerMust open the document before it moves on.
ccGets a copy of the completed document; never holds up the order.
  • routing_order (default 1) sets the order. Recipients with the same number are invited together; higher numbers wait until everyone before them has finished.
  • language picks the language of their emails and signing page (en, es, fr, de, pt, it, nl, pl, ru, ja, zh, hi).
  • verification adds an identity check: access_code (you share the code yourself; pass it as access_code), email_otp, or sms_otp (needs phone in E.164 format). Codes are never returned by the API and phones come back masked.
  • Give a recipient a key (unique, up to 64 characters) to reference them from fields.

Changing recipients

Placing fields

Fields are positioned with page (1-based) and x, y, width, height as fractions of the page, measured from the top-left corner — the same system the website editor uses. Because they are fractions, the same numbers work for A4 and US Letter.

Field coordinates on a pageThe origin is the top-left corner of the page. x and width are fractions of the page width; y and height are fractions of the page height. The example field is at x 0.12, y 0.78 with width 0.3 and height 0.06.(0, 0)(1, 1)Signaturexywidthheightpage: 1x: 0.12y: 0.78width: 0.30height: 0.06
Coordinates are fractions (0–1) of the page, measured from the top-left corner — independent of page size.

To convert from PDF points (origin bottom-left), with a page of W × H points: x = left / W, y = (H − top) / H, width = w / W, height = h / H. Width must be at least 0.02 and height at least 0.01.

  • At creation, point a field at its recipient with recipient_key or recipient_index (0-based position in recipients; the key wins if you pass both).
  • On a draft, PUT/v1/envelopes/{id}/fields replaces all fields; each needs a recipient_id. Every field is recreated, so field ids change — don’t store them.
  • Signature, initials, date and input fields belong to a signer or in_person_signer. Approvers, viewers and cc recipients get no fields. Every signer needs at least one signature field.
  • Without any fields, Signkoi puts a signature box on the last page for the first signer.
Field types
TypeUse
signatureDrawn, typed or uploaded signature.
initialsInitials.
dateDate signed — filled automatically when the recipient finishes.
nameRecipient’s name, filled from their identity.
emailRecipient’s email, filled automatically.
companyCompany name, typed by the recipient.
titleJob title, typed by the recipient.
textFree text; optional validation (email, number, phone, zip, date).
numberA number.
checkboxTicked or not.
radioOne choice in a group — give every button of the group the same group_name.
dropdownOne choice from options (at least one).
attachmentThe recipient uploads a file.
formulaRead-only value computed from number fields, e.g. [qty] * [price].
noteRead-only text you place for the recipient to read (default_value).

Send

Send a draft with POST/v1/envelopes/{id}/send. Signkoi runs the same checks as the website and answers 422 with a code if something is missing:

Send errors
CodeFix
no_recipientsAdd at least one recipient who signs, approves or views.
missing_recipient_detailsGive every recipient a name and email (and a phone or access code if their verification needs one).
unassigned_fieldsAssign every field to a signer.
missing_signature_fieldGive every signer a signature field.
expiredChoose a later expiry.

Before sending you can still change the title, message, expiry and reminders with PATCH/v1/envelopes/{id}; after sending only metadata can change (409 envelope_not_draft otherwise).

Track progress

  • GET/v1/envelopes/{id} returns the envelope with every recipient’s status and timestamps, and its fields. Field values appear once the envelope is completed.
  • GET/v1/envelopes filters by status, search (title), created_after / created_before (inclusive), template_id and metadata[key].
  • GET/v1/envelopes/{id}/audit-trail lists every event, oldest first — without IP addresses or codes.
  • Best of all, let webhooks tell you when something changes.

Download the results

The files object holds download URLs; call them with your API key like any other endpoint.

Envelope files
FileEndpointAvailable
Original PDFGET/v1/envelopes/{id}/files/originalAlways
Signed PDFGET/v1/envelopes/{id}/files/signedWhen completed (before: 404 file_not_ready)
Certificate of completionGET/v1/envelopes/{id}/files/certificateWhen completed
curl https://signkoi.com/api/v1/envelopes/9b2f4c1e-7a3d-4e8b-9c51-2d6f8a0b3e47/files/signed \
  -H "Authorization: Bearer $SIGNKOI_API_KEY" \
  -o signed.pdf

The signed PDF is digitally sealed and timestamped; anyone can check it at signkoi.com/verify.

Void and delete

  • POST/v1/envelopes/{id}/void cancels an envelope that is out for signature. A reason is required and shown to the recipients who still had something to do.
  • DEL/v1/envelopes/{id} removes a draft for good. Sent envelopes can’t be deleted — void them.

Signing in your app

Want recipients to sign without leaving your product, or on a tablet at your desk? Create a signing URL for the active recipient — see Embedded signing.