API guide

For websites that send documents to their own users and want WriteSign to run the signing: InCorp InSys sending a service of process acceptance to a client, for example. The integrating site keeps its own account system; WriteSign verifies the signer (text code to the mobile the site supplies, plus the link the site hands to its signed-in user), runs the ceremony on any device, seals the result, and reports back.

Base URL https://www.writesign.com/api/v1. Auth header Authorization: Bearer ws_live_.... JSON in, JSON out. Errors are { "error": "<code>", "message": "<plain words>" } with a 4xx status.

Keys

Sign in at https://www.writesign.com/login/, then POST /api/keys {"name":"insys"} with the session (the dashboard will get a button for this). The key is shown once. GET /api/keys lists prefixes; DELETE /api/keys/:id revokes. The account must be approved by WriteSign before it can send (account_not_approved otherwise). Keys are limited to 600 calls an hour.

Documents

POST /documents {"title": "...", "body": "..."} -> { id, doc_hash, roles, fields }. Body syntax: # heading, ## subheading, - bullet, 1. numbered, blank line between paragraphs, and inline fields [[signature:signer1]], [[initials:signer1]], [[date:signer1]], [[text:signer1:Label]], [[checkbox?:signer1:Label]] (? = optional). A document is immutable once created; its hash roots the evidence chain.

Envelopes

POST /envelopes

{ "document_id": "...", "signers": [{ "role": "signer1", "name": "Ada Lovelace", "email": "[email protected]", "mobile": "+17025550100" }],
  "order_mode": "parallel", "message": "optional", "expires_days": 14, "reference": "INC-12345", "deliver": "link", "send": true }
  • deliver: "email" (default): WriteSign emails each signer the link. deliver: "link": no email; the send response carries signing_url per signer whose turn it is, ONCE (the raw link is never stored), for the site to open or send itself. Keep it; a lost link needs a new envelope or a resend. The signer still gets the text code on the mobile given. The ledger records the link as issued to the sender's system.
  • reference is the sender's own id (searchable in the dashboard, echoed in webhooks).
  • Response and GET /envelopes/:id: `{ id, title, status, reference, verify_code, verify_url, signers:[{ id, role, name, email, status, completed_at, declined_at, signing_url }], seal, download_url }`. Status: draft, sent, in_progress, sealing, completed, declined, voided, expired.
  • POST /envelopes/:id/send (for send:false drafts), POST /envelopes/:id/void, GET /envelopes/:id/pdf (sealed PDF).

Webhooks

POST /webhooks {"url":"https://..."} -> { id, url, secret } (secret shown once). Events envelope.completed, envelope.declined, envelope.voided, envelope.expired are POSTed as JSON with headers X-WriteSign-Event and X-WriteSign-Signature = HMAC-SHA256(secret, rawBody) in hex. Answer 2xx; failures retry with backoff for about a day. Payload: { event, at, envelope:{ id, title, status, reference, verify_code, download_url, seal }, signers:[...], reference }.

Verification

Anyone can confirm a document at https://www.writesign.com/verify/?code=XXXX-XXXX-XXXX or by uploading the PDF, and GET /api/verify/:code is public.