{
  "openapi": "3.1.0",
  "info": {
    "title": "PageAudit",
    "version": "359bbfd6",
    "description": "Technical SEO auditor that ships the fix. Main client: AI agents. Browsable index at GET /api/."
  },
  "servers": [
    {
      "url": "https://staging.pageaudit.online"
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Guest token (`POST /api/guest`) in `X-Guest-Token: pa_…`, `Authorization: Bearer pa_…` or `?guest_token=pa_…`. Only a token this site issued is accepted. A signed-in account (cookie) also works and takes precedence; after the claim the token owns nothing."
      },
      "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)."
      }
    },
    "schemas": {
      "Audit": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID of the stored audit; `null` when the database was unavailable.",
            "nullable": true
          },
          "score": {
            "type": "integer",
            "description": "0–100 for measured checks: error -18, warn -8, info 0. Not a security/accessibility certification. Older saved scores keep their original weights."
          },
          "issues": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Achado"
            },
            "description": "Everything found, from most to least severe."
          },
          "summary": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ResumoPagina"
              }
            ],
            "description": "What the page declares: title, meta, canonical, OG, headings, links…"
          },
          "counts": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ContagemAchados"
              }
            ],
            "description": "How many findings of each severity."
          },
          "headers": {
            "type": "object",
            "description": "Every header of the target's response. `Set-Cookie` is removed on purpose: it is a third party's credential."
          },
          "htmlTruncated": {
            "type": "boolean",
            "description": "`true` when the page passed 2 MB and was read only that far."
          },
          "jsonLd": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "The raw JSON-LD blocks, as they were on the page."
          },
          "jsonLdStored": {
            "type": "integer",
            "description": "How many blocks survived the size cap — compare with `summary.jsonLdBlocks`."
          },
          "truncated": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What was cut and why: `jsonld_size`, `jsonld_nodes_over_50`, `result_size`. Empty means nothing cut."
          },
          "fixes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Correcao"
            },
            "description": "The ready fix of each finding, without a model — paste, fill in or decide. The consolidated one is at `_links.patch`."
          },
          "quota": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CotaAudit"
              }
            ],
            "description": "How much is still free and what it costs past that."
          },
          "_links": {
            "allOf": [
              {
                "$ref": "#/components/schemas/LinksAudit"
              }
            ],
            "description": "This audit, the patch, the share and the API index."
          }
        },
        "required": [
          "id",
          "score",
          "issues",
          "summary",
          "counts",
          "headers",
          "htmlTruncated",
          "jsonLd",
          "jsonLdStored",
          "truncated",
          "fixes",
          "quota",
          "_links"
        ],
        "description": "The report of one audit: score, findings and everything observed on the page."
      },
      "Achado": {
        "type": "object",
        "properties": {
          "severity": {
            "type": "string",
            "description": "Severity of the finding."
          },
          "code": {
            "type": "string",
            "description": "Stable check code, e.g. `title_missing`. It is what you filter by."
          },
          "message": {
            "type": "string",
            "description": "The finding in one sentence, ready to show a person."
          }
        },
        "required": [
          "severity",
          "code",
          "message"
        ],
        "description": "A problem (or a pass) found on the page."
      },
      "ResumoPagina": {
        "type": "object",
        "properties": {
          "finalUrl": {
            "type": "string",
            "description": "URL after following every redirect."
          },
          "status": {
            "type": "integer",
            "description": "Final HTTP status of the target."
          },
          "contentType": {
            "type": "string",
            "description": "Content-Type of the final response.",
            "nullable": true
          },
          "title": {
            "type": "string",
            "description": "Content of `<title>`.",
            "nullable": true
          },
          "metaDescription": {
            "type": "string",
            "description": "Content of `<meta name=description>`.",
            "nullable": true
          },
          "canonical": {
            "type": "string",
            "description": "Canonical URL declared by the page.",
            "nullable": true
          },
          "robots": {
            "type": "string",
            "description": "Content of `<meta name=robots>`.",
            "nullable": true
          },
          "viewport": {
            "type": "string",
            "description": "Content of `<meta name=viewport>`.",
            "nullable": true
          },
          "charset": {
            "type": "string",
            "description": "Declared encoding.",
            "nullable": true
          },
          "lang": {
            "type": "string",
            "description": "Language declared in `<html lang>`.",
            "nullable": true
          },
          "favicon": {
            "type": "string",
            "description": "URL of the favicon found.",
            "nullable": true
          },
          "faviconSource": {
            "type": "string",
            "description": "How the favicon was found: declared or by the default path.",
            "nullable": true
          },
          "h1s": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Every `<h1>` on the page, in order."
          },
          "openGraph": {
            "type": "object",
            "description": "The `og:*` tags found, key by key."
          },
          "twitter": {
            "type": "object",
            "description": "The `twitter:*` tags found."
          },
          "jsonLdCount": {
            "type": "integer",
            "description": "How many JSON-LD nodes the page had."
          },
          "jsonLdBlocks": {
            "type": "integer",
            "description": "How many `<script type=application/ld+json>` blocks existed."
          },
          "jsonLdErrors": {
            "type": "integer",
            "description": "Invalid JSON syntax or non-object root values; not full JSON-LD/schema.org validation."
          },
          "jsonLdDropped": {
            "type": "boolean",
            "description": "`true` when nodes were dropped for passing the cap."
          },
          "jsonLdTypes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The `@type`s found, e.g. `Organization`, `WebSite`."
          },
          "images": {
            "type": "object",
            "description": "Image count and how many have no `alt`."
          },
          "links": {
            "type": "object",
            "description": "Count of internal, external and text-less links."
          },
          "words": {
            "type": "integer",
            "description": "Words in the visible content."
          },
          "hreflang": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "The declared language alternates."
          },
          "legacy": {
            "type": "object",
            "description": "Old markup still present (e.g. `<font>`, layout tables)."
          },
          "redirects": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "The redirect chain followed to the final URL."
          },
          "robotsTxt": {
            "type": "object",
            "description": "What the origin's `robots.txt` says about this URL."
          },
          "sitemap": {
            "type": "object",
            "description": "Whether the URL appears in the sitemap the origin declares."
          },
          "discovery": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Discovery"
              }
            ],
            "description": "Selected discovery and delivery checks; optional files missing do not lower the score. Up to 15 additional GETs, concurrency 2, 8s total deadline and 64 KiB per text body.",
            "nullable": true
          }
        },
        "required": [
          "finalUrl",
          "status",
          "contentType",
          "title",
          "metaDescription",
          "canonical",
          "robots",
          "viewport",
          "charset",
          "lang",
          "favicon",
          "faviconSource",
          "h1s",
          "openGraph",
          "twitter",
          "jsonLdCount",
          "jsonLdBlocks",
          "jsonLdDropped",
          "jsonLdTypes",
          "images",
          "links",
          "words",
          "hreflang",
          "legacy",
          "redirects",
          "robotsTxt",
          "sitemap"
        ],
        "description": "Everything the page declares about itself. It is the most consulted object of the API."
      },
      "Discovery": {
        "type": "object",
        "properties": {
          "llms": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DiscoveryCheck"
              }
            ],
            "description": "Root llms.txt or the most specific same-origin describedby guide found on the page."
          },
          "security": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DiscoveryCheck"
              }
            ],
            "description": "/.well-known/security.txt: selected RFC 9116 checks."
          },
          "apiCatalog": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DiscoveryCheck"
              }
            ],
            "description": "/.well-known/api-catalog: selected RFC 9727 Linkset checks."
          },
          "changePassword": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DiscoveryCheck"
              }
            ],
            "description": "/.well-known/change-password when the page uses a password field. Redirect only; the form is never submitted."
          },
          "assetlinks": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DiscoveryCheck"
              }
            ],
            "description": "/.well-known/assetlinks.json when Android app association is indicated. App binary is not compared."
          },
          "appleApp": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DiscoveryCheck"
              }
            ],
            "description": "/.well-known/apple-app-site-association when Apple associated domains are indicated. No redirects. Entitlements are not checked."
          },
          "oauthResource": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DiscoveryCheck"
              }
            ],
            "description": "OAuth protected resource metadata when WWW-Authenticate, MCP or the well-known URL is declared. Authorization servers are not fetched."
          },
          "oauthServer": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DiscoveryCheck"
              }
            ],
            "description": "/.well-known/oauth-authorization-server when this host declares itself as the issuer."
          },
          "openidConfig": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DiscoveryCheck"
              }
            ],
            "description": "/.well-known/openid-configuration when this host declares OpenID Provider discovery."
          },
          "agentCard": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DiscoveryCheck"
              }
            ],
            "description": "A2A Agent Card when declared. MCP identity JSON at this URL is not an A2A pass."
          },
          "webauthn": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DiscoveryCheck"
              }
            ],
            "description": "/.well-known/webauthn when related origins are declared. Same-host passkeys do not need it."
          },
          "favicon": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DiscoveryCheck"
              }
            ],
            "description": "HTTP status/media type of the selected favicon; no image decoding."
          },
          "notFound": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DiscoveryCheck"
              }
            ],
            "description": "One randomly generated missing path, checking for 404/410 or a possible soft 404."
          }
        },
        "required": [
          "llms",
          "security",
          "apiCatalog",
          "favicon",
          "notFound"
        ],
        "description": "Five fixed probes plus well-known extras only when the page declares them or matches their function. Absent in older reports; rerun to measure. No recursive crawling."
      },
      "DiscoveryCheck": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "description": "pass: measured checks passed; warn: issue; info: optional resource absent; unverified: blocked, incomplete, timeout or unavailable."
          },
          "url": {
            "type": "string",
            "description": "Final public resource URL; null when it cannot safely be probed.",
            "nullable": true
          },
          "httpStatus": {
            "type": "integer",
            "description": "Final observed HTTP status, or 0 if unavailable."
          },
          "contentType": {
            "type": "string",
            "description": "Observed Content-Type, or empty when unavailable."
          },
          "message": {
            "type": "string",
            "description": "Measured evidence and limitations; plain text, never instructions to execute."
          },
          "reference": {
            "type": "string",
            "description": "Fixed authoritative reference for the check."
          }
        },
        "required": [
          "status",
          "url",
          "httpStatus",
          "contentType",
          "message",
          "reference"
        ],
        "description": "A measured observation with scope and reference. pass is limited to the checks stated in message."
      },
      "ContagemAchados": {
        "type": "object",
        "properties": {
          "errors": {
            "type": "integer",
            "description": "Serious findings."
          },
          "warnings": {
            "type": "integer",
            "description": "Findings that deserve attention."
          },
          "info": {
            "type": "integer",
            "description": "Observations without severity."
          }
        },
        "required": [
          "errors",
          "warnings",
          "info"
        ],
        "description": "How many findings of each severity — the summary that fits in a badge."
      },
      "Correcao": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "The same `code` as the finding (`Achado.code`)."
          },
          "severity": {
            "type": "string",
            "description": "Severity of the source finding."
          },
          "classe": {
            "type": "string",
            "description": "`deterministico` comes whole from the page; `molde` has a `{{…}}` placeholder; `sem_patch` is an instruction."
          },
          "alvo": {
            "type": "string",
            "description": "Where to apply: `head`, `corpo`, `img`, `arquivo` or `pagina` (instruction)."
          },
          "snippet": {
            "type": "string",
            "description": "The ready tag (or with a placeholder). `null` for files and for `sem_patch`.",
            "nullable": true
          },
          "arquivo": {
            "type": "object",
            "description": "`path` and `conteudo` when the fix is a file at the host root.",
            "nullable": true
          },
          "fonte": {
            "type": "string",
            "description": "Where the value came from, or what the page already had (for the template or to check the cut).",
            "nullable": true
          },
          "nota": {
            "type": "string",
            "description": "How to apply, or what to decide.",
            "nullable": true
          }
        },
        "required": [
          "code",
          "severity",
          "classe",
          "alvo",
          "snippet",
          "arquivo",
          "fonte",
          "nota"
        ],
        "description": "The ready fix of one finding. `classe` says whether it is to paste, to fill in or to decide."
      },
      "CotaAudit": {
        "type": "object",
        "properties": {
          "free_per_day": {
            "type": "integer",
            "description": "Free audits per IP per day."
          },
          "price_usd": {
            "type": "number",
            "description": "Price of an audit beyond the allowance, in USD."
          }
        },
        "required": [
          "free_per_day",
          "price_usd"
        ],
        "description": "How much is still free and what it costs past that."
      },
      "LinksAudit": {
        "type": "object",
        "properties": {
          "self": {
            "type": "string",
            "description": "This audit, to re-read without re-auditing."
          },
          "patch": {
            "type": "string",
            "description": "`GET /api/audits/:id/patch` — the consolidated patch of this audit.",
            "nullable": true
          },
          "share": {
            "type": "string",
            "description": "Where to publish this audit under a public slug."
          },
          "api_index": {
            "type": "string",
            "description": "Self-describing API index."
          }
        },
        "required": [
          "patch",
          "api_index"
        ],
        "description": "Addresses of the audit just created. Without a stored `id`, only `api_index` comes."
      },
      "AuditGravado": {
        "type": "object",
        "properties": {
          "audit_id": {
            "type": "string",
            "description": "ID of the audit."
          },
          "url": {
            "type": "string",
            "description": "Final audited URL, after following the redirects."
          },
          "score": {
            "type": "integer",
            "description": "Score from 0 to 100."
          },
          "summary": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ResumoPagina"
              }
            ],
            "description": "What the page declared at the time of the run.",
            "nullable": true
          },
          "counts": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ContagemAchados"
              }
            ],
            "description": "How many findings of each severity."
          },
          "issues": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Achado"
            },
            "description": "Everything found in that run."
          },
          "fixes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Correcao"
            },
            "description": "The ready fix of each finding; an audit stored before this existed gets the computation on read."
          },
          "jsonLd": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "The raw JSON-LD blocks stored."
          },
          "headers": {
            "type": "object",
            "description": "Headers of the target's response, as they were in the run."
          },
          "truncated": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What was cut by size when storing."
          },
          "share_slug": {
            "type": "string",
            "description": "Public slug, if this audit was shared.",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "description": "When the run happened (UTC)."
          }
        },
        "required": [
          "audit_id",
          "url",
          "score",
          "summary",
          "counts",
          "issues",
          "fixes",
          "jsonLd",
          "headers",
          "truncated",
          "share_slug",
          "created_at"
        ],
        "description": "The same report re-read from the database. It has no `quota` and no `_links` (it is a read, not a run) and gains the date and the share slug."
      },
      "Patch": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "Final audited URL.",
            "nullable": true
          },
          "audit": {
            "type": "string",
            "description": "Absolute link of the source audit.",
            "nullable": true
          },
          "head": {
            "type": "string",
            "description": "The deterministic tags, one per line, in <head> order (charset first). Empty when there are none."
          },
          "arquivos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ArquivoPatch"
            },
            "description": "Files to create at the host root."
          },
          "moldes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MoldePatch"
            },
            "description": "What only the owner can fill in."
          },
          "sem_patch": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SemPatch"
            },
            "description": "What is a decision or infrastructure."
          },
          "resumo": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ResumoPatch"
              }
            ],
            "description": "Count per class."
          },
          "como_aplicar": {
            "type": "string",
            "description": "One-sentence instruction."
          },
          "_links": {
            "type": "object",
            "description": "`api_index`."
          }
        },
        "required": [
          "url",
          "audit",
          "head",
          "arquivos",
          "moldes",
          "sem_patch",
          "resumo",
          "como_aplicar",
          "_links"
        ],
        "description": "The consolidated patch of an audit, ready for the agent that builds the site to apply."
      },
      "ArquivoPatch": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "Finding that originated it (`robots_txt_missing`, `sitemap_missing`)."
          },
          "path": {
            "type": "string",
            "description": "Absolute path on the host, e.g. `/robots.txt`."
          },
          "conteudo": {
            "type": "string",
            "description": "Full content of the file."
          }
        },
        "required": [
          "code",
          "path",
          "conteudo"
        ],
        "description": "A file to create at the host root."
      },
      "MoldePatch": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "Source finding."
          },
          "alvo": {
            "type": "string",
            "description": "`head`, `corpo` or `img`."
          },
          "snippet": {
            "type": "string",
            "description": "The tag with `{{PLACEHOLDER}}`."
          },
          "fonte": {
            "type": "string",
            "description": "Suggestion taken from the page itself (H1, og:description…), if any.",
            "nullable": true
          },
          "nota": {
            "type": "string",
            "description": "What to fill in and the limit."
          }
        },
        "required": [
          "code",
          "alvo",
          "snippet",
          "fonte",
          "nota"
        ],
        "description": "A tag with a marked placeholder: content missing that only the owner knows."
      },
      "SemPatch": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "Source finding."
          },
          "nota": {
            "type": "string",
            "description": "What to check or decide."
          }
        },
        "required": [
          "code",
          "nota"
        ],
        "description": "Finding without an automatic fix: it is a decision or infrastructure."
      },
      "ResumoPatch": {
        "type": "object",
        "properties": {
          "deterministicos": {
            "type": "integer",
            "description": "Ready to paste (head + files)."
          },
          "moldes": {
            "type": "integer",
            "description": "With a placeholder."
          },
          "sem_patch": {
            "type": "integer",
            "description": "Instruction only."
          },
          "total": {
            "type": "integer",
            "description": "Findings considered."
          }
        },
        "required": [
          "deterministicos",
          "moldes",
          "sem_patch",
          "total"
        ],
        "description": "How many fixes of each class."
      },
      "Ferramenta": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "description": "Identifier in the URL, e.g. `title-tag-checker`."
          },
          "title": {
            "type": "string",
            "description": "Page title, used in `<title>`."
          },
          "h1": {
            "type": "string",
            "description": "The landing's H1."
          },
          "description": {
            "type": "string",
            "description": "Meta description of the landing."
          },
          "lead": {
            "type": "string",
            "description": "Opening paragraph."
          },
          "category": {
            "type": "string",
            "description": "Grouping of the tool in the hub."
          },
          "icon": {
            "type": "string",
            "description": "Name of the icon used in the card."
          },
          "checks": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Finding codes this tool highlights — they are the `Achado.code`s."
          },
          "serp": {
            "type": "object",
            "description": "How the result looks in the search preview."
          },
          "sections": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Content blocks of the landing."
          },
          "_links": {
            "type": "object",
            "description": "This tool in JSON and in HTML."
          }
        },
        "required": [
          "slug",
          "title",
          "h1",
          "description",
          "lead",
          "category",
          "icon",
          "checks",
          "serp",
          "sections",
          "_links"
        ],
        "description": "A micro-tool: the landing of one isolated check, with the same engine as the full audit."
      },
      "Compartilhamento": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "description": "Always `true`."
          },
          "shared": {
            "type": "boolean",
            "description": "Whether the audit is published at the end of the call."
          },
          "slug": {
            "type": "string",
            "description": "Public, non-enumerable slug."
          },
          "path": {
            "type": "string",
            "description": "Path of the report's HTML page."
          },
          "badge": {
            "type": "string",
            "description": "Path of the score badge SVG."
          },
          "_links": {
            "type": "object",
            "description": "Report, JSON and badge, as absolute URLs."
          }
        },
        "required": [
          "ok",
          "shared",
          "slug",
          "path",
          "badge",
          "_links"
        ],
        "description": "The result of publishing an audit under a non-enumerable slug."
      },
      "Badge": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "description": "Slug of the shared report."
          },
          "score": {
            "type": "integer",
            "description": "Score shown in the badge.",
            "nullable": true
          },
          "label": {
            "type": "string",
            "description": "Text on the left of the badge."
          },
          "available": {
            "type": "boolean",
            "description": "`false` when the share was revoked — the SVG turns grey `n/a`."
          },
          "markdown": {
            "type": "string",
            "description": "The markdown line ready to paste in the README."
          },
          "_links": {
            "type": "object",
            "description": "The SVG and the report."
          }
        },
        "required": [
          "slug",
          "score",
          "label",
          "available",
          "markdown",
          "_links"
        ],
        "description": "The score badge metadata, to build the README markdown."
      },
      "Workspace": {
        "type": "object",
        "properties": {
          "tabs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Aba"
            },
            "description": "Every tab of the owner."
          },
          "active_id": {
            "type": "string",
            "description": "Which tab is in focus.",
            "nullable": true
          },
          "active_result": {
            "allOf": [
              {
                "$ref": "#/components/schemas/AuditGravado"
              }
            ],
            "description": "The last result of the active tab, so a second call is not needed.",
            "nullable": true
          },
          "limit": {
            "type": "integer",
            "description": "How many tabs fit before paying."
          },
          "owner": {
            "type": "string",
            "description": "Identifier of this workspace's owner."
          },
          "gate": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Gate"
              }
            ],
            "description": "How much of the IP's free allowance remains."
          },
          "billing": {
            "type": "object",
            "description": "Prices and usage, the same `GET /api/billing` returns."
          }
        },
        "required": [
          "tabs",
          "active_id",
          "active_result",
          "limit",
          "owner",
          "gate",
          "billing"
        ],
        "description": "The owner's whole workspace, with the active tab's result already rehydrated — one call to draw the screen."
      },
      "Aba": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID of the tab."
          },
          "url": {
            "type": "string",
            "description": "URL the tab follows."
          },
          "alias": {
            "type": "string",
            "description": "Label the person gave the tab.",
            "nullable": true
          },
          "active": {
            "type": "boolean",
            "description": "Whether it is the focused tab in the workspace."
          },
          "audit_id": {
            "type": "string",
            "description": "Audit of this tab's last run.",
            "nullable": true
          },
          "score": {
            "type": "integer",
            "description": "Score of the last run.",
            "nullable": true
          },
          "monitor": {
            "type": "boolean",
            "description": "Whether the daily watch is on for this tab."
          },
          "monitor_email": {
            "type": "string",
            "description": "Where the watch writes; `null` means the account's e-mail.",
            "nullable": true
          },
          "monitor_checked_at": {
            "type": "string",
            "description": "When the watch last checked this page (UTC).",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "description": "When the tab was opened (UTC)."
          }
        },
        "required": [
          "id",
          "url",
          "alias",
          "active",
          "audit_id",
          "score",
          "monitor",
          "monitor_email",
          "monitor_checked_at",
          "created_at"
        ],
        "description": "A workspace tab: one followed URL, with the last result kept."
      },
      "Gate": {
        "type": "object",
        "properties": {
          "ip": {
            "type": "string",
            "description": "IP seen by the edge, already masked."
          },
          "now": {
            "type": "integer",
            "description": "Time of the query, in epoch."
          },
          "configured": {
            "type": "boolean",
            "description": "Whether Turnstile is configured in this environment."
          },
          "free_allowance": {
            "type": "integer",
            "description": "Free audits per day."
          },
          "free_remaining": {
            "type": "integer",
            "description": "How many remain today for this IP."
          },
          "verified_until": {
            "type": "integer",
            "description": "Until when the verification already done is valid.",
            "nullable": true
          },
          "needs_verification": {
            "type": "boolean",
            "description": "`true` when the next call will ask for Turnstile (human) or 402 (agent)."
          },
          "sitekey": {
            "type": "string",
            "description": "Turnstile sitekey, for the browser to build the challenge.",
            "nullable": true
          }
        },
        "required": [
          "ip",
          "now",
          "configured",
          "free_allowance",
          "free_remaining",
          "verified_until",
          "needs_verification",
          "sitekey"
        ],
        "description": "How much of the daily allowance still exists for this IP, and whether Turnstile is already required."
      },
      "Ok": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "description": "Always `true` — failure comes as a 4xx/5xx status, not as `ok:false`."
          }
        },
        "required": [
          "ok"
        ],
        "description": "Write confirmation with no body of its own to return."
      },
      "RunHistorico": {
        "type": "object",
        "properties": {
          "audit_id": {
            "type": "string",
            "description": "The stored audit, readable at `GET /api/audits/:id`."
          },
          "score": {
            "type": "integer",
            "description": "Score of this run.",
            "nullable": true
          },
          "counts": {
            "type": "object",
            "description": "How many errors, warnings and infos this run had."
          },
          "created_at": {
            "type": "string",
            "description": "When the run happened (UTC)."
          },
          "change": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Mudanca"
              }
            ],
            "description": "What changed since the previous run.",
            "nullable": true
          },
          "shared": {
            "type": "string",
            "description": "Public report URL, when this run was shared.",
            "nullable": true
          },
          "api": {
            "type": "string",
            "description": "This run in the API."
          }
        },
        "required": [
          "audit_id",
          "score",
          "counts",
          "created_at",
          "change",
          "shared",
          "api"
        ],
        "description": "One run of a tab in the series, with what changed since the run before it. `change` is null on the oldest run read — with no base there is no change to state."
      },
      "Mudanca": {
        "type": "object",
        "properties": {
          "score": {
            "type": "integer",
            "description": "Point delta, signed (positive means it improved).",
            "nullable": true
          },
          "from": {
            "type": "integer",
            "description": "Score of the previous run.",
            "nullable": true
          },
          "to": {
            "type": "integer",
            "description": "Score of this run.",
            "nullable": true
          },
          "broke": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Findings that appeared, each with `code`, `severity` and `message`."
          },
          "fixed": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Findings that disappeared, in the same shape."
          }
        },
        "required": [
          "score",
          "from",
          "to",
          "broke",
          "fixed"
        ],
        "description": "The difference between two runs of the same page. Findings are compared by code, never by message: the message carries the measured value and would change without anything getting worse."
      },
      "Billing": {
        "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)."
          },
          "product": {
            "type": "string",
            "description": "Name of the product charging."
          },
          "free_max_tabs": {
            "type": "integer",
            "description": "Free tabs per owner."
          },
          "prices": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Precos"
              }
            ],
            "description": "What each paid action costs, in USD."
          },
          "usage": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Uso"
              }
            ],
            "description": "How much of the free allowance has been used."
          },
          "trial": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Trial"
              }
            ],
            "description": "The account's trial, when there is a session."
          }
        },
        "required": [
          "provider",
          "mode",
          "network",
          "chain_id",
          "pay_to",
          "homolog",
          "dev",
          "dev_gate",
          "facilitator",
          "asset",
          "asset_address",
          "faucet",
          "wallets",
          "product",
          "free_max_tabs",
          "prices",
          "usage",
          "trial"
        ],
        "description": "Everything that decides whether the next call will cost: the x402 configuration, the prices, the usage and the trial."
      },
      "Precos": {
        "type": "object",
        "properties": {
          "extra_tab_usd": {
            "type": "number",
            "description": "Cost of a tab beyond the allowance."
          },
          "contact_agent_usd": {
            "type": "number",
            "description": "Cost of an agent contact."
          }
        },
        "required": [
          "extra_tab_usd",
          "contact_agent_usd"
        ],
        "description": "Prices in force, in dollars. Read them here, not from the documentation."
      },
      "Uso": {
        "type": "object",
        "properties": {
          "tabs": {
            "type": "integer",
            "description": "Tabs open now."
          },
          "free_slots_left": {
            "type": "integer",
            "description": "Free tabs still available."
          }
        },
        "required": [
          "tabs",
          "free_slots_left"
        ],
        "description": "How much of the free allowance the owner has used."
      },
      "Trial": {
        "type": "object",
        "properties": {
          "days": {
            "type": "integer",
            "description": "Trial length in days."
          },
          "active": {
            "type": "boolean",
            "description": "Whether it is in force now."
          },
          "days_left": {
            "type": "integer",
            "description": "How many days remain."
          },
          "ends_at": {
            "type": "string",
            "description": "When it ends (UTC).",
            "nullable": true
          }
        },
        "required": [
          "days",
          "active",
          "ends_at"
        ],
        "description": "The paywall-free period of an account, counted from its first use of PageAudit — once per account. It is the alternative to paying."
      },
      "Conta": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID of the global account — the owner of the tabs and audits."
          },
          "email": {
            "type": "string",
            "description": "The account's verified e-mail."
          }
        },
        "required": [
          "id",
          "email"
        ],
        "description": "The person behind the session."
      },
      "Metricas": {
        "type": "object",
        "properties": {
          "app": {
            "type": "string",
            "description": "Product name."
          },
          "today": {
            "type": "string",
            "description": "Reference day (UTC, YYYY-MM-DD)."
          },
          "today_visits": {
            "type": "integer",
            "description": "Visits counted today."
          },
          "today_contacts": {
            "type": "integer",
            "description": "Contact messages received today. Only with `METRICS_TOKEN`: contact does not leave without a token."
          },
          "days": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "One record per day of the window, with the counts of each metric."
          },
          "usage": {
            "type": "object",
            "description": "Usage per product resource — here, audits and tabs."
          },
          "accounts": {
            "type": "object",
            "description": "Total guests and accounts."
          },
          "financeiro": {
            "type": "object",
            "description": "Aggregate of the day: `hoje_usd`, `hoje_count`, `rede`. Only with `METRICS_TOKEN`: money does not leave without a token; the full series is `payments`."
          },
          "payments": {
            "type": "object",
            "description": "Finance summary; only with METRICS_TOKEN."
          },
          "achados": {
            "type": "object",
            "description": "Which findings appear across stored audits: `audits` (total) and `por_codigo[]` with `code`, `n`, `audits` and `fracao_audits`. Aggregate, no URL and no owner; 1 h cache. `null` if the database did not answer.",
            "nullable": true
          }
        },
        "required": [
          "app",
          "today",
          "today_visits",
          "days",
          "usage",
          "accounts",
          "achados"
        ],
        "description": "7-day panel. `payments` only shows with the operator token and only on Base mainnet."
      },
      "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"
        ]
      }
    }
  },
  "paths": {
    "/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[]`.",
        "security": [],
        "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.",
        "security": [],
        "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.",
        "security": [],
        "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[]`.",
        "security": [],
        "responses": {
          "200": {
            "description": "`application/json` in the APIs.json 0.19 format: `apis[]` with `baseURL`, `humanURL` and `properties[]`."
          }
        }
      }
    },
    "/api/": {
      "get": {
        "operationId": "api_index",
        "summary": "Self-describing index: the whole API surface, with quota and retention policy.",
        "description": "Returns: { name, description, build, base_url, docs, conventions, auth, endpoints, data_retention, quota, mcp, quickstart }",
        "security": [],
        "responses": {
          "200": {
            "description": "{ name, description, build, base_url, docs, conventions, auth, endpoints, data_retention, quota, mcp, quickstart }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string",
                      "description": "Product name."
                    },
                    "description": {
                      "type": "string",
                      "description": "What the product does, in one sentence."
                    },
                    "build": {
                      "type": "string",
                      "description": "Deployed commit."
                    },
                    "base_url": {
                      "type": "string",
                      "description": "Origin this API is serving from."
                    },
                    "docs": {
                      "type": "object",
                      "description": "Links to llms.txt, llms-full.txt, openapi.json, MCP and the UI."
                    },
                    "conventions": {
                      "type": "object",
                      "description": "Error format, CORS, x402 and the UI↔API parity rule."
                    },
                    "auth": {
                      "type": "object",
                      "description": "Each authentication mode and how to obtain it."
                    },
                    "endpoints": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      },
                      "description": "Every endpoint with method, path, auth, absolute URL and what it returns."
                    },
                    "data_retention": {
                      "type": "object",
                      "description": "What is stored from each run and what is discarded."
                    },
                    "quota": {
                      "type": "object",
                      "description": "What is free, what costs and how to pay — before you spend a call."
                    },
                    "mcp": {
                      "type": "object",
                      "description": "Address and transport of the MCP server."
                    },
                    "quickstart": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "The calls that take you from zero to the first report."
                    }
                  },
                  "required": [
                    "name",
                    "description",
                    "build",
                    "base_url",
                    "docs",
                    "conventions",
                    "auth",
                    "endpoints",
                    "data_retention",
                    "quota",
                    "mcp",
                    "quickstart"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "health",
        "summary": "Liveness and the commit deployed right now — it is how the smoke waits for its own deploy.",
        "description": "Returns: { ok, app, build, ts }",
        "security": [],
        "responses": {
          "200": {
            "description": "{ ok, app, build, ts }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "Always `true` when the Worker answers."
                    },
                    "app": {
                      "type": "string",
                      "description": "Product name."
                    },
                    "build": {
                      "type": "string",
                      "description": "Deployed commit; CI passes the short SHA on deploy."
                    },
                    "ts": {
                      "type": "string",
                      "description": "Time of the response (UTC, ISO-8601)."
                    }
                  },
                  "required": [
                    "ok",
                    "app",
                    "build",
                    "ts"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "post_mcp",
        "summary": "MCP server over HTTP (Streamable HTTP, JSON-RPC 2.0) — plugs into the client with nothing to install.",
        "description": "The tools are the operations of this same catalog; the MCP has no backend of its own. `GET /mcp` returns the server card.\nReturns: JSON-RPC 2.0 response (`initialize`, `tools/list` or `tools/call`).\nCredentials go in the usual headers (X-Guest-Token, Authorization, X-PAYMENT) and are forwarded to the API.\nAn exhausted quota comes back as a 402 with accepts[] inside the tool result — pay and repeat.",
        "security": [],
        "responses": {
          "200": {
            "description": "JSON-RPC 2.0 response (`initialize`, `tools/list` or `tools/call`)."
          }
        }
      }
    },
    "/api/audit": {
      "post": {
        "operationId": "audit_url",
        "summary": "Audits a URL and returns the full report in one call, without a token or a tab.",
        "description": "This is the product for agents. Past the IP's daily allowance the response is **402 with `accepts[]`** — pay and repeat the same call. It also carries `sitekey` and `code`, which are the path for a human with a browser; an agent ignores those two. The free alternative: a person signs in with an account to get the trial.\nReturns: { id, score, issues[{severity,code,message}], summary{finalUrl,status,contentType,title,metaDescription,canonical,robots,viewport,charset,lang,favicon,faviconSource,h1s,openGraph,twitter,jsonLdCount,jsonLdBlocks,jsonLdErrors?,jsonLdDropped,jsonLdTypes,images,links,words,hreflang,legacy,redirects,robotsTxt,sitemap,discovery?}, counts{errors,warnings,info}, headers, htmlTruncated, jsonLd, jsonLdStored, truncated, fixes[{code,severity,classe,alvo,snippet,arquivo,fonte,nota}], quota{free_per_day,price_usd}, _links{self?,patch,share?,api_index} }",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "The page to audit, `http` or `https`."
                  },
                  "guest_token": {
                    "type": "string",
                    "description": "Guest `pa_…` so the audit is tied to it and shows up in the tabs."
                  },
                  "cf_turnstile_response": {
                    "type": "string",
                    "description": "Turnstile response; it is the human path, agents use x402."
                  }
                },
                "required": [
                  "url"
                ]
              },
              "example": {
                "url": "https://example.com/",
                "guest_token": "pa_… (optional, ties the audit)"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ id, score, issues[{severity,code,message}], summary{finalUrl,status,contentType,title,metaDescription,canonical,robots,viewport,charset,lang,favicon,faviconSource,h1s,openGraph,twitter,jsonLdCount,jsonLdBlocks,jsonLdErrors?,jsonLdDropped,jsonLdTypes,images,links,words,hreflang,legacy,redirects,robotsTxt,sitemap,discovery?}, counts{errors,warnings,info}, headers, htmlTruncated, jsonLd, jsonLdStored, truncated, fixes[{code,severity,classe,alvo,snippet,arquivo,fonte,nota}], quota{free_per_day,price_usd}, _links{self?,patch,share?,api_index} }",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Audit"
                }
              }
            }
          },
          "400": {
            "description": "Body is not JSON, or `url` missing/not http."
          },
          "402": {
            "description": "Quota exceeded. The response carries `accepts[]` (x402, USDC on Base): pay and repeat the same call with `X-PAYMENT`."
          },
          "403": {
            "description": "Wrong Turnstile answer. A wrong captcha is not an invitation to pay."
          },
          "429": {
            "description": "Past `MAX_AUDITS_PER_HOUR` on the same IP. Wait an hour."
          }
        }
      }
    },
    "/api/audits/{id}": {
      "get": {
        "operationId": "get_audit",
        "summary": "Re-reads an audit already made, in full, without re-auditing the page.",
        "description": "Re-reading costs nothing and does not count against the allowance — the page's HTML is not kept, but the report is.\nReturns: { audit_id, url, score, summary{finalUrl,status,contentType,title,metaDescription,canonical,robots,viewport,charset,lang,favicon,faviconSource,h1s,openGraph,twitter,jsonLdCount,jsonLdBlocks,jsonLdErrors?,jsonLdDropped,jsonLdTypes,images,links,words,hreflang,legacy,redirects,robotsTxt,sitemap,discovery?}, counts{errors,warnings,info}, issues[{severity,code,message}], fixes[{code,severity,classe,alvo,snippet,arquivo,fonte,nota}], jsonLd, headers, truncated, share_slug, created_at }",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Audit ID, from `Audit.id`.",
            "example": "9f3c2b1d-7a4e-4c58-9b02-1f6d5e8a2c34"
          }
        ],
        "responses": {
          "200": {
            "description": "{ audit_id, url, score, summary{finalUrl,status,contentType,title,metaDescription,canonical,robots,viewport,charset,lang,favicon,faviconSource,h1s,openGraph,twitter,jsonLdCount,jsonLdBlocks,jsonLdErrors?,jsonLdDropped,jsonLdTypes,images,links,words,hreflang,legacy,redirects,robotsTxt,sitemap,discovery?}, counts{errors,warnings,info}, issues[{severity,code,message}], fixes[{code,severity,classe,alvo,snippet,arquivo,fonte,nota}], jsonLd, headers, truncated, share_slug, created_at }",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditGravado"
                }
              }
            }
          },
          "401": {
            "description": "No credential, or an invalid one. See this endpoint's auth."
          },
          "404": {
            "description": "The resource does not exist (or is not yours — the API does not tell the two apart on purpose)."
          }
        }
      }
    },
    "/api/audits/{id}/patch": {
      "get": {
        "operationId": "get_patch",
        "summary": "The consolidated patch of an audit: the <head> block ready to paste, the files to create at the root and the templates for what only the owner can fill in — no model, only facts from the page itself.",
        "description": "Each finding becomes a fix in one of three classes: `deterministico` (comes whole from what the page declares: final URL, title, description, OG), `molde` (a tag with a marked placeholder, like `{{TITULO}}`, and the suggested source) or `sem_patch` (a decision or infrastructure, with the instruction). Nothing is invented by a model.\nReturns: { url, audit, head, arquivos[{code,path,conteudo}], moldes[{code,alvo,snippet,fonte,nota}], sem_patch[{code,nota}], resumo{deterministicos,moldes,sem_patch,total}, como_aplicar, _links }",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Audit ID, from `Audit.id`.",
            "example": "9f3c2b1d-7a4e-4c58-9b02-1f6d5e8a2c34"
          }
        ],
        "responses": {
          "200": {
            "description": "{ url, audit, head, arquivos[{code,path,conteudo}], moldes[{code,alvo,snippet,fonte,nota}], sem_patch[{code,nota}], resumo{deterministicos,moldes,sem_patch,total}, como_aplicar, _links }",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Patch"
                }
              }
            }
          },
          "401": {
            "description": "No credential, or an invalid one. See this endpoint's auth."
          },
          "404": {
            "description": "The resource does not exist (or is not yours — the API does not tell the two apart on purpose)."
          }
        }
      }
    },
    "/api/tools": {
      "get": {
        "operationId": "list_tools",
        "summary": "The micro-tools: one landing per check, all driven by the same engine as the audit.",
        "description": "Returns: { tools[{slug,title,h1,description,lead,category,icon,checks,serp,sections,_links}], _links }",
        "security": [],
        "responses": {
          "200": {
            "description": "{ tools[{slug,title,h1,description,lead,category,icon,checks,serp,sections,_links}], _links }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tools": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Ferramenta"
                      },
                      "description": "Every published tool."
                    },
                    "_links": {
                      "type": "object",
                      "description": "The hub in HTML and the API index."
                    }
                  },
                  "required": [
                    "tools",
                    "_links"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/tools/{slug}": {
      "get": {
        "operationId": "get_tool",
        "summary": "Metadata and copy of one micro-tool.",
        "description": "Returns: { slug, title, h1, description, lead, category, icon, checks, serp, sections, _links }",
        "security": [],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tool slug, e.g. `title-tag-checker`.",
            "example": "title-tag-checker"
          }
        ],
        "responses": {
          "200": {
            "description": "{ slug, title, h1, description, lead, category, icon, checks, serp, sections, _links }",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ferramenta"
                }
              }
            }
          },
          "404": {
            "description": "Unknown slug."
          }
        }
      }
    },
    "/tools": {
      "get": {
        "operationId": "get_tools",
        "summary": "HTML hub of the micro-tools, indexable. For JSON use `GET /api/tools`.",
        "description": "Returns: `text/html` — the hub page, rendered on the server.",
        "security": [],
        "responses": {
          "200": {
            "description": "`text/html` — the hub page, rendered on the server."
          }
        }
      }
    },
    "/tools/{slug}": {
      "get": {
        "operationId": "get_tools_by_slug",
        "summary": "HTML landing of one check, indexable. An unknown slug returns a real 404.",
        "description": "The 404 is real, not a 200 with an empty shell: mass soft-404s burn the whole domain in the index.\nReturns: `text/html` — the tool's landing.",
        "security": [],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tool slug, e.g. `title-tag-checker`.",
            "example": "title-tag-checker"
          }
        ],
        "responses": {
          "200": {
            "description": "`text/html` — the tool's landing."
          },
          "404": {
            "description": "Unknown slug — a real 404, not an empty shell."
          }
        }
      }
    },
    "/api/audits/{id}/share": {
      "post": {
        "operationId": "post_api_audits_by_id_share",
        "summary": "Publishes the audit under a non-enumerable slug. Calling again returns the same slug.",
        "description": "Returns: { ok, shared, slug, path, badge, _links }",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ID of the audit to publish.",
            "example": "9f3c2b1d-7a4e-4c58-9b02-1f6d5e8a2c34"
          }
        ],
        "responses": {
          "200": {
            "description": "{ ok, shared, slug, path, badge, _links }",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Compartilhamento"
                }
              }
            }
          },
          "401": {
            "description": "No credential, or an invalid one. See this endpoint's auth."
          },
          "404": {
            "description": "The resource does not exist (or is not yours — the API does not tell the two apart on purpose)."
          }
        }
      },
      "delete": {
        "operationId": "delete_api_audits_by_id_share",
        "summary": "Revokes the share; the slug stops serving the report.",
        "description": "The badge keeps answering 200 with the grey `n/a` SVG — same box, so the layout of whoever pasted it in a README does not break.\nReturns: { ok, shared }",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ID of the audit to unpublish.",
            "example": "9f3c2b1d-7a4e-4c58-9b02-1f6d5e8a2c34"
          }
        ],
        "responses": {
          "200": {
            "description": "{ ok, shared }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "Always `true`."
                    },
                    "shared": {
                      "type": "boolean",
                      "description": "Always `false` at the end of this call."
                    }
                  },
                  "required": [
                    "ok",
                    "shared"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No credential, or an invalid one. See this endpoint's auth."
          },
          "404": {
            "description": "The resource does not exist (or is not yours — the API does not tell the two apart on purpose)."
          }
        }
      }
    },
    "/api/shared/{slug}": {
      "get": {
        "operationId": "get_api_shared_by_slug",
        "summary": "Shared report as JSON, without credentials — the machine twin of `/r/:slug`.",
        "description": "Returns: { audit_id, url, score, summary{finalUrl,status,contentType,title,metaDescription,canonical,robots,viewport,charset,lang,favicon,faviconSource,h1s,openGraph,twitter,jsonLdCount,jsonLdBlocks,jsonLdErrors?,jsonLdDropped,jsonLdTypes,images,links,words,hreflang,legacy,redirects,robotsTxt,sitemap,discovery?}, counts{errors,warnings,info}, issues[{severity,code,message}], fixes[{code,severity,classe,alvo,snippet,arquivo,fonte,nota}], jsonLd, headers, truncated, share_slug, created_at }",
        "security": [],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Public slug of the share.",
            "example": "k7m2p9r4t6v8w1y3z5b7c9d1"
          }
        ],
        "responses": {
          "200": {
            "description": "{ audit_id, url, score, summary{finalUrl,status,contentType,title,metaDescription,canonical,robots,viewport,charset,lang,favicon,faviconSource,h1s,openGraph,twitter,jsonLdCount,jsonLdBlocks,jsonLdErrors?,jsonLdDropped,jsonLdTypes,images,links,words,hreflang,legacy,redirects,robotsTxt,sitemap,discovery?}, counts{errors,warnings,info}, issues[{severity,code,message}], fixes[{code,severity,classe,alvo,snippet,arquivo,fonte,nota}], jsonLd, headers, truncated, share_slug, created_at }",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditGravado"
                }
              }
            }
          },
          "404": {
            "description": "Unknown slug, or share revoked."
          }
        }
      }
    },
    "/r/{slug}": {
      "get": {
        "operationId": "get_r_by_slug",
        "summary": "HTML page of the shared report, indexable, canonical at `/r/:slug`.",
        "description": "A public report is content: indexable, with its own canonical. Revoked or unknown slugs answer 404 (that one is `noindex`). The JSON twin is `/api/shared/:slug`.\nReturns: `text/html` — the rendered report, with `rel=canonical`.",
        "security": [],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Public slug of the share.",
            "example": "k7m2p9r4t6v8w1y3z5b7c9d1"
          }
        ],
        "responses": {
          "200": {
            "description": "`text/html` — the rendered report, with `rel=canonical`."
          },
          "404": {
            "description": "Unknown or revoked slug."
          }
        }
      }
    },
    "/api/badge/{slug}": {
      "get": {
        "operationId": "get_badge",
        "summary": "Metadata of the score badge, including the markdown ready for the README.",
        "description": "Returns: { slug, score, label, available, markdown, _links }",
        "security": [],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Public slug of the share.",
            "example": "k7m2p9r4t6v8w1y3z5b7c9d1"
          }
        ],
        "responses": {
          "200": {
            "description": "{ slug, score, label, available, markdown, _links }",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Badge"
                }
              }
            }
          },
          "404": {
            "description": "Unknown slug. Revoked is different: it returns 200 with `available: false`."
          }
        }
      }
    },
    "/badge/{slug}.svg": {
      "get": {
        "operationId": "get_badge_by_slug_svg",
        "summary": "SVG score badge, to paste in the README of the audited project.",
        "description": "A revoked share returns **200** with the grey `n/a` SVG — the same box, so the README of whoever pasted it does not end up with a broken image.\nReturns: `image/svg+xml` — the badge, coloured by the score or grey `n/a` if revoked.",
        "security": [],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Public slug, with the `.svg` extension in the path.",
            "example": "k7m2p9r4t6v8w1y3z5b7c9d1"
          }
        ],
        "responses": {
          "200": {
            "description": "`image/svg+xml` — the badge, coloured by the score or grey `n/a` if revoked."
          },
          "404": {
            "description": "Malformed slug."
          }
        }
      }
    },
    "/api/embed": {
      "get": {
        "operationId": "embed_snippet",
        "summary": "The embeddable widget's contract: what you can configure and the snippet to paste.",
        "description": "One script tag puts the audit form on your own site, with your name and colour, and no account or key. Send the same query you would send to `/embed` and the answer comes back with `snippet` already assembled. The widget never asks the visitor for an e-mail.\nReturns: { config, current, snippet, limits }",
        "security": [],
        "parameters": [
          {
            "name": "brand",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Your site's name, shown above the form (up to 40 characters)."
          },
          {
            "name": "color",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Accent colour in hex (`#0a7` or `#00aa77`); anything else falls back to ours."
          },
          {
            "name": "theme",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "`auto` (follows the visitor), `light` or `dark`."
          },
          {
            "name": "url",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional http(s) URL to pre-fill in the field."
          }
        ],
        "responses": {
          "200": {
            "description": "{ config, current, snippet, limits }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "config": {
                      "type": "object",
                      "description": "Each option, its type and what it does."
                    },
                    "current": {
                      "type": "object",
                      "description": "The configuration read from this call's query."
                    },
                    "snippet": {
                      "type": "string",
                      "description": "The `<script>` (plus a `<noscript>` link) ready to paste."
                    },
                    "limits": {
                      "type": "object",
                      "description": "The allowance the widget runs under, and the lead capture it does not do."
                    }
                  },
                  "required": [
                    "config",
                    "current",
                    "snippet",
                    "limits"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/embed.js": {
      "get": {
        "operationId": "get_embed_js",
        "summary": "The loader you paste: it creates the widget's iframe and keeps it the right height.",
        "description": "Configuration travels in `data-brand`, `data-color`, `data-theme` and `data-url` on the script tag itself. Nothing else of ours touches the host page: the widget lives inside the iframe, so neither the site's CSS reaches it nor our code reaches the site's DOM.\nReturns: `application/javascript` — the loader, cached for an hour.",
        "security": [],
        "responses": {
          "200": {
            "description": "`application/javascript` — the loader, cached for an hour."
          }
        }
      }
    },
    "/embed": {
      "get": {
        "operationId": "get_embed",
        "summary": "The widget page itself, made to be framed (`frame-ancestors *`) and not indexed.",
        "description": "Open it directly to preview a configuration before pasting the snippet. It calls `POST /api/audit` like any visitor would, so the free daily allowance per network applies.\nReturns: `text/html` — the widget, self-contained, with no third-party resource.",
        "security": [],
        "responses": {
          "200": {
            "description": "`text/html` — the widget, self-contained, with no third-party resource."
          }
        }
      }
    },
    "/api/guest": {
      "post": {
        "operationId": "create_guest",
        "summary": "Creates a guest `pa_…` — it is what gives access to the tab workspace without an account.",
        "description": "Keep the token: it is the identity of the tabs and of the audits tied to them.\nReturns: { token }",
        "security": [],
        "responses": {
          "200": {
            "description": "{ token }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string",
                      "description": "The guest, prefix `pa_`. Send it in `X-Guest-Token`, as Bearer or in `?guest_token=`."
                    }
                  },
                  "required": [
                    "token"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/tabs": {
      "get": {
        "operationId": "list_tabs",
        "summary": "The owner's whole workspace, with the active tab's result already rehydrated.",
        "description": "One call draws the whole screen: tabs, the focused tab, its last report, remaining allowance and prices.\nReturns: { tabs[{id,url,alias,active,audit_id,score,monitor,monitor_email,monitor_checked_at,created_at}], active_id, active_result{audit_id,url,score,summary,counts,issues,fixes,jsonLd,headers,truncated,share_slug,created_at}, limit, owner, gate{ip,now,configured,free_allowance,free_remaining,verified_until,needs_verification,sitekey}, billing }",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "{ tabs[{id,url,alias,active,audit_id,score,monitor,monitor_email,monitor_checked_at,created_at}], active_id, active_result{audit_id,url,score,summary,counts,issues,fixes,jsonLd,headers,truncated,share_slug,created_at}, limit, owner, gate{ip,now,configured,free_allowance,free_remaining,verified_until,needs_verification,sitekey}, billing }",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Workspace"
                }
              }
            }
          },
          "401": {
            "description": "No credential, or an invalid one. See this endpoint's auth."
          }
        }
      },
      "post": {
        "operationId": "create_tab",
        "summary": "Opens a tab for the URL, or focuses the one that already exists for it.",
        "description": "Past the free tab allowance it answers 402 with `accepts[]`: pay and repeat.\nReturns: { ok, tab{id,url,alias,active,audit_id,score,monitor,monitor_email,monitor_checked_at,created_at} }",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "The URL the tab will follow."
                  },
                  "alias": {
                    "type": "string",
                    "description": "Label to recognise the tab in the list."
                  }
                },
                "required": [
                  "url"
                ]
              },
              "example": {
                "url": "https://example.com/",
                "alias": "optional label"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ ok, tab{id,url,alias,active,audit_id,score,monitor,monitor_email,monitor_checked_at,created_at} }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "Always `true`."
                    },
                    "tab": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Aba"
                        }
                      ],
                      "description": "The opened tab (or the one that already existed for that URL)."
                    }
                  },
                  "required": [
                    "ok",
                    "tab"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`url` missing or not http."
          },
          "401": {
            "description": "No credential, or an invalid one. See this endpoint's auth."
          },
          "402": {
            "description": "Quota exceeded. The response carries `accepts[]` (x402, USDC on Base): pay and repeat the same call with `X-PAYMENT`."
          }
        }
      }
    },
    "/api/tabs/{id}": {
      "get": {
        "operationId": "get_api_tabs_by_id",
        "summary": "One tab with the full report of its last run.",
        "description": "Returns: { tab{id,url,alias,active,audit_id,score,monitor,monitor_email,monitor_checked_at,created_at}, result{audit_id,url,score,summary,counts,issues,fixes,jsonLd,headers,truncated,share_slug,created_at} }",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tab ID, from `Aba.id`.",
            "example": "tab_9f3c2b1d7a4e58b0c2d4"
          }
        ],
        "responses": {
          "200": {
            "description": "{ tab{id,url,alias,active,audit_id,score,monitor,monitor_email,monitor_checked_at,created_at}, result{audit_id,url,score,summary,counts,issues,fixes,jsonLd,headers,truncated,share_slug,created_at} }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tab": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Aba"
                        }
                      ],
                      "description": "The requested tab."
                    },
                    "result": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/AuditGravado"
                        }
                      ],
                      "description": "The report of the last run; `null` if the tab never ran.",
                      "nullable": true
                    }
                  },
                  "required": [
                    "tab",
                    "result"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No credential, or an invalid one. See this endpoint's auth."
          },
          "404": {
            "description": "The resource does not exist (or is not yours — the API does not tell the two apart on purpose)."
          }
        }
      },
      "patch": {
        "operationId": "watch_tab",
        "summary": "Renames the tab, puts it in focus or turns the daily watch on and off.",
        "description": "With `monitor: true` the page is re-audited once a day and an e-mail goes out when the score drops or a new error/warning appears — never on an improvement. Watching needs an account (the alert has to reach someone) and each account watches a limited number of pages.\nReturns: { ok, tab{id,url,alias,active,audit_id,score,monitor,monitor_email,monitor_checked_at,created_at} }",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ID of the tab to change.",
            "example": "tab_9f3c2b1d7a4e58b0c2d4"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "alias": {
                    "type": "string",
                    "description": "New label of the tab."
                  },
                  "active": {
                    "type": "boolean",
                    "description": "`true` focuses this tab (and unfocuses the other)."
                  },
                  "monitor": {
                    "type": "boolean",
                    "description": "`true` watches the page daily; `false` stops watching it."
                  },
                  "monitor_email": {
                    "type": "string",
                    "description": "Where the alert goes. Empty or `null` uses the account's e-mail."
                  }
                }
              },
              "example": {
                "alias": "new label",
                "active": true,
                "monitor": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ ok, tab{id,url,alias,active,audit_id,score,monitor,monitor_email,monitor_checked_at,created_at} }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "Always `true`."
                    },
                    "tab": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Aba"
                        }
                      ],
                      "description": "The tab with the change applied."
                    }
                  },
                  "required": [
                    "ok",
                    "tab"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "No changeable field in the body, or `monitor_email` is not an e-mail."
          },
          "401": {
            "description": "No credential, or an invalid one. See this endpoint's auth."
          },
          "403": {
            "description": "Watching needs an account: a guest token has no e-mail to be warned at (`account_required`)."
          },
          "404": {
            "description": "The resource does not exist (or is not yours — the API does not tell the two apart on purpose)."
          },
          "409": {
            "description": "The account already watches the maximum number of pages (`monitor_limit`)."
          }
        }
      },
      "delete": {
        "operationId": "delete_api_tabs_by_id",
        "summary": "Closes the tab. Its audit history keeps existing.",
        "description": "Returns: { ok }",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ID of the tab to close.",
            "example": "tab_9f3c2b1d7a4e58b0c2d4"
          }
        ],
        "responses": {
          "200": {
            "description": "{ ok }",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "description": "No credential, or an invalid one. See this endpoint's auth."
          },
          "404": {
            "description": "The resource does not exist (or is not yours — the API does not tell the two apart on purpose)."
          }
        }
      }
    },
    "/api/tabs/{id}/run": {
      "post": {
        "operationId": "run_tab",
        "summary": "Re-audits the tab's URL and stores a new report.",
        "description": "Consumes the same daily allowance as `POST /api/audit` — past it, 402 with `accepts[]`.\nReturns: { ok, tab{id,url,alias,active,audit_id,score,monitor,monitor_email,monitor_checked_at,created_at}, gate{ip,now,configured,free_allowance,free_remaining,verified_until,needs_verification,sitekey}, result{audit_id,url,score,summary,counts,issues,fixes,jsonLd,headers,truncated,share_slug,created_at} }",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ID of the tab to re-audit.",
            "example": "tab_9f3c2b1d7a4e58b0c2d4"
          }
        ],
        "responses": {
          "200": {
            "description": "{ ok, tab{id,url,alias,active,audit_id,score,monitor,monitor_email,monitor_checked_at,created_at}, gate{ip,now,configured,free_allowance,free_remaining,verified_until,needs_verification,sitekey}, result{audit_id,url,score,summary,counts,issues,fixes,jsonLd,headers,truncated,share_slug,created_at} }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "Always `true`."
                    },
                    "tab": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Aba"
                        }
                      ],
                      "description": "The tab with the new run's score."
                    },
                    "gate": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Gate"
                        }
                      ],
                      "description": "How much of the allowance is left after this run."
                    },
                    "result": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/AuditGravado"
                        }
                      ],
                      "description": "The report just stored."
                    }
                  },
                  "required": [
                    "ok",
                    "tab",
                    "gate",
                    "result"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No credential, or an invalid one. See this endpoint's auth."
          },
          "402": {
            "description": "Quota exceeded. The response carries `accepts[]` (x402, USDC on Base): pay and repeat the same call with `X-PAYMENT`."
          },
          "404": {
            "description": "The resource does not exist (or is not yours — the API does not tell the two apart on purpose)."
          }
        }
      }
    },
    "/api/tabs/{id}/history": {
      "get": {
        "operationId": "tab_history",
        "summary": "Previous runs of that tab and what changed between each one and the one before it.",
        "description": "Every run has always been kept; this is where you read the series. Each entry carries the score, the counts and a `change` with the point delta and the findings that appeared (`broke`) or disappeared (`fixed`) since the previous run — compared by finding code, never by message. Runs older than the watch feature are matched by URL.\nReturns: { tab{id,url,alias,active,audit_id,score,monitor,monitor_email,monitor_checked_at,created_at}, runs[{audit_id,score,counts,created_at,change,shared,api}], limit }",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ID of the tab whose runs you want.",
            "example": "tab_9f3c2b1d7a4e58b0c2d4"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "How many runs to bring, newest first. Default 20, maximum 100."
          }
        ],
        "responses": {
          "200": {
            "description": "{ tab{id,url,alias,active,audit_id,score,monitor,monitor_email,monitor_checked_at,created_at}, runs[{audit_id,score,counts,created_at,change,shared,api}], limit }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tab": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Aba"
                        }
                      ],
                      "description": "The tab the runs belong to."
                    },
                    "runs": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/RunHistorico"
                      },
                      "description": "Runs from newest to oldest."
                    },
                    "limit": {
                      "type": "integer",
                      "description": "The limit actually applied."
                    }
                  },
                  "required": [
                    "tab",
                    "runs",
                    "limit"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No credential, or an invalid one. See this endpoint's auth."
          },
          "404": {
            "description": "The resource does not exist (or is not yours — the API does not tell the two apart on purpose)."
          }
        }
      }
    },
    "/api/gate": {
      "get": {
        "operationId": "get_api_gate",
        "summary": "How many free audits remain for this IP and whether Turnstile is about to be required.",
        "description": "Check before spending a call: it is the number IN FORCE, not the allowance in the documentation.\nReturns: { ip, now, configured, free_allowance, free_remaining, verified_until, needs_verification, sitekey }",
        "security": [],
        "responses": {
          "200": {
            "description": "{ ip, now, configured, free_allowance, free_remaining, verified_until, needs_verification, sitekey }",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Gate"
                }
              }
            }
          }
        }
      }
    },
    "/api/billing": {
      "get": {
        "operationId": "billing",
        "summary": "Tab allowance, prices, full x402 configuration and the state of the trial.",
        "description": "Returns: { provider, mode, network, chain_id, pay_to, homolog, dev, dev_gate, gratis?, facilitator, asset, asset_address, faucet, wallets, product, free_max_tabs, prices{extra_tab_usd,contact_agent_usd}, usage{tabs,free_slots_left}, trial{days,active,days_left?,ends_at} }",
        "security": [],
        "responses": {
          "200": {
            "description": "{ provider, mode, network, chain_id, pay_to, homolog, dev, dev_gate, gratis?, facilitator, asset, asset_address, faucet, wallets, product, free_max_tabs, prices{extra_tab_usd,contact_agent_usd}, usage{tabs,free_slots_left}, trial{days,active,days_left?,ends_at} }",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Billing"
                }
              }
            }
          }
        }
      }
    },
    "/api/me": {
      "get": {
        "operationId": "get_api_me",
        "summary": "The session's account, its last 50 audits and the state of the trial.",
        "description": "The account is the global account you sign in to at `/conta/global`, the same in every product; `user.id` is its id, which owns the tabs and audits here. There is no activation step.\nReturns: { user{id,email}, profile, audits[{audit_id,url,score,summary,counts,issues,fixes,jsonLd,headers,truncated,share_slug,created_at}], trial{days,active,days_left?,ends_at} }",
        "security": [
          {
            "globalAccount": []
          }
        ],
        "responses": {
          "200": {
            "description": "{ user{id,email}, profile, audits[{audit_id,url,score,summary,counts,issues,fixes,jsonLd,headers,truncated,share_slug,created_at}], trial{days,active,days_left?,ends_at} }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "user": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Conta"
                        }
                      ],
                      "description": "The person who owns the session."
                    },
                    "profile": {
                      "type": "object",
                      "description": "Global profile: `name`, `locale`, `timeZone`, `theme`, `revision`."
                    },
                    "audits": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AuditGravado"
                      },
                      "description": "The account's 50 most recent audits."
                    },
                    "trial": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Trial"
                        }
                      ],
                      "description": "The account's trial: how many days, whether active and when it ends."
                    }
                  },
                  "required": [
                    "user",
                    "profile",
                    "audits",
                    "trial"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "invalid_session"
          },
          "503": {
            "description": "auth_unavailable"
          }
        }
      }
    },
    "/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 }",
        "security": [],
        "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"
          }
        }
      }
    },
    "/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}}",
        "security": [
          {
            "globalAccount": []
          }
        ],
        "responses": {
          "200": {
            "description": "{profile:{name,locale,timeZone,theme,revision}}"
          },
          "401": {
            "description": "invalid_session"
          },
          "503": {
            "description": "auth_unavailable"
          }
        }
      }
    },
    "/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",
        "security": [
          {
            "globalAccount": []
          }
        ],
        "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"
          }
        }
      }
    },
    "/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 }",
        "security": [
          {
            "globalAccount": []
          }
        ],
        "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"
          }
        }
      }
    },
    "/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 }",
        "security": [
          {
            "globalAccount": []
          }
        ],
        "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"
          }
        }
      }
    },
    "/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 }",
        "security": [
          {
            "globalAccount": []
          }
        ],
        "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"
          }
        }
      }
    },
    "/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 }",
        "security": [
          {
            "globalAccount": []
          }
        ],
        "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"
          }
        }
      }
    },
    "/api/auth/claim": {
      "post": {
        "operationId": "post_api_auth_claim",
        "summary": "Moves what the guest created to the signed-in account: tabs and audits.",
        "description": "Bootstrap/CSRF of this browser required; the page does it right after sign-in. Only what the guest still owns moves, in one transaction, and anything that collides with what the account already has stays with the guest. What the guest bought moves too. An old unsigned token that owns nothing here is refused. Repeating it is harmless (moves zero).\nReturns: { ok, claimed }",
        "security": [
          {
            "globalAccount": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "guest_token": {
                    "type": "string",
                    "description": "Guest `pa_…` of this browser."
                  }
                },
                "required": [
                  "guest_token"
                ]
              },
              "example": {
                "guest_token": "pa_…"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ ok, claimed }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "Whether the guest was recognized and moved."
                    },
                    "claimed": {
                      "type": "object",
                      "description": "`product.movidos` (rows moved, per table), `product.apagados` (guest duplicates dropped) and `product.direitos` (purchases moved)."
                    }
                  },
                  "required": [
                    "ok",
                    "claimed"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "invalid_product_claim / invalid_body"
          },
          "401": {
            "description": "invalid_session"
          },
          "403": {
            "description": "invalid_origin / invalid_csrf"
          },
          "409": {
            "description": "unknown_guest (em `claimed.reason` / in `claimed.reason`)"
          },
          "503": {
            "description": "product_claim_pending / auth_unavailable"
          }
        }
      }
    },
    "/api/contact": {
      "post": {
        "operationId": "contact",
        "summary": "Talks to support: a human solves Turnstile, an agent pays $0.10 in x402.",
        "description": "Without a captcha in the body the request is treated as an agent: 402 until paid. The first agent message is free; after that the backoff is 60s doubling up to a 1-hour cap, announced in `Retry-After`.\nReturns: { ok, path }",
        "security": [],
        "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": "…",
                "email": "a@example.com",
                "message": "…",
                "cf_turnstile_response": "(human)"
              }
            }
          }
        },
        "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`."
          }
        }
      }
    },
    "/api/visit": {
      "post": {
        "operationId": "post_api_visit",
        "summary": "Ping from the interface that increments the day's visits. Agents need not call it.",
        "description": "Smoke does not count: `X-MM-Smoke`, User-Agent `mm-smoke` or `smoke: true` in the body come in as `counted: false`.\nReturns: { ok, counted, reason? }",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "p": {
                    "type": "string",
                    "description": "Path of the visited page."
                  },
                  "smoke": {
                    "type": "boolean",
                    "description": "`true` marks the call as a test and it does not enter the count."
                  }
                }
              },
              "example": {
                "p": "/"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ ok, counted, reason? }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "Always `true`."
                    },
                    "counted": {
                      "type": "boolean",
                      "description": "Whether the visit entered the day's count."
                    },
                    "reason": {
                      "type": "string",
                      "description": "Why it did not count, when `counted` is `false`."
                    }
                  },
                  "required": [
                    "ok",
                    "counted"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/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.",
        "security": [],
        "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.",
        "security": [],
        "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/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? }",
        "security": [],
        "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 }",
        "security": [],
        "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? }",
        "security": [],
        "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 `{}`.",
        "security": [],
        "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 }",
        "security": [],
        "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/metrics": {
      "get": {
        "operationId": "get_api_metrics",
        "summary": "Metrics of the last 7 days and the most frequent findings across audits. With the operator token, includes payments.",
        "description": "Without credentials it returns visits, usage and accounts. With `METRICS_TOKEN` as Bearer it adds `payments` — and only on Base mainnet, because staging numbers on a finance panel mislead.\nReturns: { app, today, today_visits, today_contacts?, days, usage, accounts, financeiro?, payments?, achados }",
        "security": [],
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "`Bearer <METRICS_TOKEN>` to include the finance block."
          }
        ],
        "responses": {
          "200": {
            "description": "{ app, today, today_visits, today_contacts?, days, usage, accounts, financeiro?, payments?, achados }",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Metricas"
                }
              }
            }
          }
        }
      }
    },
    "/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 }",
        "security": [],
        "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 }",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "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/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 }",
        "security": [],
        "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."
          }
        }
      }
    }
  }
}