API reference
Agents
Management endpoints for agents, keys and registration tokens, plus the registration-token key endpoint used by the CLI.
Base URL https://imnotahuman.ai/api/v1. Request bodies must be JSON with Content-Type: application/json (else 415) and at most 32,000 bytes. Bodies are validated strictly: unknown fields fail with VALIDATION_FAILED. Every response carries X-Request-Id (echoing yours if you send one) and Cache-Control: no-store except JWKS. Errors are { "error": { "code", "message", "details"? } }; see Errors.
Management endpoints require Authorization: Bearer <access token> where the token is the Supabase Auth access token from an email-and-password dashboard session. It is validated on every request, so signing out revokes access immediately. Missing header: AUTHENTICATION_REQUIRED (401); invalid or expired: INVALID_SESSION (401). Resources you do not own return NOT_FOUND. Rate limits: 600/min per network, 300/min per user.
List and create agents
curl https://imnotahuman.ai/api/v1/agents -H 'authorization: Bearer <token>'
curl -X POST https://imnotahuman.ai/api/v1/agents \
-H 'authorization: Bearer <token>' -H 'content-type: application/json' \
-d '{"name":"Nova","description":"Shopping assistant","website":"https://nova.example"}'| Field | Type | Description |
|---|---|---|
namerequired | string 1–80 | Display name; the agent id slug is derived from it. |
description | string ≤ 500 | Free text. |
website | URL ≤ 300 | http or https URL. |
{
"agent": {
"id": "agent_nova_8f2a",
"name": "Nova",
"description": "Shopping assistant",
"website": "https://nova.example/",
"status": "pending",
"created_at": "2026-09-20T11:50:00.000Z",
"updated_at": "2026-09-20T11:50:00.000Z",
"revoked_at": null,
"last_used_at": null
}
}Limit 50 agents per account (CONFLICT beyond). GET returns { "agents": [...] }.
Read, update, delete
# { "agent", "keys": [...], "recent": [events] }
curl https://imnotahuman.ai/api/v1/agents/agent_nova_8f2a -H 'authorization: Bearer <token>'
curl -X PATCH https://imnotahuman.ai/api/v1/agents/agent_nova_8f2a \
-H 'authorization: Bearer <token>' -H 'content-type: application/json' \
-d '{"name":"Nova v2"}'
curl -X DELETE https://imnotahuman.ai/api/v1/agents/agent_nova_8f2a -H 'authorization: Bearer <token>'
# { "deleted": true }PATCH accepts name, description, website. GET includes the agent's keys and the 25 most recent events.
Disable, enable, revoke
curl -X POST https://imnotahuman.ai/api/v1/agents/agent_nova_8f2a/revoke -H 'authorization: Bearer <token>'
# { "agent": { ..., "status": "revoked", "revoked_at": "..." } }Revoke is permanent and revokes every key. Calls on a revoked agent fail with AGENT_REVOKED. See Revoke keys.
Registration tokens
curl -X POST https://imnotahuman.ai/api/v1/agents/agent_nova_8f2a/registration-tokens \
-H 'authorization: Bearer <token>'
# 201 { "registration_token": "reg_...", "agent_id": "agent_nova_8f2a", "expires_at": "2026-09-20T12:15:00.000Z" }The raw token is returned exactly once; only its SHA-256 hash is stored. Valid 15 minutes, single use. Not available for revoked agents.
Keys
curl -X POST https://imnotahuman.ai/api/v1/agents/agent_nova_8f2a/keys \
-H 'authorization: Bearer <token>' -H 'content-type: application/json' \
-d '{"public_key":"_Gqb_W0_oiqrRCCw8P_X8DSeNSwTiMpA4rUS3OqqBZk","label":"prod-1"}'| Field | Type | Description |
|---|---|---|
public_keyrequired | string | JWK | Ed25519 public key: base64url/base64 raw, base64 SPKI, PEM PUBLIC KEY, or OKP JWK. |
label | string ≤ 80 | Shown in the dashboard. |
{
"agent": { "id": "agent_nova_8f2a", "status": "pending", ... },
"key": {
"id": "key_b7n2xq4mfc3rtw6y",
"agent_id": "agent_nova_8f2a",
"algorithm": "Ed25519",
"public_key": "_Gqb_W0_oiqrRCCw8P_X8DSeNSwTiMpA4rUS3OqqBZk",
"key_thumbprint": "fIpJN_bqfhSP3P4ikoK4_vs36sWvfiDG3cgfCRJ6GRo",
"label": "prod-1",
"status": "pending",
"created_at": "2026-09-20T11:55:00.000Z",
"activated_at": null,
"revoked_at": null,
"last_used_at": null
},
"challenge": { "challenge_id": "ch_...", "purpose": "registration", "action": "register_key", "intent": "key_b7n2xq4mfc3rtw6y", "expires_at": 1789906500, "challenge_url": "https://imnotahuman.ai/c/ch_...", ... }
}The key stays pending until the returned registration challenge is signed with it. Errors: KEY_INVALID (400), KEY_LIMIT (409, five non-revoked keys), CONFLICT (409, duplicate key), AGENT_REVOKED (403).
Register a key with a registration token
curl -X POST https://imnotahuman.ai/api/v1/registration/keys \
-H 'authorization: Bearer reg_...' -H 'content-type: application/json' \
-d '{"public_key":"_Gqb_W0_oiqrRCCw8P_X8DSeNSwTiMpA4rUS3OqqBZk","label":"prod-1"}'Same body and response as POST /agents/:id/keys, authenticated by the one-time registration token instead of a session. The key is validated first, so a malformed or duplicate key does not consume the token; it is consumed only when the key is accepted. Invalid, expired or used tokens: REGISTRATION_TOKEN_INVALID (401). Rate limit 30/min per network and 10/min per agent.
Events, dashboard and profile
curl 'https://imnotahuman.ai/api/v1/events?agent_id=agent_nova_8f2a&limit=20' -H 'authorization: Bearer <token>'
# { "events": [ { "id": "ev_...", "challenge_id": "ch_...", "site_id": "site_...", "agent_id": "...", "agent_name": "...",
# "method": "ed25519_challenge", "result": "VERIFIED", "failure_reason": null, "mode": "live",
# "origin": "https://example.com", "created_at": "..." } ] }
curl https://imnotahuman.ai/api/v1/dashboard -H 'authorization: Bearer <token>' # { "summary", "recent": [10 events] }
curl https://imnotahuman.ai/api/v1/me -H 'authorization: Bearer <token>' # { "user": { "id", "email" }, "profile" }
curl -X PATCH https://imnotahuman.ai/api/v1/me -H 'authorization: Bearer <token>' \
-H 'content-type: application/json' -d '{"display_name":"Ada"}'limit is clamped to 1–200 (default 50). Events cover sites and agents you own; failure_reason is an error code for REJECTED events.