Developers
Build on the platform, not around it
A predictable REST API, idempotent writes, and SDKs that feel native. Authenticate, make a call, and ship — the boring parts are already handled.
Overview
Every request is JSON over HTTPS. Resources use stable ids, list endpoints are cursor-paginated, and all writes accept an Idempotency-Key header so retries are safe. Timestamps are ISO 8601 in UTC.
Authentication
Authenticate with a bearer token from your workspace. Keep it server-side — never ship a live key to the browser.
curl https://api.ttishlabs.com/v1/me \
-H "Authorization: Bearer tt_live_8xk2..." \
-H "Idempotency-Key: req_01H9..."Quickstart
Install the SDK, point it at your key, and make your first call in three lines.
import { Ttish } from "@ttishlabs/sdk";
const tt = new Ttish({ key: process.env.TTISH_KEY });
const project = await tt.projects.create({ template: "retail-suite" });
console.log(project.id); // "proj_8xk2"Endpoints
/v1/projects/v1/projects/v1/projects/:id/v1/projects/:id/deploy/v1/projects/:idA deployment returns a run you can poll or follow via webhook.
{
"id": "run_91kf",
"project": "proj_8xk2",
"status": "queued",
"created_at": "2026-07-25T14:02:11Z"
}Errors
Errors carry a machine-readable code and a human message. Map on the code, log the request id.
Rate limits
Limits are per workspace and returned in headers on every response. When you hit one, back off using Retry-After.
Reads
1,200 / min
Writes
300 / min
Deploys
30 / min
Webhooks
Subscribe to events instead of polling. Every payload is signed; verify the signature header before you trust it.
{
"id": "evt_123",
"event": "deployment.succeeded",
"data": { "run": "run_91kf", "url": "https://retail.example.com" }
}Official SDKs
Typed, tested, and kept in lockstep with the API. Community clients welcome — tell us and we'll list them.
Building something ambitious?
The API is the floor, not the ceiling. Talk to an engineer about what you're trying to ship.
