Developers · API · Webhooks

One call sends the contract.Know the moment it's signed.

A REST API to send PDFs for signature and follow every signer, signed webhooks for each step, idempotency keys and stable error codes. An API key and webhooks on every plan: Free 10 documents a month, Branded 100 through the API, Enterprise without a cap.

See what you can build: signatures from your own software

First call: check the key. It sends nothing.

# Paste the full key — the dashboard only shows its prefix
export WESIGN_API_KEY="wsk_live_…"

# Sends nothing: checks the key and names its workspace
curl https://api.wesign.now/v1/me \
  -H "Authorization: Bearer $WESIGN_API_KEY"
# 200 → { "workspace": { … }, "key": { … }, "capabilities": { … }, … }

Then send a PDF to two signers.

# Paste the full key — the dashboard only shows its prefix
export WESIGN_API_KEY="wsk_live_…"

curl -X POST https://api.wesign.now/v1/signing-requests \
  -H "Authorization: Bearer $WESIGN_API_KEY" \
  -H "Idempotency-Key: quickstart-$(date +%s)" \
  -F "file=@contract.pdf" \
  -F "placement=auto_append" \
  -F 'signers=[
        { "email": "anna.muster@example.com",
          "name": "Anna Muster", "role": "counterparty" },
        { "email": "you@example.com",
          "name": "Your name", "role": "company" }
      ]'
# 201 → { "documentId": "…", "signers": [
#   { "role": "counterparty", "signingUrl": "…", "emailed": true },
#   { "role": "company",      "signingUrl": "…", "emailed": true } ] }
# Every answer carries an X-Request-Id header: quote it to
# support@wesign.now when something is off.
An API key on every plan

Get your API key

  • Free: 10 documents a month, the plan's own cap
  • Branded: 100 documents a month through the API
  • Enterprise: no cap
  1. 1. Sign up free.
  2. 2. Settings → Company → Developer settings → Turn on (on a personal account: Settings → Profile).
  3. 3. Settings → Developers → Create API key.
  4. 4. Call GET /v1/me with the key. It sends nothing and shows the key works.
What you get

An API, webhooks and docs your tools can read.

REST API

Send a PDF, follow each signer, remind or withdraw, and download the sealed PDF and its audit trail. Bearer keys, JSON responses and an OpenAPI 3.1 spec with an id for every operation.

API overview

Signed webhooks

signing_request.sent, .viewed, .signed, document.completed and more, each signed with HMAC-SHA256. A failed delivery is retried for about 45 hours; the delivery log lets you send it again.

Webhook events

Docs for AI assistants

llms.txt lists every docs page, llms-full.txt holds them all as plain text, and openapi.json the exact request and response shapes. Hand them to your coding assistant.

For AI assistantsMCP server: send and track from your agent

Concrete examples.

Four calls most integrations need. Field names as in the OpenAPI spec.

1. Send with anchor placement

Put a marker such as [[ls:signature:buyer]] in your PDF. We place the buyer's signature field there and mask the marker. No marker in the PDF? We append a signature page.

# offer.pdf contains the text [[ls:signature:buyer]]
curl https://api.wesign.now/v1/signing-requests \
  -H "Authorization: Bearer $WESIGN_API_KEY" \
  -H "Idempotency-Key: offer-2041/sign" \
  -F "file=@offer.pdf" \
  -F "placement=anchors" \
  -F 'signers=[{"email":"buyer@acme.com","role":"buyer","name":"Ann Buyer"}]'

2. Several signers, in order

Three signers, one after the other. Signer 2 is invited only after signer 1 has signed.

curl https://api.wesign.now/v1/signing-requests \
  -H "Authorization: Bearer $WESIGN_API_KEY" \
  -H "Idempotency-Key: round-a/sign" \
  -F "file=@contract.pdf" \
  -F "signing_mode=sequential" \
  -F "placement=auto_append" \
  -F 'signers=[
    {"email":"founder@acme.com","role":"founder"},
    {"email":"investor@vc.example","role":"investor"},
    {"email":"witness@law.example","role":"witness"}
  ]'

3. Webhook receiver

Check the timestamp and the HMAC over the raw body, then act on the event.

// Node + Express. The full verifier (Node and PHP) is in the docs.
app.post('/wesign/callback', express.raw({ type: 'application/json' }), (req, res) => {
  // X-WeSign-Signature: t=<unix seconds>,v1=<hex>  (two v1 for 24 h after a rotation)
  const parts = (req.get('x-wesign-signature') ?? '').split(',')
  const t = parts[0]?.startsWith('t=') ? parts[0].slice(2) : ''
  if (!t || Math.abs(Date.now() / 1000 - Number(t)) > 300) return res.status(401).end()
  const expected = crypto.createHmac('sha256', SECRET)
    .update(`${t}.${req.body}`).digest()
  const valid = parts.filter((p) => p.startsWith('v1=')).some((p) => {
    const got = Buffer.from(p.slice(3), 'hex')
    return got.length === expected.length && crypto.timingSafeEqual(got, expected)
  })
  if (!valid) return res.status(401).end()

  const evt = JSON.parse(req.body.toString('utf8'))
  if (evt.event === 'document.completed') {
    // fetch evt.signed_pdf_url with your API key, compare evt.sha256, keep a copy
  }
  res.sendStatus(200)
})

4. Idempotent retry

The same key with the same body within 24 hours replays the first response, so a retry after a network error never sends twice.

POST /v1/signing-requests
Idempotency-Key: order-123/sign

# First call:                      201 Created
# Same key + same body (24 h):     201, the same body, Idempotent-Replayed: true
# Same key while the first runs:   409 idempotency_in_progress + Retry-After
# Same key + a different body:     422 idempotency_key_reuse

Built to run in production.

Bearer keys, two scopes

Each key belongs to one workspace. A full key calls the whole API; an embedded key only manages embedded signing sessions. Limit a key to your IP addresses; revoking one takes effect at once.

60 requests per minute per key

One fixed window per key across all /v1 endpoints. Successful responses carry RateLimit-* headers; a 429 carries Retry-After.

Stable error codes

Every error is JSON with a readable error, a stable code and, where it helps, meta. Match on the code; the message may change.

Sealed, verifiable PDFs

The signed PDF carries a PAdES seal any compliant reader can check. The audit trail lists every event with its time, the signer's email and masked IP address, and every SMS-code check.

Get your API key and send your first contract today.

Sign up free, switch on developer settings and create a key. Enterprise adds unlimited API documents, embedded signing and template sends through the API: talk to us. The docs are public, so you can read them first.