Help guides

Getting started with the API and webhooks

The API lets your own systems — a CRM, an HR system, a property platform — send documents for signature, follow them as they’re signed and collect the sealed copies. Webhooks tell your systems when something happens, usually within seconds. Both come with every paid plan, from Solo up.

This guide takes you from nothing to a first envelope sent and a webhook checked. The API reference has every operation in detail. New to them? How the API and webhooks work together explains what each does, and how to try both before writing any code.

Before you start

  • Your workspace is on Solo, Team or Scale, and you’re its owner or an admin.
  • A template for what you’ll send, made in the app and saved with Save & activate, is the easiest way in. Only active templates can be used through the API.
  • Every request goes to https://anz.signswifly.com.au/api/v1, over HTTPS.

Make an API key

  1. Open Settings → API & webhooks and choose + New API key.
  2. Choose Test while you build and try things, or Live for the key your system will use for real (Test or live, below).
  3. Name it after the system that will hold it, such as “CRM sync”, so you know later what revoking it would stop.
  4. Choose its scopes: four start ticked, so untick any that system doesn’t need (below).
  5. Choose when it expires: in 30 days, 90 days, a year (the default) or never. You aren’t warned before it expires. After that, each request is refused with a 401 saying when it expired.
  6. Copy the key, which starts ssk_live_, or ssk_test_ for a test key. It’s shown once and can’t be shown again, so put it straight into your system’s secret store.
ScopeLets the key
envelopes:readList envelopes and read their status and recipients’ progress.
envelopes:writeCreate, send, void, remind and resend envelopes, and get in-person signing links.
templates:readList templates and read their roles and variables.
documents:readDownload sealed documents, combined PDFs and certificates of completion.
webhooks:manageRegister, change, test and remove webhook endpoints, and read their deliveries.

A key acts as the person who made it. Envelopes it sends have them as the sender, and each action is on the envelope’s audit trail as theirs, with the key named as the device, such as API key “CRM sync” (ssk_live_…). The key stops working if they leave the workspace, stop being an owner or admin, or are suspended: make a new one under someone who is.

To change a key’s name, scopes or expiry later, choose Edit beside it. The change applies from its next request. Whether it’s a test key, and who it acts as, can’t be changed: make a new key for that. A key that has expired can’t be changed either; delete it and make a new one.

Test or live

A test key 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), says TEST in Send & Sign, in its emails and on the signing page, and doesn’t use your plan’s envelopes, drafts or email allowance. Up to 50 can be sent a day. Nobody is texted. Once it’s completed, its documents and certificate have TEST across every page and no seal, and it’s deleted 7 days after it was made. A test key sees only test envelopes, and a live key only real ones. Try it yourself takes you through it, with the API console, a Postman collection and a sample integration.

Check the key works

curl https://anz.signswifly.com.au/api/v1/me \
  -H "Authorization: Bearer ssk_live_…"

The answer gives your workspace’s id, the key’s name, its scopes, who it acts as, and whether it’s a test key (test).

Send an envelope from a template

  1. Find the template and its roles. GET /api/v1/templates lists your templates; GET /api/v1/templates/{id} gives each role’s id and label, such as “Tenant”, and the template’s variables.
  2. Create and send the envelope, saying who fills each role:
curl https://anz.signswifly.com.au/api/v1/envelopes/from-template \
  -H "Authorization: Bearer ssk_live_…" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 5f0c2d1e-8b3a-4c7e-9d21-0a6b4e3f9c11" \
  -d '{
    "templateId": "…",
    "variables": { "property_address": "12 Example St, Sydney" },
    "recipients": [
      { "roleId": "…", "name": "Jane Citizen", "email": "jane@example.com" }
    ],
    "send": true
  }'
  • With "send": true it goes out straight away. Leave it out to make a draft, and send it later with POST /api/v1/envelopes/{id}/send.
  • The Idempotency-Key makes a retry safe: send the same request with the same key within 24 hours, after a timeout say, and you get the first answer back, and nothing is sent twice. A new UUID for each envelope is ideal. Keys are shared by the whole workspace. A different request with a key already used is refused with a 422 (idempotency_key_reused), and one sent while the first is still running gets a 409 (idempotency_in_progress). A refused request leaves its key free, so you can fix it and try again with the same one.
  • Each envelope sent with a live key counts exactly as one sent from the app: a signing session, or a single envelope you bought, where one is used. One sent with a test key doesn’t count.
  • You can send your own PDFs too, with fields placed by position: POST /api/v1/envelopes, in the API reference. Each can have up to 300 pages; one that SignSwifly can’t open safely (a damaged one, say) is refused with a 422 whose detail says so, and nothing is made. A 503 (busy, with Retry-After) means it couldn’t be checked just then, and nothing was made either: try again later.
  • A Word document (.docx, .doc or .rtf) sent that way becomes a PDF as the envelope is made, and only the PDF is kept. Its fonts are embedded (Calibri is drawn in Carlito, which has the same widths, so the pages break as in Word), its comments removed, and pictures or links to other places unlinked. One with tracked changes is refused with a 422 whose detail says to accept or reject them in Word first. A file past the size limits (more than 10 pictures, say), or one that isn’t a Word file inside (a web page saved as .doc), is converted the simpler way instead, as before, never refused; its fonts and page breaks may then differ from Word’s.

Follow it and collect the signed copy

  • GET /api/v1/envelopes/{id} gives its status and each recipient’s progress.
  • Once it’s completed, download each sealed document and the certificate of completion (with documents:read). The API reference lists the addresses.
  • Rather than asking again and again, let a webhook tell you when it’s done.

Set up a webhook

  1. In Settings → API & webhooks, choose + Add endpoint. Choose Test or Live: a test endpoint hears about test envelopes only, and a live one about real envelopes only, and it stays what it’s made as. Give your system’s HTTPS address and choose the events it should hear about.
  2. Copy the signing secret, which starts whsec_. Like a key, it’s shown once.
  3. Choose Send test event, then Delivery log to see what your system answered.
EventWhen
envelope.sentAn envelope was sent for signature.
recipient.viewedA recipient opened it for the first time.
recipient.signedA recipient signed; others may still be to.
envelope.completedEveryone signed and the documents were sealed.
envelope.declinedA recipient declined, which ends the envelope.
envelope.expiredIt ran out of time.
envelope.voidedThe sender voided it.
recipient.delivery_failedAn email to a recipient bounced or was refused.

Each delivery is a POST of JSON: the event’s id, its type, createdAt (when it happened), apiVersion, workspaceId, test (true for a test envelope’s events), and under data the envelope and, where there is one, the recipient it’s about. A decline or a failed email also has data.reason. The headers SignSwifly-Event-Id and SignSwifly-Event-Type repeat the id and type. Answer with any 2xx status within 10 seconds, then do the work.

recipient.viewed is sent once for each recipient: the first time they open it while it’s their turn, however often they open it after. A signing group counts as one recipient, so it’s sent when the first person in the group opens it. If the sender corrects someone’s address with Change, the corrected person’s first view is sent, under the same recipient id. A first view from before an endpoint was added, or while it was off or the workspace was on Free, isn’t sent later. The envelope’s audit trail still records every time it’s opened.

Send test event sends a webhook.test event, with no envelope, once and without retries.

Endpoints must be HTTPS addresses on the public internet, and the address’s name must already be in DNS when you add it. Addresses on private networks are refused, and redirects aren’t followed. A new endpoint hears only about events from when it’s added. A workspace can have 10 endpoints, switched off ones included.

Check each delivery came from SignSwifly

Anyone can post to your address, so check every delivery before acting on it. Each carries a header like this:

SignSwifly-Signature: t=1790000000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
  1. Take t (the time, in Unix seconds), every v1 value in the header, and the raw request body, before anything parses it.
  2. Compute an HMAC-SHA256 of t, a full stop, then the body. Use the whole signing secret as the key, whsec_ included, as plain UTF-8 text: don’t decode it. Write the result as lowercase hex.
  3. Compare it with each v1 in constant time, and accept the delivery if any one matches. Refuse it if t is more than five minutes from your own clock, so a recorded delivery can’t be replayed. Each attempt is signed afresh, so a retry passes this check.

The API reference has this as ready-to-use code in C# and JavaScript.

When a delivery fails

  • Anything but a 2xx within 10 seconds is tried again with growing gaps, for about three days.
  • A delivery can arrive more than once, and out of order. Use the event’s id to ignore a repeat, and its time to put things in order.
  • The delivery log keeps each delivery for 30 days, with its latest status and response. While the endpoint is switched on, you can send any delivery again with Resend.
  • If every delivery to an endpoint fails for three days, it’s switched off and the workspace’s owner and admins are emailed. Fix your system, then choose Switch on.
  • Switching an endpoint off, by you or after those three days, gives up the deliveries waiting for it, and nothing is sent to it while it’s off. Switched back on, it hears about events from then on: what happened while it was off is never sent. Deliveries given up stay in the delivery log for you to Resend. To catch up on the rest, read your envelopes with GET /api/v1/envelopes.

Limits and errors

  • Each key can make 600 requests a minute, and each calling address 1,200 a minute across all its keys. Answers to a key’s requests carry X-RateLimit-Limit and X-RateLimit-Remaining. A 429 says how long to wait, in seconds, in its Retry-After header.
  • A workspace can hold 50 live API keys.
  • If SignSwifly has paused your workspace’s sending, keys are refused with a 403 (workspace_paused), and webhooks wait until the pause is lifted.
  • Errors come back as problem details with a code to act on, such as missing_scope, and a traceId to quote to support.

Keep keys and secrets safe

  • Keep keys on your servers. Never put one in a web page or an app people download, where anyone can read it.
  • Give each system its own key with the fewest scopes it needs.
  • If a key may have leaked, choose Delete beside it. It stops working on its next request.
  • Rotate secret gives a webhook endpoint a new signing secret, shown once. The old one stops at once, with no overlap, so update your system straight away. Deliveries it refuses in between are tried again, signed with the new secret.

If your plan changes

On the Free plan, keys stop working and webhooks aren’t sent. A delivery still waiting when the workspace moved to Free is marked failed when its next try comes round while you’re on Free; one whose next try comes after you’re back on a paid plan carries on. Keys and endpoints are kept, and you can still delete keys and remove endpoints.

Back on a paid plan, keys work again and each endpoint starts fresh: events from your time on Free aren’t sent. Events from just before the move to Free that hadn’t gone yet are sent then. To catch up, read your envelopes with GET /api/v1/envelopes.