Help guides

How the API and webhooks work together

SignSwifly gives your own systems two ways to work with your envelopes. The API is how your system asks SignSwifly to do something, or to tell it something: send this lease, how far has it got, give me the signed copy. Webhooks are how SignSwifly tells your system that something has happened, as it happens: it was opened, signed, finished. Most connections use both. Both come with every paid plan, from Solo up.

This guide explains how they differ, how a system uses each, and how to try them both in test mode before writing any code. For a first envelope sent step by step, see Getting started with the API and webhooks. The API reference has every operation in detail.

The difference at a glance

The APIWebhooks
Who starts itYour system, whenever it needs to.SignSwifly, as soon as something happens.
Which way it goesYour system calls https://anz.signswifly.com.au/api/v1.SignSwifly calls an HTTPS address of yours, your endpoint.
What it’s forDoing and reading: send, remind, resend, void, check progress, download the signed documents.Hearing what happened: sent, viewed, signed, completed, declined, expired, voided, or an email that bounced.
What it carriesWhatever you asked for: an envelope, a list, a PDF.A short JSON message naming the envelope and, where there is one, the recipient. Never the documents.
How each side knows who’s talkingYour request carries an API key (ssk_live_…, or ssk_test_… in test mode), which SignSwifly checks.Each delivery carries a signature made with your endpoint’s signing secret (whsec_…), which your system checks.
What you set upA key, under Settings → API & webhooks, with the scopes it needs.An endpoint, under Settings → API & webhooks: a public HTTPS address that answers within 10 seconds.
If it doesn’t get throughYour system tries again, with the same Idempotency-Key, so nothing happens twice.SignSwifly tries again for about three days, so a delivery can arrive more than once.
Limits600 requests a minute for each key.10 endpoints for each workspace.
Where to look afterwardsThe envelope’s audit trail, which names the key.The endpoint’s delivery log, for 30 days.

Which to use for what

  • Use the API when your system decides something should happen: a deal reaches the contract stage, so it sends the contract; a signer says the email never came, so it resends.
  • Use webhooks when your system needs to know something happened: a contract is signed, so the deal moves on and the signed copy is filed.
  • Prefer a webhook to asking again and again. Checking every few minutes whether an envelope is finished works, but it’s late by however long you wait between checks, and spends requests on answers that haven’t changed. A webhook usually arrives within seconds.
  • A webhook says what happened; the API acts on it. envelope.completed tells your system an envelope is finished. To get its signed documents, your system then asks the API for them.
  • Keep the API as the record. A webhook can arrive late, twice or out of order, and nothing is sent to an endpoint while it’s switched off. Once a day, say, read your envelopes with GET /api/v1/envelopes to catch anything a webhook didn’t bring.

An example: a lease sent from your CRM

StepWho starts itWhat happens
1Your system, with the APIIt sends the lease from a template: POST /api/v1/envelopes/from-template with "send": true and an Idempotency-Key. The answer has the envelope’s id, which your system keeps beside the deal.
2SignSwifly, with a webhookenvelope.sent: your CRM shows the lease as out for signature.
3SignSwifly, with a webhookrecipient.viewed, then recipient.signed, for each signer as they go.
4SignSwifly, with a webhookenvelope.completed: everyone has signed and the documents are sealed.
5Your system, with the APIGET /api/v1/envelopes/{id} lists its documents. GET /api/v1/envelopes/{id}/documents/{documentId}/sealed and GET /api/v1/envelopes/{id}/certificate download the signed lease and its certificate of completion, to file against the deal.
6Your systemIf envelope.declined, envelope.expired or envelope.voided arrives instead, it stops waiting, and can send a new envelope with the API.

Calling the API

  • Every request goes to https://anz.signswifly.com.au/api/v1 over HTTPS, with the key in the Authorization header. Requests and answers are JSON, except downloads, which are PDF files.
  • A key does only what its scopes allow. A request outside them is refused with a 403 and the code missing_scope.
  • An error comes back as problem details: a detail written for whoever is fixing it, a code for your system to act on, and a traceId to quote to support.
  • Creating or sending an envelope takes an Idempotency-Key header: a new UUID for each envelope. Repeat a request after a timeout with the same key, within 24 hours, and you get the first answer back, with nothing sent twice.
  • Lists come a page at a time: data, hasMore and nextCursor. Pass nextCursor back as ?cursor= for the next page; limit is 1 to 100, and 25 if you don’t say.
  • A key can make 600 requests a minute. Past that, a 429 says in its Retry-After header how many seconds to wait.
  • Keep keys on your servers, never in a web page or an app people download.

For example, the envelopes finished most recently:

curl "https://anz.signswifly.com.au/api/v1/envelopes?status=completed&limit=10" \
  -H "Authorization: Bearer ssk_live_…"

Receiving webhooks

  1. Your endpoint is a public HTTPS address that accepts a POST of JSON. Add it under Settings → API & webhooks with + Add endpoint, and choose the events it should hear about.
  2. Before acting on a delivery, check its SignSwifly-Signature header against the raw body, as Check each delivery came from SignSwifly describes. The API reference has the check as ready-to-use code in C# and JavaScript. Anyone can post to your address; only SignSwifly can sign.
  3. Answer with any 2xx status within 10 seconds, then do the work, from a queue, say. Anything else is tried again later.
  4. Skip a delivery whose id you’ve already handled, and use createdAt, not the order they arrive in, to tell which happened first.
  5. For anything the message doesn’t carry, such as the signed documents, call the API.

A delivery when someone signs:

{
  "id": "evt_4f0c…",
  "type": "recipient.signed",
  "createdAt": "2026-09-29T01:02:03Z",
  "apiVersion": "v1",
  "workspaceId": "…",
  "test": false,
  "data": {
    "envelope": { "id": "…", "subject": "Lease", "status": "sent", "createdAt": "…", "sentAt": "…" },
    "recipient": { "id": "…", "name": "Jane Citizen", "email": "jane@example.com", "role": "signer",
                   "status": "signed", "routingOrder": 1 }
  }
}

Send test event, beside an endpoint, sends one with no envelope, once and without retries:

{
  "id": "evt_…",
  "type": "webhook.test",
  "createdAt": "…",
  "apiVersion": "v1",
  "workspaceId": "…",
  "test": false,
  "data": { "message": "A test event from SignSwifly. If you can read this, your endpoint works." }
}

test is true for a test envelope’s events, and for the test event sent to a test endpoint: see Try it yourself.

Try it yourself

Test mode lets you try both without sending anything real. A test key (ssk_test_…) works as a live key does, with the same operations, scopes, limits and answers, but every envelope it makes is a test envelope:

  • It goes only to people in your team: the email addresses your workspace’s members sign in with.
  • It says TEST in Send & Sign, at the top of every email (with [TEST] in the subject) and on the signing page.
  • It doesn’t use your plan’s envelopes, drafts or email allowance. Up to 50 can be sent a day.
  • Nobody is texted, and nobody is left for a signer to name, such as a nominee or a witness the signer names.
  • Once it’s completed, its documents and certificate have TEST across every page and no seal. SignSwifly hasn’t signed them, and they have no legal effect.
  • It’s deleted, documents and all, 7 days after it was made, whatever state it’s in.

A test key sees only test envelopes, and a live key only real ones. Webhooks keep to the same line: a test endpoint hears about test envelopes only, and a live endpoint about real envelopes only, so your real system never acts on a test. Every delivery says which, in test. Test mode comes with the API, on Solo, Team and Scale.

1. Make a test key

Under Settings → API & webhooks, choose + New API key, then Test. Name it “Trying the API”, set it to expire in 30 days, and keep the four scopes that start ticked. Tick webhooks:manage too if you’d like to try adding endpoints through the API.

2. Try the API in the console

The API console runs every operation from your browser. Paste your test key, pick an operation, fill in its boxes and choose Send. It shows the answer, offers the ids in it for the next operation, and gives the same request as curl. It keeps your key only while the page is open, and asks before a live key changes anything.

  1. GET /api/v1/me says the key works, who it acts as, and "test": true.
  2. GET /api/v1/templates lists your active templates, and GET /api/v1/templates/{id} gives a template’s roles and variables.
  3. POST /api/v1/envelopes/from-template with yourself in each role and "send": true sends you a test envelope. Leave "send" out to make a draft instead.

Prefer an API tool? The Postman collection has the same steps in order, with your key in one variable and each request saving the ids the next one needs. Or import https://anz.signswifly.com.au/openapi/api-v1.json, which describes the whole API, into Postman, Insomnia or Bruno.

3. Watch webhooks arrive

A request-inspection service, such as webhook.site, gives you a temporary HTTPS address and shows every request sent to it. Add that address as an endpoint, choose Test and every event, then choose Send test event. Within seconds the service shows the delivery: its JSON, and the SignSwifly-Signature, SignSwifly-Event-Id and SignSwifly-Event-Type headers. The endpoint’s Delivery log shows the same delivery from SignSwifly’s side, with what the service answered.

Such a service is someone else’s, and keeps what it receives, names and email addresses included. Use one only for test envelopes to yourself, and remove the endpoint when you’ve finished.

4. Follow an envelope from start to finish

Open the [TEST] email, view the document and sign it, and watch envelope.sent, recipient.viewed, recipient.signed and envelope.completed arrive at your test endpoint. Then download the signed copy with the API, as in step 5 of the example: it has TEST across every page.

5. Run the sample integration

The Python sample is a small integration in one file, with nothing to install: it sends an envelope from a template, listens for webhooks, checks each one’s signature, skips repeats, and downloads the signed documents when an envelope is completed. Its README says how to run it with a test key, and how to receive webhooks on your own computer through a tunnel.

6. Go live

Make a live key, and a live endpoint with its own signing secret, and put them in place of the test ones. Nothing else in your code changes. From then on envelopes go to anyone, are sealed, and count towards your plan like those you send from the app.

7. Tidy up

  • Remove any endpoint at a request-inspection service.
  • Delete the test key once you’re done with it, or let it expire.
  • Test envelopes delete themselves 7 days after they were made, so there’s nothing to delete.

Next steps