API Introduction

API Introduction

The Seclai REST API allows you to programmatically create and manage AI agents, knowledge bases, sources, solutions, runs, alerts, and AI-assisted configuration. This page provides an overview of how to get started with the API.

Base URL

All API requests should be made to:

https://api.seclai.com/

Authentication

The Seclai API supports two authentication methods: OAuth (recommended) and API keys.

OAuth uses your Seclai account credentials via Cognito. Include a Bearer token in the Authorization header:

Authorization: Bearer YOUR_ACCESS_TOKEN

OAuth tokens are obtained through the standard OAuth 2.0 Authorization Code flow with PKCE. MCP clients handle this automatically — just enter the server URL and sign in when prompted.

To target a different organization's account, include the X-Account-Id header:

Authorization: Bearer YOUR_ACCESS_TOKEN
X-Account-Id: ORGANIZATION_ACCOUNT_ID

API Key Authentication

API keys are best suited for server-to-server integrations. Include your API key in the X-API-Key header:

X-API-Key: YOUR_API_KEY

Get Your API Key

  1. Log in to your Seclai account
  2. Navigate to API Keys in the left sidebar
  3. Click "Create API Key"
  4. Copy your key and store it securely right away. The key will not be shown again.

Important: Treat your API keys like passwords. Never share them or commit them to version control. Each user should create their own key.

Calling from a Browser

You can't. The API sends no CORS headers, and neither credential type can be narrowed for a browser: there are no per-resource or read-only scopes, so a leaked key or token carries every permission its identity holds. Browser-facing apps call their own backend, which calls Seclai. See Calling from a Browser for the reasoning and the proxy checklist.

Making Requests

Example Request

curl https://api.seclai.com/agents \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json"

Request Headers

HeaderRequiredDescription
Authorization*OAuth Bearer token: Bearer YOUR_ACCESS_TOKEN
X-API-Key*Your API key (alternative to OAuth)
X-Account-IdNoTarget a different organization account (OAuth only)
Seclai-VersionNoOpt into dated API changes — see API Versioning
Content-TypeYesSet to application/json for POST/PUT requests

* One of Authorization or X-API-Key is required.

Response Format

All responses are returned as JSON. Successful responses will have a 200 status code and include the requested data:

{
  "id": "agent_abc123",
  "name": "My Agent",
  "status": "active",
  "created_at": "2026-01-12T10:00:00Z"
}

Error Responses

Error responses carry an error object with a machine-readable code and a human-readable message (plus occasional extra fields, e.g. retry_after, callers):

{
  "error": {
    "code": "agent_in_use",
    "message": "This agent is still called by other live agents."
  }
}

Request-validation failures (a missing or malformed body field, a bad query-parameter type, or an unknown query parameter) historically returned a different { "detail": [...] } envelope. On Seclai-Version: 2026-07-27 or later they are unified into the same error envelope, with the per-field breakdown under details:

{
  "error": {
    "code": "validation_error",
    "message": "field required",
    "details": [
      { "type": "missing", "loc": ["body", "name"], "msg": "field required" }
    ]
  }
}

Clients on an older version keep the { "detail": [...] } shape for validation errors. One exception on every version: a malformed Seclai-Version header is rejected with { "detail": [...] } (it is rejected before a version can be resolved, so the response cannot be version-gated). Always branch on HTTP status first; then parse error (or, for validation errors on a legacy version, detail).

API Versioning

The API evolves without breaking existing integrations by making backward-incompatible changes opt-in through a dated version. The version a request runs under is resolved in this order:

  1. Seclai-Version request header (if present) — overrides everything for that one request, so you can test a new version on demand:

    curl https://api.seclai.com/agents \
      -H "X-API-Key: YOUR_API_KEY" \
      -H "Seclai-Version: 2026-07-27"
    
  2. Your account's pinned version — a sticky default for every request you make without the header. New accounts are pinned to the latest version at signup; accounts that predate a change stay on their existing version, so a release never changes behavior under you.

  3. The baseline — if your account is unpinned, requests fall back to a stable legacy baseline.

Sending (or pinning) a date opts into every change released on or before it. Every response echoes the version it was served with in the Seclai-Version response header; a malformed value (not YYYY-MM-DD) returns 422. The published OpenAPI spec carries an x-seclai-versions object listing the default, latest, and all known versions.

Managing your account's version

GET /version reports your pinned version, the version the current request resolved to, and the known versions. An account owner or admin can pin (or clear) it with PUT /version:

# Pin the whole account to a version (applies to every future request)
curl -X PUT https://api.seclai.com/version \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"version": "2026-07-27"}'

# Clear the pin (revert to the baseline)
curl -X PUT https://api.seclai.com/version \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"version": null}'

Changes by version

VersionWhat it changes
2026-07-27Unknown query parameters are rejected with 422 instead of silently ignored. Every list endpoint returns the canonical { data, pagination } envelope (see Pagination) — previously some returned a bare array, a flat { data, total, page, limit }, a { configs, total }, or another per-resource key. Request-validation errors use the unified { error: { code, message, details } } envelope instead of { detail: [...] }. GET /agents/evaluation-results/non-manual-summary also gains an agent_id scoping parameter.
2026-08-03Memory banks: the retired compaction threshold max_age_days is rejected with 400 and reads back as null0 stays accepted, since it is the sentinel that clears a value stored earlier. An omitted retention_days on create resolves per bank type — 90 days for a conversation bank, indefinite for a general bank — instead of a flat 30 days. An explicit retention_days (including null) is honoured on every version. See Memory Banks.
2026-08-21POST /sources rejects a dimensions value the chosen embedding_model does not support, with 400 and the allowed values, instead of storing it. Such a source could never be indexed — every later ingest failed with "No embedding model for dimensions N", far from the request that caused it. GET /models/embedders reports the supported dimensions per embedder. Omitting dimensions still uses the default on every version. See Embedding Models.

Authentication Error Codes

HTTP StatusError CodeMeaning
401API_NOT_AUTHENTICATEDMissing or invalid API key / Bearer token
401USER_NOT_AUTHENTICATEDOAuth Bearer token could not be verified
429RATE_LIMIT_EXCEEDEDToo many requests — see Retry-After header

Pagination

Every list endpoint returns the same envelope: the items under data, and a pagination object. Paginate with page/limit (or limit/offset, depending on the endpoint):

curl "https://api.seclai.com/agents?page=1&limit=20" \
  -H "X-API-Key: YOUR_API_KEY"

Response (on Seclai-Version: 2026-07-27 or later):

{
  "data": [...],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 150,
    "pages": 8,
    "has_next": true,
    "has_prev": false
  }
}

Because the shape is uniform, one helper can unwrap data and read pagination.has_next for any list endpoint. Naturally-bounded lists (reference data, relationship lists) return the whole set as a single page (has_next: false). The search endpoints (/search, /docs-search) are the exception — they return ranked results as { "results": [...] } (not a paginated collection). Clients on an older version keep each endpoint's legacy shape until they opt in.

SDKs

We provide official SDKs to make integration easier:

  • Python SDK - pip install seclai
  • JavaScript SDK - npm install @seclai/sdk
  • Go SDK - go get github.com/seclai/seclai-go
  • C# SDK - dotnet add package Seclai
  • CLI Tool - npm install -g @seclai/cli — includes built-in skills for common workflows

Rate Limits

The API enforces rate limits to protect service quality. Limits apply at two levels:

Global Limits

All API requests are subject to a per-IP limit of 120 requests per minute and a per-account limit of 300 requests per minute, regardless of plan.

Plan-Specific Limits

Your plan defines the maximum API requests allowed per minute. When you exceed this limit, the API returns a 429 Too Many Requests response.

Rate Limit Headers

Every successful API response includes rate-limit headers:

HeaderDescription
X-RateLimit-LimitMaximum requests allowed per window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the rate limit window resets

429 Too Many Requests

When rate-limited, the response includes a Retry-After header and a structured error body:

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "API request quota exceeded: 60/60 requests per minute. Retry after 45s.",
    "retry_after": 45
  }
}

Best practices:

  • Check X-RateLimit-Remaining to anticipate limits before hitting them.
  • On a 429 response, wait for the Retry-After duration before retrying.
  • Use exponential backoff for transient failures.

Webhooks

Configure webhooks to receive real-time notifications about events in your account:

{
  "event": "agent.run.completed",
  "data": {
    "run_id": "run_xyz789",
    "agent_id": "agent_abc123",
    "status": "completed"
  }
}

Set up webhooks in your account settings.

Next Steps