Skip to content
KortixKortix
Esc
↑↓navigate↵open⌘Jpreview
On this page

REST API

Call the Kortix API directly: base URL, authentication, errors, retries, and where the full route reference lives.

The Kortix REST API is the HTTP interface to accounts, projects, sessions, secrets, connectors, triggers, and Apps. The web app, the CLI, the SDK, and the Kortix MCP server all call it. Use it directly from any language that can send an HTTPS request with a bearer token.

The shortest path: create a personal access key, list your projects, and start a session.

kortix tokens new my-script --expires 30d    # prints kortix_pat_… once
export TOKEN=kortix_pat_...

curl -s https://api.kortix.com/v1/projects \
  -H "Authorization: Bearer $TOKEN"

curl -s https://api.kortix.com/v1/projects/<project_id>/sessions \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"initial_prompt": "Summarize the open change requests."}'

GET /v1/projects returns an array of projects, each with project_id. The session create returns 201 with the session, including session_id and branch_name. It returns 202 with status, command_id, and session_id when Kortix queues the create. Read the session with GET /v1/projects/<project_id>/sessions/<session_id> until it appears.

Pick a surface

All four surfaces reach the same API with the same permissions.

Surface Use it for Credential
REST API Any language. Integrations, scripts, and servers that are not TypeScript. A bearer token from Authenticate
SDK (@kortix/sdk) TypeScript and React. Sessions with live streaming, typed errors, automatic retries, and the session runtime. getToken returns a bearer token
CLI (kortix) Terminals, CI jobs, and agents inside a session sandbox. kortix login, or a token in CI
Kortix MCP server Claude, Cursor, ChatGPT, and other MCP clients that act as you. Its search_api, describe_api, and call_api tools read and call this API. OAuth sign-in from the client

Prefer the SDK for anything that drives a session: it owns the start, the readiness wait, the event stream, and the runtime routes that the REST reference does not list.

Base URL and reference

Deployment Base URL
Kortix Cloud https://api.kortix.com/v1
Self-hosted https://api.<domain>/v1 by default. See Self-hosting.

Every deployment serves its own route reference:

  • GET /v1/docs: the interactive reference. The API reference tab at the top of these docs opens the Kortix Cloud copy.
  • GET /v1/openapi.json: the OpenAPI 3.1 document. Its servers entry is the origin you requested it from, so a client generated from a self-hosted instance points at that instance.
  • GET /v1/health: no token needed. Returns status, version, and commit.

The reference leaves out operator routes. A self-host operator turns off both /v1/docs and /v1/openapi.json with OPENAPI_PUBLIC_DOCS=false in the API environment.

Authenticate

Send one header on every request:

Authorization: Bearer <token>

The token decides who the request acts as. Every Kortix credential starts with a prefix that names its kind. Create and manage them on Sign-in, SSO & API keys.

Prefix Credential Acts as
kortix_pat_ Personal access key (Settings → Personal access keys, kortix tokens new, kortix login) You, with your roles. A key bound to one project gets 403 everywhere else.
kortix_sa_ Service account key (Account settings → API keys) The service account. It has no access until someone assigns it a role.
kortix_oat_ OAuth access token from Sign in with Kortix. It lasts 1 hour. A kortix_ort_ refresh token gets a new one. The person who approved the app.
kortix_gw_ Project gateway key (kortix gateway keys new) The LLM gateway inference routes of one project, and nothing else. See Models.
kortix_scim_ SCIM token (Account settings → Identity) Directory sync under /scim/v2 for one account.
kortix_pat_ in KORTIX_TOKEN Session token. Kortix sets it in every session sandbox. The agent of that one session, limited to its project. It ends with the session.

An OAuth token without the kortix scope reaches only /v1/accounts/me, /v1/oauth/userinfo, and /v1/oauth/revoke. Other routes answer 403, and message starts with insufficient_scope.

A person’s access token from headless sign-in also works as a bearer token. It acts as that person.

A missing or invalid token returns 401. A 401 with code: "session_token_revoked" means the credential is revoked, expired, or belongs to a closed session. It never works again: stop retrying and get a new token.

The same tokens open the project’s git origin. See Git.

Errors

An error response is JSON. Every body has error. The generic shape adds message and status. A typed error adds code and can add more fields.

Field Type Meaning
error true or text Text is a human-readable reason.
message text A human-readable reason.
code text A stable machine code. Branch on this, never on the text.
status number The HTTP status, repeated.

Some errors add fields. A failed body, query, or path validation returns:

{ "error": true, "message": "Validation failed", "status": 400, "issues": [ … ] }

issues lists each invalid field with its path and message.

Status Meaning What to do
400 The request is not valid. Read issues or message. Fix the request.
401 No valid credential. Send a valid token. Stop on session_token_revoked.
402 The account cannot pay for this, or its plan does not include it. Read code: insufficient_credits, subscription_required, no_account, entitlement_required, budget_exceeded. A billing 402 (insufficient_credits, subscription_required, no_account) also carries billing_state, balance, and account_id. Branch on billing_state to choose between subscribe and top up. See Common error codes.
403 The credential is valid, but the action is not allowed. A permission denial names the action it needed and a code. feature_disabled adds feature, the flag key.
404 The object does not exist, or you may not see it. Kortix answers 404, not 403, for an object you may not see. Check the id. Check your access to the object.
409 The request conflicts with the current state. Read code. Reload the object and decide again.
422 The request is valid, but the operation cannot apply. Read code, for example CR_HEAD_NOT_AHEAD.
429 A rate limit. Wait Retry-After seconds. See Retries and idempotency.
500 A defect in Kortix. Do not retry in a loop. Report it with the X-Request-Id response header.
502, 503, 504 A temporary failure. A 503 usually carries Retry-After. Retry reads. Check the state before you repeat a write.

Every response carries an X-Request-Id header. Quote it when you report a problem.

Common error codes

These are the codes clients branch on most. The linked page explains each fix.

code Status Cause Fix on
session_token_revoked 401 The credential can never work again. Sign-in, SSO & API keys
insufficient_credits 402 The account’s credit balance is empty. Plans & credits
subscription_required 402 The account has no plan for Kortix-billed usage. Plans & credits
no_account 402 The account has no credit account yet. Its setup is not complete. Plans & credits
entitlement_required 402 The plan lacks sso, scim, rbac, auditAccess, or branding. The body names entitlement. Sign-in, SSO & API keys
budget_exceeded 402 A model budget set to block reached its limit. Models
feature_disabled 403 The project has this feature flag off. The body names feature. Projects
feature_operator_only 403 Only Kortix (a platform admin) may change this flag, for example apps. Projects
account_mfa_required 403 The account requires two-factor, and this sign-in did not use it. Sign-in, SSO & API keys
expiry_required, expiry_too_far 400 A new key breaks the account’s key rules. Sign-in, SSO & API keys
INVALID_IDEMPOTENCY_KEY 400 The Idempotency-Key header is not 1 to 255 characters of A-Z a-z 0-9 . _ : + / = -. Retries and idempotency
IDEMPOTENCY_KEY_CONFLICT, IDEMPOTENCY_*_CONFLICT 409 The key is in use for another request, or for this one with different connector_bindings, secrets, runtime_context, or provider_secret_pools. Retries and idempotency
IDEMPOTENCY_KEY_SESSION_DELETED 409 The key belongs to a session that was deleted. Use a new key.
INVALID_SESSION_RUNTIME_CONTEXT, INVALID_SESSION_CONNECTOR_BINDINGS, INVALID_SESSION_SECRETS 400 A session create field is malformed. Sessions from code
project_archived 404 The project was deleted. Projects
request_deadline 503 A request ran past the API’s 25-second processing limit. Retry the read. Check the state before you repeat a write.
git_mirror_unavailable 503 The project repository is temporarily unreachable. Retry after Retry-After. Git
repository_push_rejected 409 The git host refused a push because of branch protection or repository rules. Git
CR_HEAD_NOT_AHEAD 422 The change request branch has no commits ahead of its base. Git
CR_SELF_MERGE_REFUSED 403 A session tried to merge its own change request without a project.gitops.merge grant. Git
MANIFEST_INVALID 422 The change request makes kortix.yaml invalid. The merge is blocked. issues lists the errors. kortix.yaml reference
PERSONAL_SECRET_REQUIRES_PRIVATE_SESSION 409 You tried to share a session that holds a secret shared only with you. Secrets
project_secret_write_limit 429 The project wrote secrets more than 100 times in one hour. Secrets
app_config_invalid 400 An App release config is not valid. issues lists the errors. Apps
app_auth_required 401 An App URL needs a viewer that may open it. Apps

A connector call reports its outcome in reason, not code, inside { ok: false, status: "denied" | "error", reason }. The reasons, such as connector_not_connected and policy_block, are on Connectors. LLM provider and model failures are on Models.

Retries and idempotency

The SDK retries reads, and a DELETE that got no response. It never repeats any other write. In your own client, decide per response:

Response Retry
GET or HEAD with 502, 503, or 504 Yes, after Retry-After when it is present. The SDK retries 2 times, after 250 ms and 500 ms.
A write with 502, 503, or 504 Read the state first.
429 Yes, after Retry-After seconds. The body repeats the wait as retry_after_seconds.
A write with no response (network failure) Read the state first, or resend with the same Idempotency-Key where the route takes one.
400, 401, 402, 403, 404, 409, 422 No. Change the request or the state first.
500 No. Report it with X-Request-Id.

Idempotency-Key

Two create routes deduplicate a retried request:

Route Where the key goes Format
POST /v1/projects/<project_id>/sessions (start a session) Idempotency-Key header 1 to 255 characters of A-Z a-z 0-9 . _ : + / = -
POST /v1/projects/provision (create a project with a new repository) idempotency_key body field Up to 200 characters of A-Z a-z 0-9 . _ : -

Send a new random value, such as a UUID, for each intent. Send the same value again when you retry that intent. A repeated session create returns the original session instead of starting a second sandbox. Session keys are unique across all of Kortix. A key that another project or account already used returns 409 IDEMPOTENCY_KEY_CONFLICT.

Pagination

A list route that pages takes limit and cursor. Pass the next cursor back as cursor. No next cursor means you have the last page.

List Next cursor limit
GET /v1/projects/<project_id>/sessions X-Next-Cursor response header Default 50, maximum 200
GET /v1/accounts/<account_id>/audit next_cursor in the body Default 50, maximum 200

The session list also returns an ETag. Send it back as If-None-Match and an unchanged list answers 304 with no body.

Rate limits

A rate-limited route returns X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (seconds until the window resets). When the limit is reached it returns 429 with Retry-After and this body:

{ "error": "rate_limit_exceeded", "message": "Rate limit exceeded. Please retry shortly.", "retry_after_seconds": 12 }
Route Limit
Headless sign-in routes under /v1/auth 30 requests per minute per IP address. The 429 body is { "error": "over_request_rate_limit", "error_description": "…" } with Retry-After, and no X-RateLimit-* headers.
The sandbox proxy, /v1/p/<external_id>/<port>/*: previews and the session runtime 600 requests per minute per sandbox
Secret writes in one project 100 per hour, code: "project_secret_write_limit"

What the reference does not cover

The reference does not list the session runtime routes. The surfaces below also take a different credential or protocol than a plain bearer call:

Surface Use instead
The session runtime under /v1/p/<external_id>/8000/kortix/runtime/*: prompts, the event stream, files, and the transcript of a running session. The path takes the sandbox’s external id at the provider, not the session_id. Read it from sandbox_url in kortix sessions info <session_id> --json (after /v1/p/), or from sandboxId in the SDK’s ensureReady(). The SDK session handle, kortix.session(projectId, sessionId). See Sessions from code.
SCIM 2.0 under /scim/v2/accounts/<account_id>. It takes a kortix_scim_ token, not a personal key. SCIM provisioning
Inbound trigger webhooks, POST /v1/webhooks/projects/<project_id>/<slug>. They authenticate with the trigger secret, not a Kortix token: send an HMAC signature (X-Kortix-Signature or X-Hub-Signature-256), X-Kortix-Token, or Authorization: Bearer <secret>. Webhooks
The LLM gateway’s OpenAI- and Anthropic-compatible endpoints. They take a kortix_gw_ key. Models
The project git origin, https://api.kortix.com/v1/git/<project_id>.git. Git

Machine-readable docs

These docs are also published as plain Markdown for coding agents and LLM tools:

URL Content
https://kortix.com/llms.txt An index of every public page, docs included, with a link to its Markdown
https://kortix.com/llms-full.txt All public pages in one file
https://kortix.com/markdown/docs/<path>.md One page. For example, this page is /markdown/docs/api.md.
Any /docs/<path> URL, requested with Accept: text/markdown The same page as Markdown

Point a coding agent at https://kortix.com/llms.txt for the concepts and at https://api.kortix.com/v1/openapi.json for the exact routes. An MCP client that uses the Kortix MCP server reads the route reference itself through search_api and describe_api.

Was this page helpful?