Developers
Read what is in a company file, push dockets in from your own systems, and be told the moment a claim moves. One rule carries over from the product: the API can snap, only a person can tick.
The owner makes a key under Settings → API and webhooks. Keys are read-only or read + capture, shown once, and stored hashed. Send it as a bearer token. 120 requests a minute per key.
curl https://app.inktick.com/api/v1/ping \ -H "Authorization: Bearer itk_live_…"
| GET | /api/v1/ping | read | Confirms the key and names the company file. |
| GET | /api/v1/claims | read | List claims. Filters: status, since, until (ISO-8601), limit (≤200), cursor. |
| GET | /api/v1/claims/{id} | read | One claim with lines, custom fields, originals and every timestamp. |
| POST | /api/v1/claims | write | Capture a docket: { filename, mimeType, contentBase64 } or { text }, plus kind and note. Lands as NEEDS_CONFIRM. |
| GET | /api/v1/files/{id} | read | The original, byte for byte. SHA-256 in X-InkTick-SHA256. |
| GET | /api/v1/suppliers | read | Suppliers with aliases, default coding, standing split and registry check. |
| GET | /api/v1/expense-reports | read | Bundles with their claims and totals. Filter: status. |
Money is integer cents with the currency beside it. Dates printed on a docket are YYYY-MM-DD; everything that happened in InkTick is an ISO-8601 UTC timestamp. Lists are newest first and page with nextCursor.
{
"id": "clm_…", "object": "claim", "status": "APPROVED", "kind": "STAFF_CLAIM",
"merchant": "Bunnings", "amount": { "cents": 8790, "currency": "AUD" },
"tax": { "cents": 799, "code": "INPUT" }, "issuedAt": "2026-09-02",
"accountCode": "310", "supplier": { "id": "…", "name": "Bunnings", "verified": true },
"lines": [], "customFields": { "Job number": "JOB-1042" },
"originals": [{ "id": "…", "sha256": "…", "url": "…/api/v1/files/…" }],
"ledger": null,
"timestamps": { "createdAt": "…", "confirmedAt": "…", "approvedAt": "…", "publishedAt": null }
}Add an https:// address under Settings → API and webhooks and pick events. Each delivery is a JSON POST carrying the same claim shape as the API. Events:
claim.capturedclaim.confirmedclaim.submittedclaim.approvedclaim.rejectedclaim.publishedclaim.reimbursedreport.submittedreport.approved
Every delivery is signed. Rebuild the signature from the raw body and compare before you trust it; reject anything older than five minutes.
X-InkTick-Event: claim.approved
X-InkTick-Timestamp: 1788862800
X-InkTick-Signature: sha256=<hex HMAC-SHA256(secret, timestamp + "." + rawBody)>
X-InkTick-Delivery: <uuid>
// Node
const crypto = require("crypto");
function verify(secret, headers, rawBody) {
const ts = headers["x-inktick-timestamp"];
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const expected = crypto.createHmac("sha256", secret).update(ts + "." + rawBody).digest("hex");
const given = String(headers["x-inktick-signature"]).replace(/^sha256=/, "");
return expected.length === given.length &&
crypto.timingSafeEqual(Buffer.from(expected, "hex"), Buffer.from(given, "hex"));
}Answer 2xx quickly and do the work afterwards. A failed delivery is retried once after two seconds; after twenty failures in a row the webhook pauses itself and the owner sees why in Settings.
The API is in beta while InkTick is pre-launch: shapes may gain fields, never lose them without notice. Questions: developers@inktick.com