API
API reference
The v1 API reference for engineering teams that want to automate site audits, findings, keywords, reports and content status from their own code. Authentication uses a session cookie or a Bearer token, every response is JSON, and errors return a machine-readable code. This page documents syntax and contracts; it does not include an official SDK, a separate sandbox or a response-time guarantee.
Last updated: 2026-11-05·By Kestralia editorial team
Authentication
Two methods: the session cookie (web UI, with an x-csrf-token header on writes) or a Bearer token prefixed kst_. Tokens can be created only on plans with API access, and only their hash is stored.
curl -s https://your-host/api/v1/projects \
-H "Authorization: Bearer kst_xxxxxxxx"Responses and errors
Success: { ok: true, ... }. Error:
{ "ok": false, "error": "Human readable", "code": "machine_code" }Common codes: 401 invalid_token, 403 forbidden, 402 plan_limit, 409 invalid_transition, 422 validation_error, 429 rate_limited.
Rate limits
- Login: 10 attempts per 15 minutes per IP
- Signup: 5 per hour per IP
- Public audit: 5 per hour per IP
- Other calls: bounded by plan entitlements (crawls, GEO queries, drafts)
Endpoints
| GET | /api/v1/health | Liveness and database check |
| POST | /api/v1/auth/signup | Create user, workspace and session |
| POST | /api/v1/auth/login | Email + password login |
| POST | /api/v1/audit/preview | Public sample audit (rate limited, 5/hour/IP) |
| GET | /api/v1/projects | List projects |
| POST | /api/v1/projects | Create a project |
| GET | /api/v1/projects/:id | Project detail and history |
| POST | /api/v1/projects/:id/crawl | Run an audit (synchronous, bounded by plan) |
| GET | /api/v1/projects/:id/issues | Findings from the latest crawl |
| GET | /api/v1/projects/:id/keywords | Keyword map; ?format=csv for export |
| POST | /api/v1/projects/:id/geo | Run authorized AI measurements |
| POST | /api/v1/projects/:id/content | Generate a brief or draft |
| PUT | /api/v1/content/:id | Update content, re-run quality gates |
| POST | /api/v1/content/:id/status | Approve / publish / reject |
| GET | /api/v1/projects/:id/reports | List reports |
| POST | /api/v1/projects/:id/reports | Generate a report snapshot |
| POST | /api/v1/integrations | Connect and test a CMS or provider |
| GET | /api/v1/tokens | List API tokens |
| POST | /api/v1/billing/checkout | Start a plan change |
| POST | /api/v1/billing/webhook | Stripe webhook (signature verified) |
Example: run an audit
curl -X POST https://your-host/api/v1/projects/PROJECT_ID/crawl \
-H "Authorization: Bearer kst_xxxxxxxx" \
-H "content-type: application/json"The crawl runs synchronously and is bounded by your plan's page limit. For long-running work, run the worker and use the job queue.
What the API will not do
- It returns no data without a valid token.
- Write access is rejected without the write scope.
- No endpoint produces a simulated AI answer.
What should you know before you integrate?
Should a server-to-server script use a bearer token or the session cookie?
A Bearer token prefixed kst_ is the better fit for server-to-server calls because it does not depend on a browser cookie or a CSRF header. The secret is shown once and only its hash is stored; keep it in an environment variable and create tokens on plans that include API access.
What should my client do when it receives a 429?
Back off exponentially and queue the request instead of retrying in a tight loop; the 429 body includes retryAt. Limits are 10 login attempts per 15 minutes per IP, 5 signups and 5 public audits per hour, and plan entitlements for everything else.
How is the public preview different from a project crawl?
The public preview needs no account, reads only a sample of pages and is limited to 5 requests per hour per IP. A project crawl requires authentication, runs up to your plan's page limit, is stored in history and exposes its findings through the issues and reports endpoints.