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
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 "https://api-uat.softsages.com/core/api/v1/inkfree/me" \
-H "X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"{
"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 "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 "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 -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
}'{
"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
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 -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"
}'{
"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
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.