{"openapi":"3.1.0","info":{"title":"OKF Index","version":"597d0edd","description":"The search index of Open Knowledge Format bundles. Index: GET /api/."},"servers":[{"url":"https://staging.okfindex.com"}],"components":{"schemas":{"Saude":{"type":"object","properties":{"ok":{"type":"boolean","description":"Always `true` when the Worker answers."},"app":{"type":"string","description":"Display name of the product."},"build":{"type":"string","description":"Commit published (`dev` outside the CI)."}},"required":["ok","app","build"],"description":"Liveness of the Worker and the build it is serving."},"PaginaDeBundles":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Bundle"},"description":"The bundles on this page."},"limit":{"type":"integer","description":"Page size applied."},"offset":{"type":"integer","description":"Offset applied."},"next_offset":{"type":"integer","description":"Offset of the next page; `null` when there is no more (or past the 1000 cap).","nullable":true},"next":{"type":"string","description":"Absolute URL of the next page, same filters; follow it until it comes back `null`.","nullable":true}},"required":["items","limit","offset","next_offset","next"],"description":"A page of the index. No `total`: counting on every search would cost a scan without changing any decision — `GET /api/okf/stats` has the totals."},"Bundle":{"type":"object","properties":{"id":{"type":"string","description":"Bundle id; the key across the whole API."},"name":{"type":"string","description":"Title of the root `index.md`; `owner/repo · dir` when it has none or the title is a listing heading (`Files`, `Index`)."},"tagline":{"type":"string","description":"One line from the frontmatter `description`; empty when the author gave none."},"description":{"type":"string","description":"Body of the root `index.md`, capped at 1000 characters."},"okf_version":{"type":"string","description":"The `okf_version` the bundle declares (0.1 and 0.2 coexist)."},"concepts":{"type":"integer","description":"How many linked entries the root index lists."},"concept_list":{"type":"array","items":{"$ref":"#/components/schemas/Concept"},"description":"The entries the root lists, in order, up to 24 — read from the indexed body, so a very long root is cut."},"type":{"type":"string","description":"The `type` declared in the root frontmatter, when any."},"index_url":{"type":"string","description":"The root `index.md`, raw — what you hand to an agent."},"page_url":{"type":"string","description":"The page a human opens: the file on GitHub, or the bundle URL on its site."},"source":{"allOf":[{"$ref":"#/components/schemas/BundleSource"}],"description":"Provenance and location of the bundle."},"repo":{"allOf":[{"$ref":"#/components/schemas/RepoSignal"}],"description":"Repository signal; `null` for bundles served by a domain.","nullable":true},"indexed_at":{"type":"string","description":"When the bundle entered the index, `YYYY-MM-DD HH:MM:SS` UTC."},"updated_at":{"type":"string","description":"When its indexed content last changed, `YYYY-MM-DD HH:MM:SS` UTC."},"api":{"type":"string","description":"Absolute URL of this bundle's card."}},"required":["id","name","tagline","description","okf_version","concepts","concept_list","type","index_url","page_url","source","repo","indexed_at","updated_at","api"],"description":"One OKF bundle: a markdown tree whose root `index.md` carries `okf_version`."},"Concept":{"type":"object","properties":{"name":{"type":"string","description":"Link text as written in the root index."},"url":{"type":"string","description":"Absolute URL of the entry, resolved against the root; a directory link gets its `index.md`."},"summary":{"type":"string","description":"Text after the link on the same line; empty when the index has none."}},"required":["name","url","summary"],"description":"One entry the root `index.md` lists: a concept file or a subdirectory of the bundle."},"BundleSource":{"type":"object","properties":{"origin":{"type":"string","description":"Provenance of the bundle."},"via":{"type":"string","description":"How it got in: the GitHub sweep or an IndexNow ping."},"url":{"type":"string","description":"The repository (GitHub) or the site root (domain)."},"host":{"type":"string","description":"Hostname of `url`; empty when it cannot be parsed."},"repo":{"type":"string","description":"`owner/repo` in lowercase, GitHub bundles only.","nullable":true},"dir":{"type":"string","description":"Directory of the bundle inside the repository (empty at the root)."},"path":{"type":"string","description":"Path of the root `index.md` inside the repository."}},"required":["origin","via","url","host","repo","dir","path"],"description":"Where a bundle comes from and how it entered the index."},"RepoSignal":{"type":"object","properties":{"stars":{"type":"integer","description":"Stargazers at the last collection."},"forks":{"type":"integer","description":"Forks at the last collection."},"pushed_at":{"type":"string","description":"Last push seen, `YYYY-MM-DD HH:MM:SS` UTC.","nullable":true},"state":{"type":"string","description":"Repository state as classified by the enricher (active, stalled, archived, gone).","nullable":true},"language":{"type":"string","description":"Primary language reported by GitHub.","nullable":true},"license":{"type":"string","description":"License identifier reported by GitHub.","nullable":true}},"required":["stars","forks","pushed_at","state","language","license"],"description":"Repository signal collected by the enricher — GitHub bundles only."},"IndexStats":{"type":"object","properties":{"total":{"type":"integer","description":"Live bundles in the index."},"by_origin":{"type":"object","description":"`{github, domain}`: live bundles found by the sweep and submitted by domains."},"by_version":{"type":"array","items":{"$ref":"#/components/schemas/Faceta"},"description":"Live bundles per declared `okf_version`, most common first (up to 12)."},"by_type":{"type":"array","items":{"$ref":"#/components/schemas/Faceta"},"description":"Declared root types, up to 12; roots need not declare a type."},"by_concepts":{"type":"array","items":{"$ref":"#/components/schemas/Faceta"},"description":"Root entry counts in bands 0, 1-5, 6-20, 21-100, 101+."},"by_license":{"type":"array","items":{"$ref":"#/components/schemas/Faceta"},"description":"Repository licenses, up to 12; absent license is unknown."},"by_language":{"type":"array","items":{"$ref":"#/components/schemas/Faceta"},"description":"Live bundles per repository language, most common first (up to 12); domain bundles have none."},"last_update":{"type":"string","description":"Newest `updated_at` among live bundles, `YYYY-MM-DD HH:MM:SS` UTC.","nullable":true}},"required":["total","by_origin","by_version","by_type","by_concepts","by_license","by_language","last_update"],"description":"Size of the index by provenance, the facets a search can filter by, and when it last changed."},"Faceta":{"type":"object","properties":{"v":{"type":"string","description":"The stored facet value or the concept-count band."},"n":{"type":"integer","description":"Live bundles with that value."}},"required":["v","n"],"description":"One value of a facet and how many live bundles carry it."},"PaymentQuota":{"type":"object","properties":{"free":{"type":"array","items":{"$ref":"#/components/schemas/PaymentFree"},"description":"Free allowances and their windows."},"paid":{"type":"array","items":{"$ref":"#/components/schemas/PaymentPrice"},"description":"List prices in USD. The operation's 402 is the payable quote."},"how_to_pay":{"type":"string","description":"Payment instructions and availability restrictions."},"live":{"type":"string","description":"Authoritative product quota endpoint.","nullable":true},"free_now":{"type":"array","items":{"type":"string"},"description":"SKUs temporarily free despite their list price."},"trial":{"allOf":[{"$ref":"#/components/schemas/PaymentTrial"}],"description":"Registration trial, when offered."}},"required":["free","paid","how_to_pay","live"]},"PaymentFree":{"type":"object","properties":{"o_que":{"type":"string","description":"Operation or allowance."},"limite":{"type":"string","description":"Allowance and eligibility."},"janela":{"type":"string","description":"Reset window, when applicable.","nullable":true}},"required":["o_que","limite","janela"]},"PaymentPrice":{"type":"object","properties":{"o_que":{"type":"string","description":"Operation and billing unit."},"price_usd":{"type":"number","description":"Current list price in USD."}},"required":["o_que","price_usd"]},"PaymentTrial":{"type":"object","properties":{"days":{"type":"integer","description":"Trial duration in days."},"how":{"type":"string","description":"Eligibility and activation steps."}},"required":["days","how"]},"PaymentX402":{"type":"object","properties":{"provider":{"type":"string","description":"Always `x402` — the only billing protocol accepted."},"mode":{"type":"string","description":"Seller mode: `live` charges for real, `dev` lets calls through unpaid."},"network":{"type":"string","description":"USDC network: `base` in production, `base-sepolia` in staging."},"chain_id":{"type":"integer","description":"EVM chain ID of the network above, so the wallet signs on the right chain."},"pay_to":{"type":"string","description":"Address that receives the payment.","nullable":true},"homolog":{"type":"boolean","description":"Staging seam on: the loop can be closed without spending USDC."},"dev":{"type":"boolean","description":"Development mode: the 402 is simulated."},"dev_gate":{"type":"boolean","description":"A homologation credential is configured; this grants no access."},"gratis":{"type":"array","items":{"type":"string"},"description":"Temporarily free SKUs."},"facilitator":{"type":"string","description":"URL of the facilitator that verifies and settles the payment."},"asset":{"type":"string","description":"Accepted currency — always `USDC`."},"asset_address":{"type":"string","description":"USDC contract on the network above."},"faucet":{"type":"string","description":"Test-USDC faucet; only on base-sepolia.","nullable":true},"wallets":{"type":"object","description":"Links to wallets that speak x402 (metamask, coinbase, base_app)."}},"required":["provider","mode","network","chain_id","pay_to","homolog","dev","dev_gate","facilitator","asset","asset_address","faucet","wallets"],"description":"x402 payment configuration in force. Comes from `planPublic` and is the same across the products."},"PaymentCredit":{"type":"object","properties":{"url":{"type":"string","description":"POST to purchase credit; GET with X-Credito to inspect its balance."},"header":{"type":"string","description":"Header for a previously issued credit token: X-Credito."}},"required":["url","header"]}},"securitySchemes":{"globalAccount":{"type":"apiKey","in":"cookie","name":"__Host-mm-auth","description":"Global session in the product's HttpOnly cookie; writes require exact Origin and X-CSRF-Token."},"contaChaveApi":{"type":"http","scheme":"bearer","bearerFormat":"mmk_…","description":"Account API key: `Authorization: Bearer mmk_…` or `X-Api-Key: mmk_…`. Created on the account page (API keys), valid only in the product where it was created; it acts as the account (or the organization that owns it)."}}},"paths":{"/api/auth/bootstrap":{"get":{"operationId":"get_api_auth_bootstrap","summary":"Prepare the browser for global sign-in.","description":"Sets a host-only HttpOnly browser cookie. CSRF is bound to the current session. No CORS.\nReturns: { csrf, context }","responses":{"200":{"description":"{ csrf, context }","content":{"application/json":{"schema":{"type":"object","properties":{"csrf":{"type":"string","description":"X-CSRF-Token"},"context":{"type":"string","description":"Opaque view context, also in X-MM-Context; not a credential / contexto opaco da vista, não é credencial."}},"required":["csrf","context"]}}}},"400":{"description":"invalid_request"},"403":{"description":"invalid_origin / invalid_csrf"},"503":{"description":"auth_unavailable: a sessão anterior é preservada / the previous session is preserved"}},"security":[]}},"/api/account/profile":{"get":{"operationId":"get_api_account_profile","summary":"Read your global profile.","description":"Reads current preferences from the account. Edit them on your account page; products never own a separate profile.\nReturns: {profile:{name,locale,timeZone,theme,revision}}","responses":{"200":{"description":"{profile:{name,locale,timeZone,theme,revision}}"},"401":{"description":"invalid_session"},"503":{"description":"auth_unavailable"}},"security":[{"globalAccount":[]}]}},"/api/account/avatar":{"get":{"operationId":"get_api_account_avatar","summary":"Read your global profile photo.","description":"Private WebP, up to 64 KiB, no cache. Change it on your account. No user ID or object URL accepted.\nReturns: image/webp; Cache-Control: no-store","responses":{"200":{"description":"image/webp; Cache-Control: no-store","content":{"image/webp":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"invalid_session"},"404":{"description":"not_found: no photo / sem foto"},"503":{"description":"auth_unavailable"}},"security":[{"globalAccount":[]}]}},"/api/me":{"get":{"operationId":"get_api_me","summary":"Read the current global account in this product.","description":"Returns: {user:{identityId,sessionId,productId,audience,authTime,methods,mfaState}}","responses":{"200":{"description":"{user:{identityId,sessionId,productId,audience,authTime,methods,mfaState}}"},"401":{"description":"invalid_session"},"503":{"description":"auth_unavailable"}},"security":[{"globalAccount":[]}]}},"/api/auth/logout":{"post":{"operationId":"post_api_auth_logout","summary":"Revoke this product session.","description":"Bootstrap/CSRF must belong to this browser and session. Other product sessions remain active.\nReturns: { ok }","responses":{"200":{"description":"{ ok }","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","description":"true"}},"required":["ok"]}}}},"400":{"description":"invalid_request"},"403":{"description":"invalid_origin / invalid_csrf"},"503":{"description":"auth_unavailable: a sessão anterior é preservada / the previous session is preserved"}},"security":[{"globalAccount":[]}]}},"/api/account/keys":{"get":{"operationId":"get_api_account_keys","summary":"List your API keys in this product.","description":"Never returns the key itself: name, last 4 characters, organization, creation, last use (hourly) and whether it still works.\nReturns: { keys }","responses":{"200":{"description":"{ keys }","content":{"application/json":{"schema":{"type":"object","properties":{"keys":{"type":"array","items":{"type":"object"},"description":"`id`, `name`, `organizationId`, `last4`, `createdAt`, `lastUsedAt`, `revokedAt`, `active` (false when revoked or stopped by a password change / ending all sessions)."}},"required":["keys"]}}}},"401":{"description":"invalid_session"},"503":{"description":"auth_unavailable"}},"security":[{"globalAccount":[]}]}},"/api/account/keys/create":{"post":{"operationId":"post_api_account_keys_create","summary":"Create an API key for agents and scripts.","description":"Needs a sign-in in the last 5 minutes; an organization key also needs a second factor in the session and the owner/admin role with this product enabled. At most 10 live keys per account and product. The key (`secret`) is returned ONCE.\nReturns: { key, secret }","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Up to 60 characters."},"organizationId":{"type":"string","description":"`null` for an account key."}},"required":["name","organizationId"]},"example":{"name":"agent","organizationId":null}}}},"responses":{"200":{"description":"{ key, secret }","content":{"application/json":{"schema":{"type":"object","properties":{"key":{"type":"object","description":"`id`, `name`, `organizationId`, `last4`, `createdAt`."},"secret":{"type":"string","description":"`mmk_…`, shown once."}},"required":["key","secret"]}}}},"400":{"description":"invalid_key_name / invalid_organization"},"401":{"description":"invalid_session / reauth_required"},"403":{"description":"invalid_origin / invalid_csrf / organization_forbidden / organization_mfa_required"},"409":{"description":"key_limit_reached"},"503":{"description":"auth_unavailable"}},"security":[{"globalAccount":[]}]}},"/api/account/keys/revoke":{"post":{"operationId":"post_api_account_keys_revoke","summary":"Revoke one of your API keys.","description":"Stops the key at once. Repeating is harmless.\nReturns: { ok }","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The key `id`."}},"required":["id"]},"example":{"id":"…"}}}},"responses":{"200":{"description":"{ ok }","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","description":"true"}},"required":["ok"]}}}},"400":{"description":"invalid_key_id"},"401":{"description":"invalid_session"},"403":{"description":"invalid_origin / invalid_csrf"},"404":{"description":"key_not_found"},"503":{"description":"auth_unavailable"}},"security":[{"globalAccount":[]}]}},"/agent.json":{"get":{"operationId":"get_agent_json","summary":"Agent card: identity, operator, documentation, the MCP endpoint and the tools it serves. Same document as `/.well-known/agent-card.json`.","description":"Returns: `application/json`: `name`, `provider`, `protocol` (`mcp`), `interfaces[]` and `skills[]`.","responses":{"200":{"description":"`application/json`: `name`, `provider`, `protocol` (`mcp`), `interfaces[]` and `skills[]`."}}}},"/okf/{arquivo}":{"get":{"operationId":"get_okf_by_arquivo","summary":"OKF bundle (Open Knowledge Format v0.1): markdown with frontmatter so an agent reads the whole product without parsing HTML.","description":"Returns: `text/markdown`. Start at `/okf/index.md`, which lists the bundle.","parameters":[{"name":"arquivo","in":"path","required":true,"schema":{"type":"string"},"description":"`index.md`, `sobre.md`, `api.md` or `faq.md`.","example":"index.md"}],"responses":{"200":{"description":"`text/markdown`. Start at `/okf/index.md`, which lists the bundle."},"404":{"description":"File outside the bundle."}}}},"/.well-known/{arquivo}":{"get":{"operationId":"get_well_known_by_arquivo","summary":"Machine discovery before the home page: `api-catalog` (RFC 9727, a linkset with the API and the MCP), `security.txt` (RFC 9116), `x402` (payment manifest: network, wallet and the routes that charge) and `mcp-registry-auth` (the official MCP registry key).","description":"Returns: `application/linkset+json` for the api-catalog; `application/json` for x402 and apis.json; `text/plain` for the other two.","parameters":[{"name":"arquivo","in":"path","required":true,"schema":{"type":"string"},"description":"`api-catalog`, `security.txt`, `x402`, `mcp-registry-auth` or `apis.json`.","example":"api-catalog"}],"responses":{"200":{"description":"`application/linkset+json` for the api-catalog; `application/json` for x402 and apis.json; `text/plain` for the other two."},"404":{"description":"Name outside the five published."}}}},"/apis.json":{"get":{"operationId":"get_apis_json","summary":"APIs.json (apisjson.org, 0.19): the index APIs.io harvests — the API, the MCP, OpenAPI, guide and OKF bundle in one file. Also at `/.well-known/apis.json`.","description":"Returns: `application/json` in the APIs.json 0.19 format: `apis[]` with `baseURL`, `humanURL` and `properties[]`.","responses":{"200":{"description":"`application/json` in the APIs.json 0.19 format: `apis[]` with `baseURL`, `humanURL` and `properties[]`."}}}},"/api/":{"get":{"operationId":"api_index","summary":"Índice auto-descrito: cada rota, o que cobra e como plugar o MCP.","description":"Returns: { name, description, build, base_url, docs, endpoints, mcp_tools }","responses":{"200":{"description":"{ name, description, build, base_url, docs, endpoints, mcp_tools }","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Nome do produto."},"description":{"type":"string","description":"O que o produto faz."},"build":{"type":"string","description":"Commit publicado."},"base_url":{"type":"string","description":"Origem em que esta API está servindo."},"docs":{"type":"object","description":"Links para llms.txt, OpenAPI, MCP e a UI."},"endpoints":{"type":"array","items":{"type":"object"},"description":"Catálogo de endpoints."},"mcp_tools":{"type":"array","items":{"type":"string"},"description":"Tools do MCP."}},"required":["name","description","build","base_url","docs","endpoints","mcp_tools"]}}}}}}},"/api/health":{"get":{"operationId":"get_api_health","summary":"Liveness and the build being served.","description":"Returns: { ok, app, build }","responses":{"200":{"description":"{ ok, app, build }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Saude"}}}}}}},"/mcp":{"post":{"operationId":"post_mcp","summary":"MCP Streamable HTTP — as tools deste catálogo, despachadas neste mesmo Worker.","description":"Returns: JSON-RPC 2.0 (`initialize`, `tools/list`, `tools/call`).","responses":{"200":{"description":"JSON-RPC 2.0 (`initialize`, `tools/list`, `tools/call`)."}}}},"/api/bundles":{"get":{"operationId":"search_bundles","summary":"Paginated search of the index: every live OKF bundle, from GitHub and from live domains.","description":"Only `live` bundles. Free text matches the name, the tagline, the description and the origin identifier (`owner/repo:path` or the bundle URL). No `total` on purpose: `GET /api/okf/stats` has it.\nReturns: { items[{id,name,tagline,description,okf_version,concepts,concept_list,type,index_url,page_url,source,repo,indexed_at,updated_at,api}], limit, offset, next_offset, next }","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string"},"description":"Free text over name, tagline, description and origin identifier.","example":"agent"},{"name":"origin","in":"query","required":false,"schema":{"type":"string","enum":["github","domain"]},"description":"Provenance: found by the GitHub sweep, or submitted by a domain."},{"name":"repo","in":"query","required":false,"schema":{"type":"string"},"description":"Only bundles of one repository, `owner/repo` (case-insensitive).","example":"fastendpoints/fastendpoints"},{"name":"version","in":"query","required":false,"schema":{"type":"string"},"description":"Only bundles declaring one of these `okf_version` values; comma-separated, up to 5.","example":"0.1,0.2"},{"name":"concept","in":"query","required":false,"schema":{"type":"string"},"description":"Text in the indexed root content, including listed concept names and summaries (first 1000 characters); up to 80 characters."},{"name":"concepts","in":"query","required":false,"schema":{"type":"string"},"description":"Number of entries listed by the root. Up to 5 comma-separated bands: 0,1-5,6-20,21-100,101+."},{"name":"type","in":"query","required":false,"schema":{"type":"string"},"description":"Type declared by the root, not the types of every concept. Up to 5 comma-separated values, 40 characters each."},{"name":"license","in":"query","required":false,"schema":{"type":"string"},"description":"Repository license. Up to 5 comma-separated values, 40 characters each."},{"name":"language","in":"query","required":false,"schema":{"type":"string"},"description":"Only bundles whose repository language is one of these; comma-separated, up to 5 (GitHub bundles).","example":"TypeScript,Go"},{"name":"sort","in":"query","required":false,"schema":{"type":"string","default":"recent","enum":["recent","updated","name","stars"]},"description":"Result order: arrival, last content change, name or repository stars."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":24},"description":"Bundles per page, at most 100."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0},"description":"How many bundles to skip. Use `next_offset` from the previous response; the list ends at 1000."}],"responses":{"200":{"description":"{ items[{id,name,tagline,description,okf_version,concepts,concept_list,type,index_url,page_url,source,repo,indexed_at,updated_at,api}], limit, offset, next_offset, next }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginaDeBundles"}}}}}}},"/api/bundles/{id}":{"get":{"operationId":"get_bundle","summary":"One bundle's card, by id.","description":"`live` and `low` (example or fixture bundles kept out of the search) both answer here.\nReturns: { id, name, tagline, description, okf_version, concepts, concept_list[{name,url,summary}], type, index_url, page_url, source{origin,via,url,host,repo,dir,path}, repo{stars,forks,pushed_at,state,language,license}, indexed_at, updated_at, api }","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Bundle id, the `id` of every item in the list.","example":"okf-fastendpoints"}],"responses":{"200":{"description":"{ id, name, tagline, description, okf_version, concepts, concept_list[{name,url,summary}], type, index_url, page_url, source{origin,via,url,host,repo,dir,path}, repo{stars,forks,pushed_at,state,language,license}, indexed_at, updated_at, api }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Bundle"}}}},"404":{"description":"No bundle with that id, or it is not public."}}}},"/api/okf/stats":{"get":{"operationId":"index_stats","summary":"Size of the index by provenance, and when it last changed.","description":"Returns: { total, by_origin, by_version[{v,n}], by_type[{v,n}], by_concepts[{v,n}], by_license[{v,n}], by_language[{v,n}], last_update }","responses":{"200":{"description":"{ total, by_origin, by_version[{v,n}], by_type[{v,n}], by_concepts[{v,n}], by_license[{v,n}], by_language[{v,n}], last_update }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IndexStats"}}}}}}},"/api/stats":{"get":{"operationId":"get_api_stats","summary":"Counts and facets for the OKF Index home.","description":"Returns: { total, by_origin, by_version[{v,n}], by_type[{v,n}], by_concepts[{v,n}], by_license[{v,n}], by_language[{v,n}], last_update }","responses":{"200":{"description":"{ total, by_origin, by_version[{v,n}], by_type[{v,n}], by_concepts[{v,n}], by_license[{v,n}], by_language[{v,n}], last_update }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IndexStats"}}}}}}},"/api/ping":{"post":{"operationId":"submit_bundles","summary":"Submits OKF bundles from a domain you control, using the IndexNow protocol.","description":"No account, no payment: ownership is proved by a key file on the host, exactly as IndexNow does it. Host `https://<host>/<key>.txt` containing the key (or point `keyLocation` at another path on the SAME host), then send the bundle URLs. We answer **202**: the key has not been checked yet. Verification and reading happen on our collector, never at the edge — so nothing is published, and no URL of yours is fetched, before the key matches. Re-sending a URL is how you say the bundle changed; it goes back in line to be re-read. At most 100 URLs per request and 200 per host per UTC day. Bundles in public GitHub repositories need no ping: the sweep finds them.\nReturns: { ok, estado, host, recebidos, chave_em, mensagem, api_index }","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"urlList":{"type":"array","items":{"type":"string"},"description":"The bundle roots (`index.md` files): https, on `host`, ending in .md — any path, since the spec fixes none."},"host":{"type":"string","description":"The domain that serves the bundles and the key file."},"key":{"type":"string","description":"The IndexNow key: 8 to 128 characters of [a-zA-Z0-9-]."},"keyLocation":{"type":"string","description":"Alternative location of the key file, on the SAME host. Default: `https://<host>/<key>.txt`."}},"required":["urlList","host","key"]},"example":{"urlList":["https://kb.example.org/knowledge/index.md"],"host":"kb.example.org","key":"okf-2026-09-08-k3y"}}}},"responses":{"202":{"description":"{ ok, estado, host, recebidos, chave_em, mensagem, api_index }","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","description":"The submission was queued."},"estado":{"type":"string","description":"Always `pendente`: the key has not been checked yet."},"host":{"type":"string","description":"The host as normalized (lowercase)."},"recebidos":{"type":"integer","description":"How many distinct URLs entered the queue."},"chave_em":{"type":"string","description":"Where we will look for the key file. Check it if you are unsure."},"mensagem":{"type":"string","description":"What happens next, in one sentence."},"api_index":{"type":"string","description":"Absolute URL of this API's index."}},"required":["ok","estado","host","recebidos","chave_em","mensagem","api_index"]}}}},"400":{"description":"Body is not JSON, `host` is not a domain, `key` is out of shape, or `urlList` is missing/empty/over 100."},"422":{"description":"Some URL is not https, does not end in .md or lives on another host; `keyLocation` off-host too."},"429":{"description":"The host already submitted 200 bundles this UTC day."}}}},"/api/visit":{"post":{"operationId":"post_api_visit","summary":"One ping per page view from the interface; it feeds the index's own visit counter.","description":"Counted under the index's metric (`okf_visit`), apart from the Meta Agent Tools counter that shares the database. Test traffic is left out: `X-MM-Smoke`, User-Agent `mm-smoke` or `smoke: true`.\nReturns: { counted, ok }","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"smoke":{"type":"boolean","description":"`true` flags a test call, which is acknowledged but not counted."},"p":{"type":"string","description":"Path of the page that was opened (informative)."}}},"example":{"p":"/","smoke":false}}}},"responses":{"200":{"description":"{ counted, ok }","content":{"application/json":{"schema":{"type":"object","properties":{"counted":{"type":"boolean","description":"`false` for test traffic, `true` when the day's counter moved."},"ok":{"type":"boolean","description":"Always `true`; the route never refuses a ping."}},"required":["counted","ok"]}}}}}}},"/api/vitrine":{"get":{"operationId":"get_api_vitrine","summary":"The product's public numbers: traffic, agents, usage and reliability, no money.","description":"Projection published hourly by the house collector, rounded to two significant digits; `null` is a missing measurement, never zero. 15-minute cache with ETag (`If-None-Match` → 304). There is no way to send numbers through this route: publishing belongs to the collector, with its own token.\nReturns: { v, produto, publicado, atualizado_em, stale, nome?, desde?, fuso?, hoje?, dias?, janelas?, visitantes?, pessoas?, agentes?, superficies?, mcp?, uso?, contas?, confiabilidade?, catalogo?, apoio? }","responses":{"200":{"description":"{ v, produto, publicado, atualizado_em, stale, nome?, desde?, fuso?, hoje?, dias?, janelas?, visitantes?, pessoas?, agentes?, superficies?, mcp?, uso?, contas?, confiabilidade?, catalogo?, apoio? }","content":{"application/json":{"schema":{"type":"object","properties":{"v":{"type":"integer","description":"Contract version (1)."},"produto":{"type":"string","description":"Product id."},"publicado":{"type":"boolean","description":"`false` before the collector's first publication; then only these five keys come."},"atualizado_em":{"type":"string","description":"When the collector published (ISO 8601).","nullable":true},"stale":{"type":"boolean","description":"`true` when the projection is older than 26 h."},"nome":{"type":"string","description":"Product name."},"desde":{"type":"string","description":"First day the series covers.","nullable":true},"fuso":{"type":"string","description":"Time zone of the days (`UTC`)."},"hoje":{"type":"object","description":"Today: pages by class (human, AI, bot), API calls by class, machine-surface reads and product usage."},"dias":{"type":"array","items":{"type":"object"},"description":"Up to 31 days, oldest first: `dia`, `paginas`, `api`, `api_ia`, `maquina`, `visitantes`, `uso`."},"janelas":{"type":"object","description":"7- and 30-day sums (`d7`, `d30`)."},"visitantes":{"type":"object","description":"Unique visitors at the edge over 7 days."},"pessoas":{"type":"object","description":"GA4 when available: users, sessions, countries, devices and who arrived from AI.","nullable":true},"agentes":{"type":"object","description":"The AI agents and bots that read the most, 7 days."},"superficies":{"type":"object","description":"Reads of OKF, llms, well-known, OpenAPI and MCP over 7 days."},"mcp":{"type":"object","description":"MCP calls over 7 days."},"uso":{"type":"object","description":"Real product usage per resource: label, today, 7 and 30 days."},"contas":{"type":"object","description":"Users and guests.","nullable":true},"confiabilidade":{"type":"object","description":"Share of requests without 5xx over 7 days, and the live build."},"catalogo":{"type":"object","description":"Size of the catalog, when the product has one.","nullable":true},"apoio":{"type":"object","description":"Impressions and clicks per sponsor, when any."}},"required":["v","produto","publicado","atualizado_em","stale"]}}}}}}},"/api/vitrine/operador":{"get":{"operationId":"get_api_vitrine_operador","summary":"The product's full document on the operator panel — operator token only.","description":"Returns: { produto, atualizado_em, operador }","parameters":[{"name":"Authorization","in":"header","required":true,"schema":{"type":"string"},"description":"`Bearer <METRICS_TOKEN>` — the operator class."}],"responses":{"200":{"description":"{ produto, atualizado_em, operador }","content":{"application/json":{"schema":{"type":"object","properties":{"produto":{"type":"string","description":"Product id."},"atualizado_em":{"type":"string","description":"When the collector published.","nullable":true},"operador":{"type":"object","description":"The collector's full document, with what the public projection leaves out.","nullable":true}},"required":["produto","atualizado_em","operador"]}}}},"401":{"description":"No token, wrong token or a token of another class."},"503":{"description":"Worker without `METRICS_TOKEN` or without the control plane."}}}},"/api/vitrine/painel":{"get":{"operationId":"get_api_vitrine_painel","summary":"The whole house panel, in the shape the gm reads — operator token only.","description":"Returns: { apps, updated?, totals? }","parameters":[{"name":"Authorization","in":"header","required":true,"schema":{"type":"string"},"description":"`Bearer <METRICS_TOKEN>` — the operator class."}],"responses":{"200":{"description":"{ apps, updated?, totals? }","content":{"application/json":{"schema":{"type":"object","properties":{"apps":{"type":"array","items":{"type":"object"},"description":"One operator document per product, ordered by id."},"updated":{"type":"string","description":"When the collector closed the round."},"totals":{"type":"object","description":"House totals."}},"required":["apps"]}}}},"401":{"description":"No token, wrong token or a token of another class."},"503":{"description":"Worker without `METRICS_TOKEN` or without the control plane."}}}},"/api/vitrine/cursores":{"get":{"operationId":"get_api_vitrine_cursores","summary":"The resolved-error cursor per product (`borda`, `cli`) — operator token only.","description":"Returns: JSON: `{ [product]: { borda?: ISO, cli?: ISO } }`; empty is `{}`.","parameters":[{"name":"Authorization","in":"header","required":true,"schema":{"type":"string"},"description":"`Bearer <METRICS_TOKEN>` — the operator class."}],"responses":{"200":{"description":"JSON: `{ [product]: { borda?: ISO, cli?: ISO } }`; empty is `{}`."},"401":{"description":"No token, wrong token or a token of another class."},"503":{"description":"Worker without `METRICS_TOKEN` or without the control plane."}}}},"/api/partners":{"get":{"operationId":"get_api_partners","summary":"Partnership, sponsorship and advertising: the product's placements with a suggested price, the public numbers next to them and how to propose.","description":"Information on request, no activation: placements from the house catalogue priced in USD per 30 days (90 and 365 days discounted), sponsors in effect, an excerpt of `/api/vitrine`, the house wallet (USDC on Base) and the contact path — bank deposit, PIX or invoice are arranged in the reply. Cached for 1 hour.\nReturns: { status, produto, idioma, titulo, descricao, publico, modalidades, placements, house_bundle, parcerias, current_sponsors, stats, payment, contact, politica, _links }","responses":{"200":{"description":"{ status, produto, idioma, titulo, descricao, publico, modalidades, placements, house_bundle, parcerias, current_sponsors, stats, payment, contact, politica, _links }","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","description":"`sob_consulta`: information and proposal, no activation and no charge."},"produto":{"type":"string","description":"Product name."},"idioma":{"type":"string","description":"Language of the texts (the product's)."},"titulo":{"type":"string","description":"Title of the offer."},"descricao":{"type":"string","description":"One sentence about the offer."},"publico":{"type":"string","description":"Who uses the product — the audience a sponsor reaches."},"modalidades":{"type":"array","items":{"type":"object"},"description":"`{ id, nome }`: patrocinio, parceria, anuncio."},"placements":{"type":"array","items":{"type":"object"},"description":"The product's placements: `id`, `nome`, `onde`, `formato`, `exclusivo`, `medicao`, `price_usd_30d` (suggested; `null` is on request), `exposure[{ dias, price_usd }]` for 30, 90 and 365 days, `disponivel`."},"house_bundle":{"type":"object","description":"The house bundle: footer and agent mention across the ten products, discounted."},"parcerias":{"type":"array","items":{"type":"string"},"description":"Partnership ideas the product is open to discuss."},"current_sponsors":{"type":"array","items":{"type":"object"},"description":"Sponsors in effect: `id`, `nome`, `url`, `frase`, `espacos`, `ate`."},"stats":{"type":"object","description":"Excerpt of the public numbers (`hoje`, `janelas`, `agentes`, `confiabilidade`) and the `link` to `/api/vitrine`; `publicado: false` before the first publication."},"payment":{"type":"object","description":"How to pay: `rede`, `chain_id`, `ativo`, `pay_to`, `eip681` (the house wallet, when declared), `alternativas` and the `nota` — bank deposit, PIX or invoice in the reply."},"contact":{"type":"object","description":"`email`, `form_url`, `api_url` (`POST /api/contact` where the handler exists), `campos` (required), `campos_proposta` (the optional proposal fields, each with its accepted values), `price_agent_usd`, `message_template`, `instructions`."},"politica":{"type":"object","description":"Placement label, refused sectors, prepayment, deadlines."},"_links":{"type":"object","description":"`self`, `stats`, `page` (`null` until the page exists), `contact`, `casa` (the same path on the ten products)."}},"required":["status","produto","idioma","titulo","descricao","publico","modalidades","placements","house_bundle","parcerias","current_sponsors","stats","payment","contact","politica","_links"]}}}}}}},"/api/contact":{"post":{"operationId":"post_api_contact","summary":"Talks to the people behind the index: a human solves Turnstile, an agent pays $0.10 in x402 or prepaid credit.","description":"Without a captcha in the body the request is treated as an agent: 402 until paid — x402 (`X-PAYMENT`) or prepaid credit (`Authorization: Bearer cred_…`, bought at `POST /api/credito`, the same token in every product of the house). The first agent message is free; after that the backoff is 60s doubling up to a 1-hour cap, announced in `Retry-After`. A partnership proposal goes through this same route with `tipo`.\nReturns: { ok, path }","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"What to call the person writing."},"email":{"type":"string","description":"Where to reply."},"message":{"type":"string","description":"What you want to say."},"form_ts":{"type":"integer","description":"When the form was opened; the anti-robot of the human path, and only it requires this."},"cf_turnstile_response":{"type":"string","description":"Turnstile response; present only on the human path."},"tipo":{"type":"string","description":"Proposal: `patrocinio`, `parceria` or `anuncio`. Turns on the fields below."},"empresa":{"type":"string","description":"Who is proposing, when it is a company."},"site":{"type":"string","description":"Website of who is proposing."},"orcamento":{"type":"string","description":"`ate_100`, `100_500`, `500_2000`, `2000_mais` or `a_combinar`."},"espaco":{"type":"array","items":{"type":"string"},"description":"Placement ids from `GET /api/partners`, up to 6."},"duracao":{"type":"string","description":"Exposure in days: `30`, `90` or `365`."},"pagamento":{"type":"string","description":"`usdc`, `deposito` or `a_combinar`."}},"required":["name","email","message"]},"example":{"name":"Agent","email":"agent@example.com","message":"hello from an agent"}}}},"responses":{"200":{"description":"{ ok, path }","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","description":"Always `true` when the message was accepted."},"path":{"type":"string","description":"Which path it came through: human with captcha or paid agent."}},"required":["ok","path"]}}}},"400":{"description":"Required field missing."},"402":{"description":"Quota exceeded. The response carries `accepts[]` (x402, USDC on Base): pay and repeat the same call with `X-PAYMENT`."},"429":{"description":"Agent backoff: wait for `Retry-After`."},"503":{"description":"Mail or captcha not configured on the Worker; nothing was charged."}}}},"/api/credito":{"post":{"operationId":"post_api_credito","summary":"Top up prepaid credit: pay once with x402 and get the token that debits on any API of the house.","description":"Returns: { token, saldo_usd, guarde, usar, saldo_em }","parameters":[{"name":"usd","in":"query","required":true,"schema":{"type":"integer"},"description":"Package: 1, 5, 10 ou 25 dollars."}],"responses":{"200":{"description":"{ token, saldo_usd, guarde, usar, saldo_em }","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"Bearer token for the balance (`cred_…`). Shown ONCE — it cannot be recovered."},"saldo_usd":{"type":"string","description":"Credited balance."},"guarde":{"type":"string","description":"Warning that the token is the bearer of the credit."},"usar":{"type":"string","description":"How to present the token on paid routes."},"saldo_em":{"type":"string","description":"Where to check balance and statement."}},"required":["token","saldo_usd","guarde","usar","saldo_em"]}}}},"400":{"description":"Package outside the list (1, 5, 10 ou 25)."},"402":{"description":"Unpaid — the body carries the x402 `accepts[]`."}}},"get":{"operationId":"get_api_credito","summary":"Credit balance and statement — the latest movements, without returning the token.","description":"Returns: { saldo_micros, saldo_usd, criado_em, movimentos }","responses":{"200":{"description":"{ saldo_micros, saldo_usd, criado_em, movimentos }","content":{"application/json":{"schema":{"type":"object","properties":{"saldo_micros":{"type":"integer","description":"Balance in micro-dollars (1e-6 USD)."},"saldo_usd":{"type":"string","description":"Formatted balance."},"criado_em":{"type":"string","description":"When the credit was opened."},"movimentos":{"type":"array","items":{"type":"object"},"description":"Recent credits and debits, with product and resource."}},"required":["saldo_micros","saldo_usd","criado_em","movimentos"]}}}},"401":{"description":"No token, or unknown token."}}}},"/api/metrics":{"get":{"operationId":"get_api_metrics","summary":"Usage of the index for the house dashboard: bundles indexed, visits and MCP calls per day.","description":"Anonymous calls get the usage block only. Send `METRICS_TOKEN` as Bearer and the finance block is added — all zeros, because nothing here is charged.\nReturns: `{app, today, today_visits, days[], usage: {okf, mcp}, accounts, payments?}`.","parameters":[{"name":"Authorization","in":"header","required":false,"schema":{"type":"string"},"description":"Optional `Bearer <METRICS_TOKEN>`; unlocks the zeroed finance block."}],"responses":{"200":{"description":"`{app, today, today_visits, days[], usage: {okf, mcp}, accounts, payments?}`."},"401":{"description":"Token present but wrong."},"503":{"description":"Token present, but the Worker has no `METRICS_TOKEN` to compare."}}}},"/api/erro-cliente":{"post":{"operationId":"post_api_erro_cliente","summary":"Browser error report, sent by the interface itself. Agents need not call it.","description":"The interface reports on its own JS errors, unhandled rejections, scripts/CSS that failed to load and CSP blocks — once per session — and the app reports handled failures through `window.mmErro.relata`. The server validates the envelope, redacts credentials, e-mails and phone numbers, merges repeats of the same failure per minute and records an operational event; nothing is written to a database. It keeps no IP, cookie, query string or full User-Agent. Always answers 204, even for an invalid report.\nReturns: 204 with no body, always — an invalid, repeated or over-cap report also gets 204.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","description":"Failure code, `UI-` + letters/digits (`UI-JS-001` global error, `UI-PROMESSA-001`, `UI-RECURSO-001`, `UI-CSP-001`, `UI-APP-001` app report)."},"phase":{"type":"string","description":"Where it broke, lowercase: `global`, `promessa`, `script`, `load_list`…"},"path":{"type":"string","description":"Path of the open page, without query."},"message":{"type":"string","description":"Error message, up to 2000 characters."},"stack":{"type":"string","description":"Stack trace, up to 12000 characters."},"source":{"type":"string","description":"Originating script; only its path is kept."},"line":{"type":"integer","description":"Line in the originating script."},"column":{"type":"integer","description":"Column in the originating script."},"visivel":{"type":"boolean","description":"Whether the tab was visible when it broke."}},"required":["code","phase"]},"example":{"code":"UI-APP-001","phase":"carregar_lista","path":"/","message":"lista 500"}}}},"responses":{"200":{"description":"204 with no body, always — an invalid, repeated or over-cap report also gets 204."}}}},"/api/pagamento/aberto":{"post":{"operationId":"post_api_pagamento_aberto","summary":"The interface reports a visible payment prompt. Agents must not call this route.","description":"An empty same-origin report, sent automatically when a payment prompt becomes visible. It starts no payment, grants no access and receives no identity or credentials. It writes no database row per report. Counts events, not unique people. The private operator dashboard separates API payment requests and browser payment views per UTC day; the two counts may overlap.\nReturns: 202 with no body when accepted; 204 when ignored. Always no-store.","parameters":[{"name":"Origin","in":"header","required":true,"schema":{"type":"string"},"description":"The page origin, identical to this route's origin."},{"name":"Sec-Fetch-Site","in":"header","required":true,"schema":{"type":"string"},"description":"`same-origin`, set by the browser."},{"name":"X-MM-Payment-View","in":"header","required":true,"schema":{"type":"string"},"description":"`1`, set by the shared component."}],"responses":{"202":{"description":"202 with no body when accepted; 204 when ignored. Always no-store."}}}},"/api/pricing":{"get":{"operationId":"pricing","summary":"Current prices and free allowances.","description":"Returns: { product, quota{free,paid,how_to_pay,live,free_now?,trial?}, pricing, billing, api_index }","responses":{"200":{"description":"{ product, quota{free,paid,how_to_pay,live,free_now?,trial?}, pricing, billing, api_index }","content":{"application/json":{"schema":{"type":"object","properties":{"product":{"type":"string","description":"Product name."},"quota":{"allOf":[{"$ref":"#/components/schemas/PaymentQuota"}],"description":"Public allowances and current list prices; not personal usage."},"pricing":{"type":"string","description":"Absolute URL of the current price list."},"billing":{"type":"string","description":"Absolute URL of payment discovery or the existing billing summary."},"api_index":{"type":"string","description":"Absolute URL of the API catalog."}},"required":["product","quota","pricing","billing","api_index"]}}}},"405":{"description":"Use GET or HEAD."}}}},"/api/billing":{"get":{"operationId":"billing","summary":"Public payment and prepaid credit discovery.","description":"Returns: { product, quota{free,paid,how_to_pay,live,free_now?,trial?}, pricing, billing, api_index, payment{provider,mode,network,chain_id,pay_to,homolog,dev,dev_gate,gratis?,facilitator,asset,asset_address,faucet,wallets}, credit{url,header} }","responses":{"200":{"description":"{ product, quota{free,paid,how_to_pay,live,free_now?,trial?}, pricing, billing, api_index, payment{provider,mode,network,chain_id,pay_to,homolog,dev,dev_gate,gratis?,facilitator,asset,asset_address,faucet,wallets}, credit{url,header} }","content":{"application/json":{"schema":{"type":"object","properties":{"product":{"type":"string","description":"Product name."},"quota":{"allOf":[{"$ref":"#/components/schemas/PaymentQuota"}],"description":"Public allowances and current list prices; not personal usage."},"pricing":{"type":"string","description":"Absolute URL of the current price list."},"billing":{"type":"string","description":"Absolute URL of payment discovery or the existing billing summary."},"api_index":{"type":"string","description":"Absolute URL of the API catalog."},"payment":{"allOf":[{"$ref":"#/components/schemas/PaymentX402"}],"description":"Public x402 configuration; pay_to=null means not configured."},"credit":{"allOf":[{"$ref":"#/components/schemas/PaymentCredit"}],"description":"Prepaid credit entry point. Never contains a balance or token."}},"required":["product","quota","pricing","billing","api_index","payment","credit"]}}}},"405":{"description":"Use GET or HEAD."}}}}}}