Quickstart
This guide takes you from an empty account to a signed PDF. You create a case with one participant, upload the document, wait for the signature and download the result. Everything runs against the sandbox, TrustInk’s environment for testing.
You need curl and jq, a PDF of 1 KB to 25 MB, and an email address you can read for the participant.
-
Get API credentials
Sign in to the tenant portal and open API credentials. Create a client for your integration and copy its client ID, client secret and token URL. The secret is shown once; keep it in your secret store, never in the browser or a mobile app.
Terminal window export API=https://api-sandbox.trustink.ioexport TOKEN_URL=... # shown next to your credentialsexport CLIENT_ID=...export CLIENT_SECRET=... -
Get an access token
Exchange the credentials for a token with the OAuth 2.0 client credentials grant. The client authenticates with HTTP Basic.
Terminal window export TOKEN=$(curl -s -X POST "$TOKEN_URL" \-u "$CLIENT_ID:$CLIENT_SECRET" \-H 'Content-Type: application/x-www-form-urlencoded' \-d grant_type=client_credentials | jq -r .access_token)Send it as
Authorization: Bearer <token>on every tenant request. Cache it until shortly beforeexpires_inruns out instead of fetching one per request. -
Create a case
A case is one document and the people who sign it.
title,validUntilandparticipantsare required;callbacktells TrustInk where to send webhooks.Terminal window curl -s -X POST "$API/cases" \-H "Authorization: Bearer $TOKEN" \-H 'Content-Type: application/json' \-d '{"title": "Service contract 2026/0142","validUntil": "2026-10-31T23:59:59Z","participants": [{"firstName": "Jana", "lastName": "Nováková", "email": "jana.novakova@example.com", "language": "sk"}],"callback": {"url": "https://example.com/trustink/webhook","authType": "NONE","signingSecret": "replace-with-32-to-128-random-characters","data": {"orderId": 4711}}}' > case.jsonconst response = await fetch(`${process.env.API}/cases`, {method: 'POST',headers: {authorization: `Bearer ${token}`, 'content-type': 'application/json'},body: JSON.stringify({title: 'Service contract 2026/0142',validUntil: '2026-10-31T23:59:59Z',participants: [{firstName: 'Jana', lastName: 'Nováková', email: 'jana.novakova@example.com', language: 'sk'}],callback: {url: 'https://example.com/trustink/webhook',authType: 'NONE',signingSecret: process.env.TRUSTINK_WEBHOOK_SECRET,data: {orderId: 4711},},}),});const {case: created, upload} = await response.json();The answer holds the case in status
NEWand where to put the document:{"case": {"id": "49d4ae62-…","title": "Service contract 2026/0142","status": "NEW","validUntil": "2026-10-31T23:59:59.000Z","participants": [{"id": "7a1c…", "firstName": "Jana", "lastName": "Nováková", "status": "UNSIGNED","signerUrl": "https://…", "signatureFields": []}]},"upload": {"type": "PUT", "url": "https://…"}}Each participant’s
signerUrlis their personal signing link. TrustInk emails it to them; you can also show it in your own system. -
Upload the PDF
PUT the document to
upload.urlwithin an hour. It must be a PDF of 1 KB to 25 MB.Terminal window export CASE_ID=$(jq -r .case.id case.json)curl -s -X PUT -H 'Content-Type: application/pdf' \--upload-file contract.pdf "$(jq -r .upload.url case.json)"The case moves to
IN_PROGRESSand the participants are invited by email. Open the link in Jana’s mailbox and sign. A file that is not a PDF of the right size moves the case toUPLOAD_REJECTEDwith arejectReason. -
Wait for the signatures
TrustInk POSTs
participant-signedafter each signature andcase-completedonce the signed PDF is ready. Verify theTrustink-Signatureheader before you trust the body; the webhooks guide has samples in Node.js, Java and C#.{"id": "7b1e4c2a-…","type": "case-completed","occurredAt": "2026-09-23T15:40:00Z","caseId": "49d4ae62-…","status": "DONE","data": {"orderId": 4711},"signedDocument": {"url": "https://…"},"evidenceDocument": {"url": "https://…"}}Without a public endpoint, read the case until it leaves
IN_PROGRESS. Poll gently, for example every 30 seconds.Terminal window until [ "$(curl -s "$API/cases/$CASE_ID" -H "Authorization: Bearer $TOKEN" | jq -r .status)" != "IN_PROGRESS" ]; dosleep 30doneDONEmeans everyone signed.EXPIRED,CANCELLEDandFAILEDend the case without a signed document. -
Download the signed PDF and the evidence
Once the case is
DONE,GET /cases/{caseId}links both documents with short-lived presigned URLs:Terminal window curl -s "$API/cases/$CASE_ID" -H "Authorization: Bearer $TOKEN" > done.jsoncurl -s -o signed.pdf "$(jq -r .signedDocument.url done.json)"curl -s -o evidence.pdf "$(jq -r .evidenceDocument.url done.json)"signed.pdfcarries one signature per participant, each with a certificate that names them, closed with the TrustInk seal and extended to PAdES B-LTA (signedDocument.level).evidence.pdfis the sealed evidence summary: every participant’s steps, the document’s SHA-256 and the certificates.
Links in webhooks work for an hour. Fetch a fresh one with
GET /cases/{caseId}whenever you need it.
Next steps
Section titled “Next steps”- Place the signature exactly where it belongs with signature fields.
- Ask each signer for a one-time code by email.
- Let people sign in person on a kiosk.
- Browse every route in the API reference.