kite~/kite/docs/REST API
v0.2.1
Reference

API Reference

The Kite REST API powers the dashboard and CLI. All endpoints are under https://api.getkite.sh/api/v1.

// 01Authentication

Most API calls require an API key bearer token:

bash
Authorization: Bearer <your-api-key>

Obtain an API key from the dashboard or via device auth:

bash
kite login

Bearer-token endpoints also require team_id as a query parameter. API keys are scoped to one team; read, write, and admin permissions are hierarchical, so admin can call any bearer endpoint and write can call read endpoints.

Payment-backed routes use payment-signature for x402 payment submission. Legacy x-payment and x-payment-signature headers are also accepted. Successful paid calls return payment-response; unpaid calls return 402 with payment-required.

// 02Public endpoints

POST /bootstrap/x402

Bot-first onboarding paid with x402. This endpoint does not use bearer auth.

Request:

json
{
  "source": "my-bot",
  "deposit_atomic": 1000000,
  "plan": "starter"
}

source is required, lowercased by the server, and must be 1-64 alphanumeric or hyphen characters. deposit_atomic is optional and defaults to 1000000; values below 1000000 are rejected. plan is optional and defaults to the starter paid plan.

Response (paid):

json
{
  "team_id": "...",
  "source": "my-bot",
  "api_key": "kite_...",
  "endpoint": "/hooks/<team_id>/<source>",
  "endpoint_with_token": "/hooks/<team_id>/<source>/<hook_token>",
  "hook_token": "khk_...",
  "wallet_balance_atomic": 1000000,
  "network": "eip155:84532",
  "asset": "0x036CbD53842C5426634e7929541eC2318f3dCF7e",
  "credentials_available": true
}

Credentials are returned for successful new bootstraps and payment replays within the credential replay window. Later replays return the same team and endpoint metadata with credentials_available: false.

Common errors: 400 invalid source or deposit, 402 missing or invalid payment, 404 unavailable requested plan, 409 bootstrap session in progress, 503 x402 or bootstrap encryption not configured.

GET /webhook-config

Return the active outbound webhook config for ?team_id=<team>.

Auth: bearer token with read permission.

Response fields: id, team_id, url, active, event_types, created_at, updated_at.

Common errors: 401 invalid bearer token, 403 insufficient permissions, 404 no active webhook config found, 500 internal error.

PUT /webhook-config

Create or replace the active outbound webhook config for ?team_id=<team>.

Auth: bearer token with write permission.

Request:

json
{
  "url": "https://example.com/kite-events",
  "secret": "shared-delivery-secret",
  "event_types": ["com.kite.agent.message"]
}

url and secret are required. event_types is optional; an empty array accepts all event types. The secret is encrypted and is not returned.

Response fields: id, team_id, url, event_types, active.

Common errors: 400 missing or invalid url/secret, 401, 403, 500 including missing outbound webhook secret encryption.

DELETE /webhook-config

Deactivate the active outbound webhook config for ?team_id=<team>.

Auth: bearer token with write permission.

Response: { "ok": true }

Common errors: 401, 403, 404 no active webhook config found, 500.

GET /events

Replay retained events for ?team_id=<team>.

Auth: bearer token with read permission.

Query parameters:

NameRequiredDescription
team_idyesTeam to read events from. Must match the API key.
sincenoOpaque cursor: timestamp, optionally followed by :<event_id>. Missing means oldest retained event.
limitnoNumber of events to return, clamped to 1..1000; default 100.

Response:

json
{
  "events": [
    {
      "event_id": "01900000-0000-7000-8000-000000000001",
      "created_at": "2026-04-27 12:34:56.789",
      "event": { "specversion": "1.0", "type": "..." }
    }
  ]
}

x402 subscriptions may require a payment for the billable events returned. Common errors: 401, 402 payment required or invalid payment, 403 insufficient permissions or no active subscription when x402 fallback is disabled, 500 Tinybird/payment/internal errors.

GET /plans

List active subscription plans. No bearer auth required.

Response fields: plans[] with id, name, events_per_month, events_per_day, max_payload_bytes, price_atomic_monthly, price_atomic_per_event, plus legacy price_sats_* aliases.

Common errors: 500 internal error.

GET /subscription

Return the current non-cancelled subscription for ?team_id=<team>.

Auth: bearer token with read permission.

Response fields: subscription with id, plan_name, provider, status, events_used, events_limit, current_period_start, current_period_end; plan with plan limits and prices.

Common errors: 401, 403, 404 no active subscription, 500.

POST /subscription

Create or switch the current subscription for ?team_id=<team>.

Auth: bearer token with write permission.

Request:

json
{
  "plan_id": "00000000-0000-0000-0000-000000000000",
  "provider": "x402"
}

plan_id must be an active plan UUID. provider must be x402 or clerk.

Response fields: subscription.id, team_id, plan_id, provider, status, current_period_end.

Common errors: 400 invalid plan_id or provider, 401, 403, 404 plan not found or inactive, 409 active subscription conflict, 500.

GET /wallet

Return x402 wallet balances for ?team_id=<team>.

Auth: bearer token with read permission.

Response fields: balance_atomic, reserved_atomic, plus legacy balance_sats and reserved_sats aliases.

Common errors: 401, 403, 404 no active subscription, 409 wallet only available for x402 subscriptions, 500.

POST /wallet/invoices

Deposit x402 funds into the wallet for ?team_id=<team>.

Auth: bearer token with write permission.

Request:

json
{
  "amount_atomic": 1000000
}

amount_atomic is required and must be greater than zero. amount_sats is accepted as a legacy alias.

Without a valid payment, the response is 402 with payment-required. Retry with payment-signature to settle and credit the wallet.

Response fields (paid): balance_atomic, amount_deposited_atomic, plus legacy balance_sats and amount_deposited_sats aliases.

Common errors: 400 invalid amount, 401, 402 payment required or invalid, 403, 404 no active subscription, 409 wallet deposits only available for x402 subscriptions, 503 x402 disabled, 500.

GET /usage

Return current-period usage for ?team_id=<team>.

Auth: bearer token with read permission.

Response fields: events_used, events_limit, events_remaining, events_today, current_period_start, current_period_end, total_charged_atomic, plus legacy total_charged_sats. x402 subscriptions also include wallet_balance_atomic, wallet_balance_sats, and events_affordable.

Common errors: 401, 403, 404 no active subscription, 500.

POST /agents/messages

Send an agent-to-agent message for ?team_id=<team>.

Auth: bearer token with write permission.

Request:

json
{
  "from": "agent-beta",
  "to": "agent-alpha",
  "body": "Here are the results you asked for.",
  "thread_id": "thread-abc123",
  "reply_to_id": "01900000-0000-7000-8000-000000000001"
}

from, to, and body are required strings. from and to must be non-empty. The JSON body must be at most 64 KiB. thread_id and reply_to_id are optional.

Response: 202 Accepted

json
{
  "id": "01900000-0000-7000-8000-000000000001",
  "created_at": "2026-04-30T10:00:00Z",
  "from": "agent-beta",
  "to": "agent-alpha",
  "usage": {
    "events_used": 42,
    "events_limit": 100000,
    "amount_charged_atomic": 0
  }
}

Common errors: 400 invalid JSON or missing from/to, 401, 403, 413 payload too large, 429 rate limit exceeded, 500.

// 03Rate limits

PlanRequests/min
Free60
Starter300
Growth600
Pro1,000
EnterpriseUnlimited

// 04Error format

Errors return a JSON body with at least error:

json
{
  "error": "unauthorized",
  "message": "Invalid or expired API key"
}