TrustInk API
Send documents for legally-binding e-signature, route them to multiple signers, track status, download the completed PDF with its audit trail, and get real-time webhooks — all over a simple REST API.
Authentication
The API authenticates with an API key. Create one in the TrustInk app under Settings → API keys. Keys look like tk_live_… and are shown once — store it securely.
Send it on every request as a Bearer token (or the X-Api-Key header):
curl https://api.trustink.cloud/v1/envelopes \ -H "Authorization: Bearer tk_live_your_key_here"
Base URL & versioning
All endpoints are under the versioned base:
https://api.trustink.cloud/v1
Requests and responses are JSON (documents travel as base64). We version by URL prefix; breaking changes ship under a new prefix.
Create & send an envelope
Creates an envelope from a PDF, places fields for each signer, and (by default) sends it. Set "send": false to create a draft.
Body parameters
| Field | Type | Description |
|---|---|---|
| docName required | string | File name shown to signers, e.g. "NDA.pdf". |
| docB64 required | string | The PDF, base64-encoded. |
| signers required | array | One or more recipients — see Signers. |
| fields | array | Field placements bound to a signer — see Fields. |
| subject | string | Email subject for the signing request. |
| message | string | Message included in the signing email. |
| signingMode | string | sequential (default) or parallel. |
| reminderDays | integer | Reminder cadence in days. 0 disables reminders. |
| expiresAt | string | ISO-8601 expiry timestamp (optional). |
| send | boolean | Send immediately (default true). |
Example
curl -X POST https://api.trustink.cloud/v1/envelopes \
-H "Authorization: Bearer tk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"docName": "NDA.pdf",
"docB64": "JVBERi0xLjc…",
"subject": "Please sign: Mutual NDA",
"signingMode": "sequential",
"reminderDays": 3,
"signers": [
{ "email": "alice@acme.com", "name": "Alice", "roleLabel": "Discloser" },
{ "email": "bob@example.com", "name": "Bob", "roleLabel": "Recipient" }
],
"fields": [
{ "signerIndex": 0, "page": 1, "x": 0.12, "y": 0.82, "w": 0.25, "h": 0.05, "type": "signature" },
{ "signerIndex": 1, "page": 1, "x": 0.55, "y": 0.82, "w": 0.25, "h": 0.05, "type": "signature" }
]
}'
201 Created
{
"envelope": {
"id": "env_…", "status": "sent", "doc_name": "NDA.pdf",
"signing_mode": "sequential",
"signers": [
{ "email": "alice@acme.com", "status": "sent", "sign_url": "https://app.trustink.cloud/sign/…" },
{ "email": "bob@example.com", "status": "pending" }
]
}
}
List envelopes
Returns your envelopes, newest first. Filter with ?status= (draft, sent, signed, declined, voided, expired).
curl "https://api.trustink.cloud/v1/envelopes?status=sent" \ -H "Authorization: Bearer tk_live_your_key_here"
Get an envelope
Full status including every signer and field.
curl https://api.trustink.cloud/v1/envelopes/env_123 \ -H "Authorization: Bearer tk_live_your_key_here"
Download the document
Returns the PDF bytes (application/pdf). Once complete this is the signed document, with the certificate-of-completion page and a tamper-evident SHA-256; before completion it's the original.
curl https://api.trustink.cloud/v1/envelopes/env_123/document \ -H "Authorization: Bearer tk_live_your_key_here" \ -o signed.pdf
Void an envelope
Cancels an in-flight envelope. Signers can no longer act on it.
curl -X POST https://api.trustink.cloud/v1/envelopes/env_123/void \
-H "Authorization: Bearer tk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "reason": "Superseded by a new version" }'
Fields & signers
Signer object
| Field | Type | Description |
|---|---|---|
| email required | string | Recipient email. |
| name | string | Recipient name. |
| roleLabel | string | Role shown in the UI/certificate, e.g. "Buyer". |
| signOrder | integer | Order for sequential signing (1-based). |
| authMethod | string | none (default) or code (access-code required). |
| accessCode | string | Required when authMethod is code. |
Field object
Coordinates are normalized 0–1 from the top-left of the page, so they're resolution-independent.
| Field | Type | Description |
|---|---|---|
| signerIndex required | integer | Index into signers[] this field belongs to. |
| page required | integer | 1-based page number. |
| x, y, w, h required | number | Position and size, each 0–1. |
| type required | string | signature, initials, date, text, checkbox, dropdown. |
| label | string | Field label / placeholder. |
| required | boolean | Whether the signer must complete it. |
| options | array | Choices for a dropdown. |
Webhooks
Add an endpoint under Settings → Webhooks. TrustInk POSTs JSON when envelope state changes. Each request carries:
| Header | Description |
|---|---|
X-TrustInk-Event | The event name (below). |
X-TrustInk-Signature | sha256=<hex> — HMAC-SHA256 of the raw body using your webhook secret. |
Events
| Event | Fires when |
|---|---|
envelope.sent | An envelope is sent to its first signer(s). |
envelope.signed | A signer completes their part. |
envelope.completed | All signers have signed; the final PDF is ready. |
envelope.declined | A signer declines. |
envelope.expired | An envelope passes its expiry. |
Verify the signature (Node)
const crypto = require('crypto');
function verify(rawBody, header, secret) {
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
return crypto.timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}
Errors
Standard HTTP status codes; the body is { "error": "message" }.
| Status | Meaning |
|---|---|
400 | Missing or invalid parameters. |
401 | Missing or invalid API key. |
403 | Not permitted (e.g. no verified sending domain, or plan quota reached). |
404 | Envelope not found. |
429 | Rate limited. |
Rate limits & quotas
Sends are metered against your plan's monthly envelope quota (Free / Starter / Business / Enterprise). A 403 on create means the quota is reached — upgrade in the app. Before you can send, your account must have a verified sending domain (Settings → Domains).
TrustInk — by ThreatShield. Questions? Your account team, or the in-app help. This reference covers the public /v1 API; the portal has additional account-management endpoints.