Connect your own tools to TeamTrackin: read and change tickets, move them across your boards, and get a signed message the moment something happens.
curl https://api.teamtrackin.com/api/v1/tickets/?q=assignee%20%3D%20me() \
-H "Authorization: Bearer ttk_xxxxxxxxxxxx_..."
{
"results": [{ "id": "…", "key": "WEB-12", "title": "Fix login",
"column": { "title": "In progress", "category": "in_progress" } }],
"next": "https://api.teamtrackin.com/api/v1/tickets/?cursor=eyJj…",
"limit": 25
}Everything below applies to every call under /api/v1/.
Make a key in Company settings, Developers, and send it as Authorization: Bearer ttk_… on every call.
Each key acts as one named person. A call needs the key's scope, that person's own permission, boards and Space role, and the rights of whoever set the key up.
Requests per minute per key: 120 on Standard, 600 on Premium, 1,200 on Enterprise. You can set a lower limit on a key; it never goes above your plan's.
Send an Idempotency-Key header on a POST. Repeating it within 24 hours returns the first answer instead of doing the work twice.
GET /api/v1/tickets/ returns newest first. Follow next until it is null; limit takes up to 100. Other lists use limit and offset.
Every error has the same shape: { error, detail, code }. A refused move answers 422 workflow_blocked with the rules that stopped it.
Choose scopes when you make a key. A call needs the scope and the person's own permission.
Read and work on tickets. Deleting is always its own scope.
Make and shape boards, Spaces and sprints.
Find work, keep knowledge and run projects.
Databases in Docs: their fields, views and entries. Plans with Docs.
Whiteboards in Docs: their elements, versions and comments. Plans with Docs.
Look up who to assign work to.
Manage webhooks through the API too.
Every endpoint, its scope and what it does. The full description, with every field, is at /api/v1/openapi.json for your API tools.
Who the key acts as and what it may do.
Tickets, comments, checklists, files and time.
Edit and delete comments.
Files on tickets: list, download, remove.
Boards, their columns, statuses and settings.
Spaces: make, change and remove them.
Plan, start and complete sprints.
Epics, by board.
A board's labels.
Custom fields and their values on tickets.
The search language and saved searches.
Docs pages, their files and images, and their history.
Docs databases, their fields, views and entries.
Docs whiteboards, their elements, versions and comments.
Standard operating procedures.
Projects and milestones.
Board reports, with the same numbers as the app.
Dashboards and their widgets.
People to assign tickets to.
Webhooks and their delivery log.
Add a webhook in Company settings, Developers: an https URL, the events you want and, if you like, the boards. TeamTrackin posts each event as JSON, signed with the webhook's secret.
POST https://your-system.example.com/teamtrackin
X-TeamTrackin-Event: ticket.moved
X-TeamTrackin-Delivery: 6f1c…
X-TeamTrackin-Signature: t=1762419600,v1=5d41…
{
"id": "0b9e…",
"type": "ticket.moved",
"occurred_at": "2026-11-06T09:00:00+00:00",
"origin": { "kind": "user", "ref": null },
"data": {
"ticket": { "id": "…", "key": "WEB-12", "title": "Fix login", … },
"change": { "field": "column", "from": { "title": "To do" }, "to": { "title": "In progress" } }
}
}X-TeamTrackin-Signature is t=<unix time>,v1=<hex HMAC-SHA256 of "<t>.<body>"> with your signing secret. Use the exact bytes received. After you make a new secret, deliveries carry a v1 for both secrets for 24 hours.
import crypto from "node:crypto";
// rawBody: the exact bytes received. secret: the webhook's signing secret.
export function verify(rawBody, header, secret, toleranceSeconds = 300) {
const parts = header.split(",").map((p) => p.split("="));
const t = parts.find(([k]) => k === "t")?.[1];
const expected = crypto.createHmac("sha256", secret)
.update(`${t}.`).update(rawBody).digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(t)) <= toleranceSeconds;
return fresh && parts.some(([k, v]) => k === "v1" && v.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(v), Buffer.from(expected)));
}Any language with HMAC-SHA256 works the same way.
import hashlib, hmac, time
def verify(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
"""raw_body: the exact bytes received. secret: the webhook's signing secret."""
parts = [p.split("=", 1) for p in header.split(",")]
t = next((v for k, v in parts if k == "t"), "")
expected = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
fresh = t.isdigit() and abs(time.time() - int(t)) <= tolerance
return fresh and any(k == "v1" and hmac.compare_digest(v, expected) for k, v in parts)Pick any of these when you add a webhook.
Every change that matters to another system.
Someone commented on a ticket.
Bigger moments on a board. An import sends one event when it finishes, not one per ticket.
Every key is locked to your own company and never does more than the person it acts as. Basic has no API. Passwords, the vault, sign-in settings, billing and payroll payouts are never reachable. Connecting AI tools? See the AI tools docs at /developers/ai-tools.
3 API keys, 120 requests a minute per key, and webhooks.
10 API keys, 600 requests a minute per key, and webhooks.
Unlimited API keys, 1,200 requests a minute per key, and webhooks.
API keys and webhooks are included on Standard and higher plans. Try TeamTrackin free for 14 days.