Reference

API Reference

Base URL: https://clavisagent.com  ยท  All requests and responses use JSON.

Authentication

All endpoints except POST /v1/auth/register and POST /v1/auth/login require a Bearer token in the Authorization header:

header
Authorization: Bearer eyJ...

Obtain a token by calling POST /v1/auth/login. Tokens expire after 24 hours.

Auth Endpoints

POST /v1/auth/register

Create a new developer account. Returns the developer profile including the permanent api_key prefixed with cla_.

Request body

FieldTypeDescription
email*stringValid email address. Must be unique.
password*stringMinimum 8 characters.
shell
$ curl -sX POST https://clavisagent.com/v1/auth/register \
    -H 'Content-Type: application/json' \
    -d '{"email":"you@example.com","password":"yourpassword"}'
response 201
{
  "id": "uuid",
  "email": "you@example.com",
  "is_active": true,
  "created_at": "2026-03-08T00:00:00Z",
  "api_key": "cla_..."
}
POST /v1/auth/login

Authenticate and receive a JWT. Pass this token as Authorization: Bearer <token> on all subsequent requests. Expires in 24 hours.

Request body

FieldTypeDescription
email*stringRegistered email address.
password*stringAccount password.
response 200
{
  "access_token": "eyJ...",
  "token_type": "bearer",
  "expires_in": 86400
}
GET /v1/auth/me requires auth

Return the authenticated developer's profile. Useful to verify a token is valid and retrieve your permanent api_key.

response 200
{
  "id": "uuid",
  "email": "you@example.com",
  "is_active": true,
  "created_at": "2026-03-08T00:00:00Z",
  "api_key": "cla_..."
}

Services

A service is a named instance of a connector that holds your credentials and rate limit settings.

POST /v1/services requires auth

Register a new third-party service. The name you choose is how you identify it in get_token() and proxy calls.

Request body

FieldTypeDescription
name*stringYour identifier for this service (e.g., "my-openai-prod"). 1โ€“100 chars.
connector_name*stringBuilt-in connector to use: openai, anthropic, github, stripe, brave-search, kalshi, or coinbase.
display_nameoptstringHuman-friendly display name.
descriptionoptstringFree-text description.
rate_limit_rulesoptarrayCustom rate limit rules. Overrides connector defaults. Each rule: {"requests": N, "window_seconds": N}.
shell
$ curl -sX POST https://clavisagent.com/v1/services \
    -H 'Authorization: Bearer eyJ...' \
    -H 'Content-Type: application/json' \
    -d '{"name":"my-openai","connector_name":"openai"}'
response 201
{
  "id": "a1b2c3d4-...",
  "name": "my-openai",
  "connector_name": "openai",
  "auth_type": "api_key",
  "is_active": true,
  "rate_limit_rules": [],
  "created_at": "2026-03-08T00:00:00Z"
}
GET /v1/services requires auth

List all active services registered by the current developer, ordered by creation date descending.

GET /v1/services/{service_id} requires auth

Get details for a specific service by UUID.

PATCH /v1/services/{service_id} requires auth

Update service metadata or toggle the active flag. All fields are optional.

Request body

FieldTypeDescription
display_nameoptstringNew display name.
descriptionoptstringNew description.
is_activeoptboolSet to false to soft-delete; true to reactivate.
DELETE /v1/services/{service_id} requires auth

Soft-delete a service (sets is_active = false). The record and its credentials are retained for audit purposes. Use PATCH with is_active: true to reactivate. Returns 204 No Content.

Credentials

Credentials are Fernet-encrypted before storage. The plaintext is never written to disk. See the Connectors guide for required fields per connector.

POST /v1/services/{service_id}/credentials requires auth

Encrypt and store credentials for a service. Can only be called once โ€” use PUT to update.

Request body

FieldTypeDescription
token_type*stringOne of "api_key", "oauth2", or "jwt". Use "api_key" for all 7 built-in connectors.
data*objectCredential fields. For api_key: {"api_key": "..."}. For oauth2: {"client_id": "...", "client_secret": "..."}.
shell โ€” OpenAI example
$ curl -sX POST https://clavisagent.com/v1/services/a1b2c3d4-.../credentials \
    -H 'Authorization: Bearer eyJ...' \
    -H 'Content-Type: application/json' \
    -d '{"token_type":"api_key","data":{"api_key":"sk-..."}}'
shell โ€” Kalshi example (email + password)
$ curl -sX POST https://clavisagent.com/v1/services/a1b2c3d4-.../credentials \
    -H 'Authorization: Bearer eyJ...' \
    -H 'Content-Type: application/json' \
    -d '{"token_type":"api_key","data":{"email":"you@example.com","password":"..."}}'
GET /v1/services/{service_id}/credentials requires auth

Return credential metadata โ€” never the plaintext secret or encrypted blob. Useful to check when credentials were created or last used.

response 200
{
  "id": "uuid",
  "service_id": "uuid",
  "token_type": "api_key",
  "expires_at": null,
  "last_used_at": "2026-03-08T10:00:00Z",
  "created_at": "2026-03-08T00:00:00Z"
}
PUT /v1/services/{service_id}/credentials requires auth

Replace credential data. Re-encrypts the new payload, clears the cached access token, and invalidates the Redis token cache. Use this to rotate credentials.

Request body

FieldTypeDescription
data*objectNew credential fields (same shape as POST).
DELETE /v1/services/{service_id}/credentials requires auth

Permanently remove stored credentials. Returns 204 No Content.

Tokens

The token endpoints return ready-to-use tokens, handling decryption, caching, refresh, and retries transparently.

GET /v1/tokens/{service_name} requires auth

Get a valid access token for the named service. Auto-refreshes if expired. Uses Redis cache for <5ms response on cache hit.

{service_name} is the name you chose when registering the service (e.g., my-openai) โ€” not the connector name.
shell
$ curl -s https://clavisagent.com/v1/tokens/my-openai \
    -H 'Authorization: Bearer eyJ...'
response 200
{
  "service_name": "my-openai",
  "token_type": "Bearer",
  "access_token": "sk-...",
  "expires_at": null
}

Response headers

HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the rate limit window.
X-RateLimit-RemainingRequests remaining in the current window.
X-RateLimit-ResetUnix timestamp when the window resets.
POST /v1/tokens/{service_name}/invalidate requires auth

Force-invalidate the cached token for a service, triggering a fresh fetch on the next get_token() call. Useful after external credential rotation. Returns 204 No Content.

Proxy

The proxy endpoints forward requests to the upstream service with auth injected and rate limits tracked. Clavis handles signing (e.g., Coinbase HMAC) and injects the correct headers per connector.

POST /v1/proxy/{service_name} requires auth

Proxy a request. The target path is in the request body.

Request body

FieldTypeDescription
methodoptstringHTTP method. Default: "GET".
path*stringPath on the target service (e.g., "/v1/chat/completions").
paramsoptobjectURL query parameters.
bodyoptobjectJSON request body.
headersoptobjectExtra headers to merge (auth headers take precedence).
shell โ€” chat completion via proxy
$ curl -sX POST https://clavisagent.com/v1/proxy/my-openai \
    -H 'Authorization: Bearer eyJ...' \
    -H 'Content-Type: application/json' \
    -d '{
      "method": "POST",
      "path": "/v1/chat/completions",
      "body": {"model":"gpt-4o","messages":[{"role":"user","content":"Hello"}]}
    }'
response 200
{
  "status_code": 200,
  "headers": { "content-type": "application/json", "...": "..." },
  "body": { "id": "chatcmpl-...", "choices": [...] }
}
POST /v1/proxy/{service_name}/{path} requires auth

Alternative proxy form โ€” target path comes from the URL instead of the body. Useful for REST-style integrations.

Request body

FieldTypeDescription
methodoptstringHTTP method. Default: "GET".
paramsoptobjectURL query parameters.
bodyoptobjectJSON request body.
headersoptobjectExtra headers.
shell โ€” path in URL form
$ curl -sX POST \
    https://clavisagent.com/v1/proxy/my-openai/v1/chat/completions \
    -H 'Authorization: Bearer eyJ...' \
    -H 'Content-Type: application/json' \
    -d '{"method":"POST","body":{"model":"gpt-4o","messages":[{"role":"user","content":"Hello"}]}}'

Error Codes

All errors return a JSON body with a detail field explaining the issue:

error response shape
{ "detail": "Human-readable explanation with a suggested fix." }
StatusMeaning
400Bad request โ€” missing or invalid fields. Check the detail message.
401Unauthorized โ€” missing or expired Bearer token. Re-login at POST /v1/auth/login.
403Forbidden โ€” account is inactive.
404Not found โ€” service, credential, or resource doesn't exist.
409Conflict โ€” resource already exists (duplicate service name, duplicate credentials).
422Validation error โ€” field type or constraint violation.
429Rate limit exceeded. Check X-RateLimit-Reset and Retry-After headers.
503Token unavailable โ€” connector could not authenticate. Check stored credentials.