Skip to main content

Getting started

Quickstart

From an API key to a sent envelope and a webhook subscription, in five steps. Every sample below is copy-paste ready — swap in your own key and ids.

On this page

1. Get an API key

Sign in to Inkfree, open Account Settings → API Keys, and create a key. Give it a name that says where it will be used — the name is what you will see when deciding which key to revoke later.

Copy the key immediately

The full sk_live_… value is shown once, at creation. Only a hash is stored server-side, so a lost key cannot be recovered — it has to be revoked and replaced.

Sign in to Inkfree to create one. API access is included on the Business plan.

2. Verify the key

Every authenticated request carries the key in the X-API-Key header. Start with GET /api/v1/inkfree/me: it confirms which account, user, and key the credential resolves to, and reports the key's rate limit and expiry.

curl
curl "https://api-uat.softsages.com/core/api/v1/inkfree/me" \
  -H "X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
200 response
{
  "account": "acme",
  "app": "inkfree",
  "user": {
    "email": "ops@acme.com",
    "first_name": "Dana",
    "last_name": "Reed"
  },
  "key": {
    "id": "3f9a1c02-6b7e-4d18-9a5c-2e8b4f6d0a13",
    "name": "Zapier production",
    "rate_limit_per_min": 60,
    "expires_on": "01/01/2027 00:00:00"
  },
  "capabilities": [
    "envelopes:read",
    "envelopes:write",
    "webhooks:manage"
  ]
}

A 401 here means the key is missing, malformed, unknown, expired, revoked, or inactive. The response does not tell you which, so check the key in Account Settings → API Keys if you are unsure.

3. Find a template

Templates carry the documents and the field placement, which makes sending from one far simpler than uploading a PDF and positioning fields yourself. List them first:

curl
curl "https://api-uat.softsages.com/core/api/v1/inkfree/templates" \
  -H "X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Then read one template to see its signer slots. Each slot's id is the signerIndex you will pass in the next step — every field positioned for that slot follows whoever you name there.

curl
curl "https://api-uat.softsages.com/core/api/v1/inkfree/templates/tpl_abc123" \
  -H "X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

4. Send an envelope

Send from the template. The request supplies only who fills each signer slot and the per-send email wording — signing order, cc flags, field placement, reminders and approval configuration all come from the template and cannot be overridden per send.

curl
curl -X POST "https://api-uat.softsages.com/core/api/v1/inkfree/envelopes/from-template/tpl_abc123" \
  -H "X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "signers": [
    {
      "signerIndex": 1,
      "name": "Priya Sharma",
      "email": "priya.sharma@example.com"
    },
    {
      "signerIndex": 2,
      "name": "Sam Okafor",
      "email": "sam.okafor@example.com"
    }
  ],
  "emailSubject": "Mutual NDA — Acme / Example",
  "emailMessage": "Countersigned copy follows once both parties sign.",
  "expirationDays": 14
}'
200 response
{
  "code": 200,
  "message": "env_xyz789"
}

The message field carries the new envelope id. Keep it — it is what you pass to every other envelope endpoint, including the signed-PDF download.

Make the send safe to retry

Pass an X-Idempotency-Key header and a replay with the same key and an identical body returns the original response instead of sending a second envelope. See Idempotency.

5. Subscribe to a webhook

Rather than polling for completion, subscribe a target URL to envelope.completed. Inkfree then POSTs each matching event to that URL.

curl
curl -X POST "https://api-uat.softsages.com/core/api/v1/inkfree/webhooks" \
  -H "X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
  "targetUrl": "https://hooks.example.com/inkfree",
  "eventType": "envelope.completed",
  "secret": "whsec_your_shared_secret"
}'
200 response
{
  "id": "whk_123",
  "target_url": "https://hooks.example.com/inkfree",
  "event_type": "envelope.completed",
  "secret": "whsec_example_value_shown_once_at_creation",
  "secret_note": "Store this now. It is shown only at creation and cannot be retrieved later; use PATCH /webhooks/{id} to rotate it if lost."
}

Note the casing change

The request body is camelCase (targetUrl, eventType); the response comes back snake_case (target_url, event_type). That is deliberate, not a typo — see Field naming.

Before you go live, verify the signature on every delivery — an unverified endpoint will accept anything that knows its URL.