{"openapi":"3.1.0","info":{"title":"Lithtrix API","description":"**Agent-native search API.** Agents register themselves, receive an `ltx_` API key, and search the web with credibility-scored results — no human involvement required.\n\n**Quickstart for agents:** `GET /v1/guide` returns a complete machine-readable walkthrough.\n\n**Agent flow:** `GET /v1/capabilities` → `POST /v1/register` → `GET /v1/search` → `GET /v1/billing` → `POST /v1/billing/setup` (if upgrading)\n\n**MCP:** Install `lithtrix-mcp` via npm for Claude/MCP client integration. Tool definitions: `GET /mcp/lithtrix-search.json`, `GET /mcp/lithtrix-register.json`.\n\n**Auth:** `Authorization: Bearer ltx_...` on all `/v1/` routes except register, capabilities, billing/config, and guide.","version":"1.0.0"},"paths":{"/health":{"get":{"tags":["health"],"summary":"Liveness probe","description":"Returns `status` and semantic API `version` for load balancers and operators. No authentication required.","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health Health Get"}}}}}}},"/v1/capabilities":{"get":{"tags":["discovery"],"summary":"Machine-readable API capabilities","description":"Lithtrix-native description of endpoints, authentication, and behaviour. No authentication required.","operationId":"capabilities_v1_capabilities_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"x-agent-hint":"Start here. No auth required. Returns rate limits, endpoints, and credibility scoring rules."}},"/v1/guide":{"get":{"tags":["guide"],"summary":"Agent quickstart guide","description":"Machine-readable step-by-step guide for agents: discover → register → search → check usage → upgrade. No authentication required. Follow steps in order.","operationId":"get_guide_v1_guide_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"x-agent-hint":"Start here if you are new to Lithtrix. This endpoint returns everything you need to go from zero to searching."}},"/v1/register":{"post":{"tags":["register"],"summary":"Register a new agent","description":"Create an `agents` row and return a one-time `ltx_` API key (SHA-256 stored). The same `agent_name` + `owner_identifier` pair returns HTTP 409.","operationId":"register_agent_v1_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-agent-hint":"Step 1 (after discovery). No auth required. Returns your ltx_ API key — store it immediately, it is shown only once."}},"/v1/me":{"get":{"tags":["agent"],"summary":"Get current agent profile","description":"Returns profile fields for the Bearer-authenticated agent (name, owner, tier, limits).","operationId":"read_me_v1_me_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/usage":{"get":{"tags":["agent"],"summary":"Get usage statistics","description":"Monthly call count, remaining quota, and a seven-day UTC daily breakdown from `usage_logs`.","operationId":"read_usage_v1_usage_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageStatsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/keys/rotate":{"post":{"tags":["agent"],"summary":"Rotate API key","description":"Replace the stored key hash with a new `ltx_` key. The previous key stops working immediately after this call succeeds.","operationId":"rotate_api_key_v1_keys_rotate_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyRotateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/billing/config":{"get":{"tags":["billing"],"summary":"Get Billing Config","description":"Return the Stripe publishable key for minting PaymentMethods (no auth).\n\nReturns:\n    JSON with ``stripe_publishable_key``.","operationId":"get_billing_config_v1_billing_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingConfigResponse"}}}}}}},"/v1/billing":{"get":{"tags":["billing"],"summary":"Get Billing","description":"Return tier, usage totals, over-limit flag, and Stripe customer id if any.\n\nArgs:\n    agent: Authenticated agent from Supabase.\n\nReturns:\n    Billing status for the current agent.","operationId":"get_billing_v1_billing_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-agent-hint":"Check calls_total vs call_limit. When over_limit is true, call POST /v1/billing/setup to upgrade."}},"/v1/billing/setup":{"post":{"tags":["billing"],"summary":"Post Billing Setup","description":"Attach a PaymentMethod, create or reuse a Stripe Customer, and upgrade to Pro.\n\nArgs:\n    body: Stripe ``payment_method_id`` (``pm_...``).\n    agent: Authenticated agent row.\n\nReturns:\n    Success payload with Pro tier and Stripe customer id.\n\nRaises:\n    HTTPException: 400 on invalid payment method, 502 on other Stripe errors.","operationId":"post_billing_setup_v1_billing_setup_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingSetupRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingSetupSuccessResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/billing/webhook":{"post":{"tags":["billing"],"summary":"Post Billing Webhook","description":"Handle Stripe webhooks: verify signature, log payment events (MVP).\n\nArgs:\n    request: Raw ASGI request (body must not be pre-parsed as JSON).\n\nReturns:\n    ``{\"status\": \"ok\"}`` on success; 400 if signature verification fails.","operationId":"post_billing_webhook_v1_billing_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/agents":{"get":{"tags":["admin"],"summary":"List Agents","description":"List agents with monthly call counts (paginated).\n\nArgs:\n    _: Valid admin key dependency.\n    page: Page number (1-based).\n    page_size: Page size (max 100).\n\nReturns:\n    Paginated agents and call counts for the current UTC month.","operationId":"list_agents_admin_agents_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Page Size"}},{"name":"X-Admin-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentsListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/agents/{agent_id}":{"get":{"tags":["admin"],"summary":"Get Agent Detail","description":"Return full agent row, monthly calls, and 7-day daily breakdown.\n\nArgs:\n    _: Admin key.\n    agent_id: Agent UUID.\n\nReturns:\n    Combined agent detail payload.\n\nRaises:\n    HTTPException: 404 if the agent does not exist.","operationId":"get_agent_detail_admin_agents__agent_id__get","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","description":"Agent UUID","title":"Agent Id"},"description":"Agent UUID"},{"name":"X-Admin-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Agent Detail Admin Agents  Agent Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/stats":{"get":{"tags":["admin"],"summary":"Get Stats","description":"Return aggregate counts for agents and usage.\n\nArgs:\n    _: Admin key.\n\nReturns:\n    Totals for dashboard-style monitoring.","operationId":"get_stats_admin_stats_get","parameters":[{"name":"X-Admin-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/agents/{agent_id}/suspend":{"post":{"tags":["admin"],"summary":"Suspend Agent","description":"Set agent status to ``suspended``.\n\nArgs:\n    _: Admin key.\n    agent_id: Agent UUID.\n\nReturns:\n    Acknowledgment with new status.\n\nRaises:\n    HTTPException: 404 if no row updated.","operationId":"suspend_agent_admin_agents__agent_id__suspend_post","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","description":"Agent UUID","title":"Agent Id"},"description":"Agent UUID"},{"name":"X-Admin-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusActionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/agents/{agent_id}/reinstate":{"post":{"tags":["admin"],"summary":"Reinstate Agent","description":"Set agent status to ``active``.\n\nArgs:\n    _: Admin key.\n    agent_id: Agent UUID.\n\nReturns:\n    Acknowledgment with new status.\n\nRaises:\n    HTTPException: 404 if no row updated.","operationId":"reinstate_agent_admin_agents__agent_id__reinstate_post","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","description":"Agent UUID","title":"Agent Id"},"description":"Agent UUID"},{"name":"X-Admin-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusActionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/search":{"get":{"tags":["search"],"summary":"Search the web","description":"Brave-backed web search with HTML-free snippets and heuristic credibility scores. Requires `Authorization: Bearer ltx_...`. Repeated identical queries may be served from Redis (`cached: true`) to save Brave quota. Logs usage and returns usage quota.","operationId":"search_v1_search_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":500,"description":"Search query string (1–500 characters).","title":"Q"},"description":"Search query string (1–500 characters)."},{"name":"num_results","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":1,"description":"Number of search results to return (1–20, default 10).","default":10,"title":"Num Results"},"description":"Number of search results to return (1–20, default 10)."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchSuccessResponse"}}}},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchErrorResponse"}}},"description":"Bad Gateway"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-agent-hint":"The primary endpoint. Requires Bearer token. Returns credibility-scored results and your remaining quota in usage.calls_remaining."}}},"components":{"schemas":{"AgentListItem":{"properties":{"id":{"type":"string","title":"Id"},"agent_name":{"type":"string","title":"Agent Name"},"owner_identifier":{"type":"string","title":"Owner Identifier"},"tier":{"type":"string","title":"Tier"},"status":{"type":"string","title":"Status"},"created_at":{"type":"string","title":"Created At"},"calls_this_month":{"type":"integer","title":"Calls This Month"}},"type":"object","required":["id","agent_name","owner_identifier","tier","status","created_at","calls_this_month"],"title":"AgentListItem","description":"Agent summary for admin list."},"AgentsListResponse":{"properties":{"agents":{"items":{"$ref":"#/components/schemas/AgentListItem"},"type":"array","title":"Agents"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"}},"type":"object","required":["agents","total","page","page_size"],"title":"AgentsListResponse","description":"Paginated agent list."},"BillingConfigResponse":{"properties":{"stripe_publishable_key":{"type":"string","title":"Stripe Publishable Key"}},"type":"object","required":["stripe_publishable_key"],"title":"BillingConfigResponse","description":"Public Stripe publishable key for client-side PaymentMethod creation."},"BillingSetupRequest":{"properties":{"payment_method_id":{"type":"string","minLength":1,"title":"Payment Method Id","description":"Stripe pm_... token"}},"type":"object","required":["payment_method_id"],"title":"BillingSetupRequest","description":"Client-provided Stripe PaymentMethod ID."},"BillingSetupSuccessResponse":{"properties":{"tier":{"type":"string","title":"Tier","default":"pro"},"stripe_customer_id":{"type":"string","title":"Stripe Customer Id"},"message":{"type":"string","title":"Message"}},"type":"object","required":["stripe_customer_id","message"],"title":"BillingSetupSuccessResponse","description":"Successful upgrade to Pro tier."},"BillingStatusResponse":{"properties":{"tier":{"type":"string","title":"Tier"},"calls_total":{"type":"integer","title":"Calls Total"},"call_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Call Limit"},"over_limit":{"type":"boolean","title":"Over Limit"},"stripe_customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stripe Customer Id"}},"type":"object","required":["tier","calls_total","call_limit","over_limit","stripe_customer_id"],"title":"BillingStatusResponse","description":"Current billing snapshot for the authenticated agent."},"DailyBreakdownItem":{"properties":{"date":{"type":"string","title":"Date"},"calls":{"type":"integer","title":"Calls"}},"type":"object","required":["date","calls"],"title":"DailyBreakdownItem","description":"Single day in the usage breakdown."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"KeyRotateResponse":{"properties":{"api_key":{"type":"string","title":"Api Key"},"message":{"type":"string","title":"Message","default":"Your old key has been invalidated. Store this new key securely."}},"type":"object","required":["api_key"],"title":"KeyRotateResponse","description":"One-time new key after rotation."},"MeResponse":{"properties":{"agent_id":{"type":"string","title":"Agent Id"},"agent_name":{"type":"string","title":"Agent Name"},"owner_identifier":{"type":"string","title":"Owner Identifier"},"tier":{"type":"string","title":"Tier"},"monthly_limit":{"type":"integer","title":"Monthly Limit"},"status":{"type":"string","title":"Status"},"created_at":{"type":"string","title":"Created At"}},"type":"object","required":["agent_id","agent_name","owner_identifier","tier","monthly_limit","status","created_at"],"title":"MeResponse","description":"Public agent profile for ``GET /v1/me``."},"RegisterRequest":{"properties":{"agent_name":{"type":"string","maxLength":100,"minLength":1,"title":"Agent Name"},"owner_identifier":{"type":"string","maxLength":255,"minLength":1,"title":"Owner Identifier"}},"type":"object","required":["agent_name","owner_identifier"],"title":"RegisterRequest","description":"Body for `POST /v1/register`."},"SearchErrorResponse":{"properties":{"status":{"type":"string","const":"error","title":"Status","default":"error"},"error_code":{"type":"string","title":"Error Code"},"message":{"type":"string","title":"Message"}},"type":"object","required":["error_code","message"],"title":"SearchErrorResponse","description":"Standard API error envelope for search and global handlers."},"SearchResultItem":{"properties":{"title":{"type":"string","title":"Title"},"url":{"type":"string","title":"Url"},"snippet":{"type":"string","title":"Snippet"},"source":{"type":"string","title":"Source"},"credibility_score":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Credibility Score"},"published_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Published Date"}},"type":"object","required":["title","url","snippet","source","credibility_score"],"title":"SearchResultItem","description":"Single search result aligned with the locked response schema."},"SearchSuccessResponse":{"properties":{"status":{"type":"string","const":"success","title":"Status","default":"success"},"query":{"type":"string","title":"Query"},"results":{"items":{"$ref":"#/components/schemas/SearchResultItem"},"type":"array","title":"Results"},"cached":{"type":"boolean","title":"Cached","default":false},"response_time_ms":{"type":"integer","title":"Response Time Ms"},"usage":{"$ref":"#/components/schemas/UsageInfo"}},"type":"object","required":["query","results","response_time_ms","usage"],"title":"SearchSuccessResponse","description":"Successful search response including usage counters."},"StatsResponse":{"properties":{"total_agents":{"type":"integer","title":"Total Agents"},"active_agents":{"type":"integer","title":"Active Agents"},"flagged_agents":{"type":"integer","title":"Flagged Agents"},"calls_today":{"type":"integer","title":"Calls Today"},"calls_this_month":{"type":"integer","title":"Calls This Month"}},"type":"object","required":["total_agents","active_agents","flagged_agents","calls_today","calls_this_month"],"title":"StatsResponse","description":"Aggregate platform stats."},"StatusActionResponse":{"properties":{"status":{"type":"string","title":"Status","default":"ok"},"agent_id":{"type":"string","title":"Agent Id"},"new_status":{"type":"string","title":"New Status"}},"type":"object","required":["agent_id","new_status"],"title":"StatusActionResponse","description":"Result of suspend/reinstate."},"UsageInfo":{"properties":{"calls_total":{"type":"integer","title":"Calls Total"},"calls_remaining":{"type":"integer","title":"Calls Remaining"},"over_limit":{"type":"boolean","title":"Over Limit","default":false},"upgrade_url":{"type":"string","title":"Upgrade Url","default":"/v1/billing/setup"}},"type":"object","required":["calls_total","calls_remaining"],"title":"UsageInfo","description":"Usage snapshot for the authenticated agent."},"UsageStatsResponse":{"properties":{"calls_this_month":{"type":"integer","title":"Calls This Month"},"calls_remaining":{"type":"integer","title":"Calls Remaining"},"monthly_limit":{"type":"integer","title":"Monthly Limit"},"daily_breakdown":{"items":{"$ref":"#/components/schemas/DailyBreakdownItem"},"type":"array","title":"Daily Breakdown"}},"type":"object","required":["calls_this_month","calls_remaining","monthly_limit","daily_breakdown"],"title":"UsageStatsResponse","description":"Aggregated usage for ``GET /v1/usage``."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}