Skip to content

API overview

The console is built on Sift’s HTTP API, and you can call the same API yourself: sign in with a session cookie, send a CSRF token on every change, and read one error shape. Every endpoint, with its roles, is listed on API endpoints.

The API is served on the console’s own address, under /api. The stack publishes no other port.

Path on the console’s addressWhat it isAuthentication
/api/v1/...The API the console uses.Session cookie
/api/healthzLiveness: {"status": "ok", "service": ..., "version": ...}.None
/api/readyzReadiness: checks the database, the queue and object storage. 200 with "status": "ok", or 503 with "status": "degraded" and each check’s result. Gate an orchestrator on this one.None
/api/metricsPrometheus metrics. 404 unless SIFT_METRICS_TOKEN is set. See Monitor Sift.Authorization: Bearer <SIFT_METRICS_TOKEN>; 401 without it
/api/openapi.jsonThe OpenAPI 3.1 document. Only when SIFT_ENVIRONMENT is development.None
/api/docsInteractive API docs for that document. Only in development.None
  1. Send POST /api/v1/auth/login with a JSON body:

    {"username": "admin", "password": "your-password"}
  2. Keep the sift_session cookie the response sets. It is HttpOnly, SameSite=Lax, and outside development it is Secure, so it is only sent over HTTPS.

  3. Keep csrf_token from the response body. The body is the same as GET /api/v1/auth/me returns:

    {
    "user": {"id": "...", "username": "admin", "role": "admin", "must_change_password": false, "created_at": "...", "last_login_at": "..."},
    "csrf_token": "..."
    }
  4. Send the cookie on every request, and on every POST, PUT, PATCH and DELETE also send the token in the X-CSRF-Token header. GET, HEAD and OPTIONS need no token.

A missing or wrong token is refused with 403 csrf_failed. GET /api/v1/auth/me returns the token again for a client that has lost it. A session lasts SIFT_SESSION_TTL_HOURS (12 by default); POST /api/v1/auth/logout, or a password change, ends every session of that account. Repeated failed sign-ins from one address or for one username are refused with 429 too_many_attempts and a Retry-After header.

Terminal window
SIFT=https://sift.example.internal
JAR=$(mktemp)
# Sign in; keep the cookie in the jar and the CSRF token in a variable.
CSRF=$(curl -sS -c "$JAR" -H 'Content-Type: application/json' \
-d '{"username":"admin","password":"your-password"}' \
"$SIFT/api/v1/auth/login" | jq -r .csrf_token)
# A read: the cookie is enough.
curl -sS -b "$JAR" "$SIFT/api/v1/filters"
# A change: the cookie and the CSRF token.
curl -sS -b "$JAR" -X POST -H "X-CSRF-Token: $CSRF" "$SIFT/api/v1/auth/logout"

On a development stack over plain HTTP, use http://localhost:8080 (or your SIFT_WEB_PORT).

Every endpoint under /api/v1 except POST /api/v1/auth/login needs a signed-in user. Which roles may call each one is in the OpenAPI document as x-required-roles on each operation, and on API endpoints. A role the endpoint does not allow is refused with 403 forbidden.

WhoMay call
reviewer, operator, adminEvery read of filters, activity, alerts, the dashboard, models, labels, system status and Kindo agents and models; their own session and password; labelling a gold-set item; answering the verdict check; previewing a version or a stage change.
operator, adminEvery change to a filter: creating and saving versions, lifecycle moves, training, Sift’s assistant (/api/v1/copilot/...), the analyzer and the portfolio scan, approving a gold set (POST /api/v1/filters/{filter_id}/gold-set/approve) and approving a threshold (POST /api/v1/filters/{filter_id}/threshold/approve); POST /api/v1/system/ping.
adminUsers, the Kindo credential, webhooks, the recipe settings, and POST /api/v1/system/decisions/ping.

The console shows the gold-set and threshold forms to a reviewer, but the server refuses a reviewer’s approval. See Users and roles.

The portfolio scan has no screen in the console. It ranks every agent in your Kindo tenant by its filtering opportunity: it looks briefly at every agent, then more closely at the likeliest. It runs in the background, and a large tenant means many Kindo API calls and inference spend. Operator or admin.

Method and pathWhat it does
POST /api/v1/analysis/portfolio-scanQueues a scan.
GET /api/v1/analysis/portfolio-scan/{scan_id}The scan and its ranking, as far as it has got.

To start from one agent instead, use the analyzer in the console: see Start from an existing agent.

Every error has one shape, whatever the endpoint:

{
"error": {
"code": "validation_failed",
"message": "Request failed validation.",
"details": {"errors": [{"loc": ["body", "username"], "msg": "...", "type": "..."}]},
"request_id": "3f9c1e0a7b2d4c6e8a1f0b2c3d4e5f60"
}
}
FieldMeaning
codeA stable, machine-readable code. Match on this, not on the message.
messageA sentence for a person.
detailsMore about the failure, or null. A validation error lists each failing field, without the value sent.
request_idThe request’s id, also returned in the X-Request-ID response header and on the server’s log lines. Send your own X-Request-ID (up to 64 characters) to have it used instead.

The general codes:

StatuscodeWhen
401unauthenticatedNot signed in, or the session is invalid, expired or ended.
403forbiddenYour role may not call this endpoint.
403csrf_failedA change was sent without the right X-CSRF-Token.
404not_foundNo such resource or path.
409conflictThe request conflicts with the current state.
409illegal_transitionA lifecycle move the filter’s state, approvals or preconditions do not allow.
422validation_failedThe body or parameters failed validation, or a filter spec broke one of its rules.
429too_many_attemptsToo many failed sign-ins; wait for Retry-After.
500internal_errorAn unexpected failure. The response carries no detail; the server log has it under the request_id.
503dependency_unavailableA service Sift depends on did not answer.

Endpoints that call Kindo or the decision model add their own codes, such as kindo_not_configured (503), kindo_rate_limited (429), kindo_unavailable (503) and decision_model_unavailable (503). Any other status without a specific code is http_error.