{"openapi":"3.1.0","info":{"title":"AgentFetch","description":"MCP-native intelligent web fetch layer for AI agents. Token estimation, smart caching, and routing built in.","version":"1.0.0"},"paths":{"/fetch":{"post":{"tags":["fetch"],"summary":"Fetch Single","operationId":"fetch_single_fetch_post","parameters":[{"name":"X-AgentFetch-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Agentfetch-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FetchRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Fetch Single Fetch Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fetch/batch":{"post":{"tags":["fetch"],"summary":"Fetch Batch","operationId":"fetch_batch_fetch_batch_post","parameters":[{"name":"X-AgentFetch-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Agentfetch-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchFetchRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Fetch Batch Fetch Batch Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/estimate":{"get":{"tags":["fetch"],"summary":"Estimate","operationId":"estimate_estimate_get","parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string","description":"URL to estimate without fetching","title":"Url"},"description":"URL to estimate without fetching"},{"name":"X-AgentFetch-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Agentfetch-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Estimate Estimate Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/search":{"post":{"tags":["fetch"],"summary":"Search And Fetch","description":"Search via Jina, fetch top N results through our pipeline.","operationId":"search_and_fetch_search_post","parameters":[{"name":"X-AgentFetch-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Agentfetch-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Search And Fetch Search Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/cache":{"get":{"tags":["cache"],"summary":"Cache Check","operationId":"cache_check_cache_get","parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string","title":"Url"}},{"name":"X-AgentFetch-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Agentfetch-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Cache Check Cache Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["cache"],"summary":"Cache Invalidate","operationId":"cache_invalidate_cache_delete","parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string","title":"Url"}},{"name":"X-AgentFetch-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Agentfetch-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Cache Invalidate Cache Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/account/signup":{"post":{"tags":["account"],"summary":"Signup","description":"Create an account + first API key. Returns the plaintext key once.\n\nAlso emails the key via SendGrid so the user has a copy. The response\nincludes the plaintext key for the in-page success state — but the email\nis the durable record.\n\nOn duplicate email we return 200 with a generic \"check your email\" message\n(and send a magic-link instead of a new key) so attackers can't enumerate\nregistered emails by watching status codes.","operationId":"signup_account_signup_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Signup Account Signup Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/account/me":{"get":{"tags":["account"],"summary":"Me","operationId":"me_account_me_get","parameters":[{"name":"X-AgentFetch-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Agentfetch-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Me Account Me Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/account/keys":{"get":{"tags":["account"],"summary":"List Keys","operationId":"list_keys_account_keys_get","parameters":[{"name":"X-AgentFetch-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Agentfetch-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/KeyOut"},"title":"Response List Keys Account Keys Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["account"],"summary":"Create Key","operationId":"create_key_account_keys_post","parameters":[{"name":"label","in":"query","required":false,"schema":{"type":"string","default":"additional","title":"Label"}},{"name":"X-AgentFetch-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Agentfetch-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Create Key Account Keys Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/account/keys/{key_id}":{"delete":{"tags":["account"],"summary":"Revoke Key","operationId":"revoke_key_account_keys__key_id__delete","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"integer","title":"Key Id"}},{"name":"X-AgentFetch-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Agentfetch-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Revoke Key Account Keys  Key Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/account/usage":{"get":{"tags":["account"],"summary":"Usage Summary","description":"Aggregate usage for the current calendar month.","operationId":"usage_summary_account_usage_get","parameters":[{"name":"X-AgentFetch-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Agentfetch-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Usage Summary Account Usage Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/spec":{"get":{"tags":["discovery"],"summary":"Get Spec","description":"Canonical machine-readable spec for AgentFetch.\n\nAgents and integration-builders should hit this URL first. It returns:\n  - product summary\n  - links to the OpenAPI schema and MCP manifest\n  - the four MCP tools and their descriptions\n  - auth instructions\n  - pricing in machine-readable form\n\nDesigned to be the *single page* that fully describes the product. No\ncrawling required.","operationId":"get_spec_spec_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Get Spec Spec Get"}}}}}}},"/.well-known/mcp.json":{"get":{"tags":["discovery"],"summary":"Get Mcp Manifest","description":"Serve the MCP manifest at the well-known location.\n\nSome MCP-aware tools probe `/.well-known/mcp.json` to discover capabilities.","operationId":"get_mcp_manifest__well_known_mcp_json_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Get Mcp Manifest  Well Known Mcp Json Get"}}}}}}},"/llms.txt":{"get":{"tags":["discovery"],"summary":"Get Llms Txt","description":"Serve llms.txt for agent crawlers.\n\nFollows the emerging llms.txt convention (https://llmstxt.org). Agents that\ncrawl this domain should look here first to find the canonical pages worth\nindexing — saves them from parsing nav-heavy HTML.","operationId":"get_llms_txt_llms_txt_get","responses":{"200":{"description":"Successful Response","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/auth/login":{"post":{"tags":["auth"],"summary":"Login","description":"Send a magic link to the email if it's a registered account.\n\nAlways returns 202 — never reveal whether an email is registered.","operationId":"login_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Login Auth Login Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/verify":{"get":{"tags":["auth"],"summary":"Verify","description":"Exchange a magic-link token for a session cookie.","operationId":"verify_auth_verify_get","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Verify Auth Verify Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/logout":{"post":{"tags":["auth"],"summary":"Logout","operationId":"logout_auth_logout_post","parameters":[{"name":"agentfetch_session","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agentfetch Session"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Logout Auth Logout Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/checkout":{"post":{"tags":["billing"],"summary":"Create Checkout","description":"Authed via session cookie. Returns a Stripe-hosted Checkout URL.","operationId":"create_checkout_billing_checkout_post","parameters":[{"name":"agentfetch_session","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agentfetch Session"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Create Checkout Billing Checkout Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/webhook":{"post":{"tags":["billing"],"summary":"Stripe Webhook","description":"Stripe webhook handler — verifies signature, updates account state.\n\nEvents handled:\n  checkout.session.completed       — upgrade plan or credit balance\n  customer.subscription.deleted    — downgrade to free\n  customer.subscription.updated    — change plan tier","operationId":"stripe_webhook_billing_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Stripe Webhook Billing Webhook Post"}}}}}}},"/billing/portal":{"get":{"tags":["billing"],"summary":"Customer Portal","description":"Generate a Stripe Customer Portal URL so the user can manage billing.","operationId":"customer_portal_billing_portal_get","parameters":[{"name":"agentfetch_session","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agentfetch Session"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Customer Portal Billing Portal Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/metrics":{"get":{"tags":["admin"],"summary":"Metrics","description":"Aggregate every metric in one DB session for consistency.","operationId":"metrics_admin_metrics_get","parameters":[{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Admin token","title":"Token"},"description":"Admin token"},{"name":"X-Admin-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Admin-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Metrics Admin Metrics Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/examples":{"get":{"tags":["examples"],"summary":"Index","operationId":"index_examples_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/examples/{slug}":{"get":{"tags":["examples"],"summary":"Pattern","operationId":"pattern_examples__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/":{"get":{"tags":["web"],"summary":"Landing","operationId":"landing__get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/langchain":{"get":{"tags":["web"],"summary":"Langchain","operationId":"langchain_langchain_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/dashboard":{"get":{"tags":["web"],"summary":"Dashboard","operationId":"dashboard_dashboard_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/auth/whoami":{"get":{"tags":["web"],"summary":"Whoami","operationId":"whoami_auth_whoami_get","parameters":[{"name":"agentfetch_session","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agentfetch Session"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Whoami Auth Whoami Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/keys":{"get":{"tags":["web"],"summary":"Auth List Keys","operationId":"auth_list_keys_auth_keys_get","parameters":[{"name":"agentfetch_session","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agentfetch Session"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object"},"title":"Response Auth List Keys Auth Keys Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["web"],"summary":"Auth Create Key","operationId":"auth_create_key_auth_keys_post","parameters":[{"name":"agentfetch_session","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agentfetch Session"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Auth Create Key Auth Keys Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/keys/{key_id}":{"delete":{"tags":["web"],"summary":"Auth Revoke Key","operationId":"auth_revoke_key_auth_keys__key_id__delete","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"integer","title":"Key Id"}},{"name":"agentfetch_session","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agentfetch Session"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Auth Revoke Key Auth Keys  Key Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/usage":{"get":{"tags":["web"],"summary":"Auth Usage","operationId":"auth_usage_auth_usage_get","parameters":[{"name":"agentfetch_session","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agentfetch Session"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Auth Usage Auth Usage Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health":{"get":{"summary":"Health","description":"Liveness probe — returns 200 as long as the process is up.\n\nRailway healthcheck targets this. We deliberately don't check DB/Redis\nhere: a transient cache outage shouldn't kill the container. Use /ready\nfor full dependency status.","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Health Health Get"}}}}}}},"/ready":{"get":{"summary":"Ready","description":"Readiness probe — returns 503 if DB or Redis is unreachable.\n\nIncludes a `checks` dict so callers can see exactly what's broken.\nUse this for monitoring, not for Railway healthcheck.","operationId":"ready_ready_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"BatchFetchRequest":{"properties":{"urls":{"items":{"type":"string","maxLength":2083,"minLength":1,"format":"uri"},"type":"array","maxItems":20,"minItems":1,"title":"Urls"},"max_tokens_each":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Max Tokens Each"},"use_cache":{"type":"boolean","title":"Use Cache","default":true}},"type":"object","required":["urls"],"title":"BatchFetchRequest"},"CheckoutBody":{"properties":{"mode":{"type":"string","enum":["pack","subscription"],"title":"Mode"},"item_key":{"type":"string","enum":["10k","100k","1m","starter","pro","scale"],"title":"Item Key"}},"type":"object","required":["mode","item_key"],"title":"CheckoutBody"},"FetchRequest":{"properties":{"url":{"type":"string","maxLength":2083,"minLength":1,"format":"uri","title":"Url"},"max_tokens":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Max Tokens","description":"Trim response to this token budget."},"format":{"type":"string","enum":["markdown","text","json"],"title":"Format","default":"markdown"},"use_cache":{"type":"boolean","title":"Use Cache","default":true}},"type":"object","required":["url"],"title":"FetchRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"KeyOut":{"properties":{"id":{"type":"integer","title":"Id"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"},"revoked":{"type":"boolean","title":"Revoked"}},"type":"object","required":["id","label","created_at","last_used_at","revoked"],"title":"KeyOut"},"LoginRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"}},"type":"object","required":["email"],"title":"LoginRequest"},"SearchRequest":{"properties":{"query":{"type":"string","maxLength":500,"minLength":2,"title":"Query"},"num_results":{"type":"integer","maximum":10.0,"minimum":1.0,"title":"Num Results","default":3},"max_tokens_each":{"type":"integer","maximum":20000.0,"minimum":100.0,"title":"Max Tokens Each","default":2000}},"type":"object","required":["query"],"title":"SearchRequest"},"SignupRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"label":{"type":"string","maxLength":64,"title":"Label","default":"default"}},"type":"object","required":["email"],"title":"SignupRequest"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}