{
  "openapi": "3.1.0",
  "info": {
    "title": "ako.tools API",
    "version": "1.0.0",
    "description": "ako.tools is Ako's home for MCP tools; the AI visibility audit is the first. OAuth 2.1 with PKCE is the preferred MCP connection. Resource-bound access tokens also authorize REST. Existing API keys and enrollment remain supported. Create brand profiles, maintain stable tracked questions, run repeatable AI visibility audits and retrieve evidence-backed results. Account limits are shared across REST and MCP. Work is paid from prepaid credit shared by the people and agents on an account. Only work that succeeds is charged: a failed call or audit costs the account nothing. A paid operation the account cannot cover returns 402 insufficient_credits with the amount required. Every response carries an X-Request-Id header: the value of the X-Request-Id header the caller sent (8 to 128 letters, digits, dots, underscores, colons or hyphens), otherwise one assigned by the service. Error bodies repeat it as requestId. Quote it when reporting a problem; it identifies the request, the work it queued and every model call made for it."
  },
  "servers": [
    {
      "url": "https://api.ako.tools"
    },
    {
      "url": "https://api.buyeros.ai",
      "description": "The earlier host. It keeps serving the same API, MCP and OAuth for connections and tokens made there; new connections use https://api.ako.tools."
    }
  ],
  "x-usage-limits": {
    "windowPolicy": "Fixed windows aligned to UTC; settings may override defaults.",
    "sharedAcross": "REST and MCP by account; enrollment creation by requester IP, polling by enrollment.",
    "defaults": {
      "readsPerMinute": 60,
      "writesPerMinute": 30,
      "auditsPerHour": 5,
      "auditsPerDay": 10,
      "activeAudits": 1,
      "profilesPerHour": 5,
      "questionGenerationsPerHour": 5,
      "enrollmentsPerHour": 10,
      "enrollmentPollsPerMinute": 6
    },
    "errorCodes": [
      "rate_limited",
      "concurrency_limit",
      "capacity_limited",
      "insufficient_credits"
    ]
  },
  "tags": [
    {
      "name": "Enrollment"
    },
    {
      "name": "Brands"
    },
    {
      "name": "Questions"
    },
    {
      "name": "Audits"
    },
    {
      "name": "Technical audits"
    },
    {
      "name": "Agent readiness audits"
    },
    {
      "name": "Billing"
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "operationId": "getHealth",
        "responses": {
          "200": {
            "description": "Healthy"
          }
        }
      }
    },
    "/v1/enrollments": {
      "post": {
        "operationId": "startEnrollment",
        "description": "Creating an enrollment sends no email. Share the returned claimUrl as a clickable link in the current conversation. The user opens it, signs in (with a code emailed to them, or Google), then clicks Approve agent access. If already signed in, they can approve directly. Keep pollToken private and save enrollmentId and pollToken in persistent private storage before sharing the link; later runs can resume the same request. Wait for approval with GET /v1/enrollments/{id}?wait=25, which returns as soon as the user approves. The response includes nextSteps, which lists what to do, in order. Do not tell the user to check email before they enter their address on that page.",
        "tags": [
          "Enrollment"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnrollmentInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Pending enrollment created. No email sent; share claimUrl with the user.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentCreated"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/enrollments/{id}": {
      "get": {
        "operationId": "getEnrollmentStatus",
        "tags": [
          "Enrollment"
        ],
        "security": [
          {
            "enrollmentToken": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "name": "wait",
            "in": "query",
            "description": "Hold the request for up to this many seconds until the user approves or the link expires, so the agent need not poll. The wait uses no poll allowance; the response that returns uses one. Use 25 while waiting for approval.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 25,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Enrollment status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "enrollmentId",
                    "status"
                  ],
                  "properties": {
                    "enrollmentId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "approved",
                        "consumed",
                        "expired"
                      ]
                    },
                    "agentToken": {
                      "type": "string",
                      "description": "Present for approved active credentials within the recovery window. Store privately. Do not stop polling merely because status is consumed."
                    },
                    "recoveryUntil": {
                      "type": "string",
                      "format": "date-time",
                      "description": "24 hours after approval; absent for pending requests."
                    },
                    "pollUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "nextStep": {
                      "type": "string",
                      "description": "What to do now, written for the agent."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Resume with the same private pollToken. Credentials are returned repeatedly for 24 hours after approval, including consumed status. Historical consumed credentials are rotated on recovery, invalidating the lost key. Revoked credentials are never returned. Persist enrollmentId/pollToken across agent runs. Prefer saved MCP OAuth connections when supported. Add ?wait=25 to hold the request until the user approves, instead of polling."
      }
    },
    "/v1/brands": {
      "post": {
        "operationId": "createBrand",
        "tags": [
          "Brands"
        ],
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:create"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BrandInput"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Brand accepted for profile research",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Brand"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientCredits"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "get": {
        "operationId": "listBrands",
        "tags": [
          "Brands"
        ],
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Brand list"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/brands/{brandId}": {
      "get": {
        "operationId": "getBrand",
        "tags": [
          "Brands"
        ],
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/BrandId"
          }
        ],
        "responses": {
          "200": {
            "description": "Brand",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Brand"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "updateBrand",
        "tags": [
          "Brands"
        ],
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:create"
            ]
          }
        ],
        "summary": "Correct the brand's market or profile",
        "description": "Corrects what ako.tools knows about the brand. country and language set its market, the default for its questions, audits and estimates; description and offers correct what it understood the business does (offers is the full list and replaces the current one). Pass any of them. A changed market needs its own questions, so changing it queues question generation for that market, charged like POST /v1/brands/{brandId}/questions/generate and free when the market already has questions; the result is returned as questionGeneration. If generation cannot start (for example insufficient_credits), the market is still saved and questionGeneration carries the error; retry with POST /v1/brands/{brandId}/questions/generate. Tracked questions and past audits are unchanged, and POST /v1/brands/{brandId}/refresh rewrites the description and offers from the website. Use it when the market or profile shown on the brand is not right. Confirm a market change with the person first, since it writes and charges for a new set of questions; a market written with other capitals is the same market and changes nothing.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BrandId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BrandUpdateInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated brand",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrandUpdate"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/brands/{brandId}/refresh": {
      "post": {
        "operationId": "refreshBrandProfile",
        "tags": [
          "Brands"
        ],
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:create"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/BrandId"
          }
        ],
        "responses": {
          "202": {
            "description": "Profile refresh queued"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientCredits"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/brands/{brandId}/questions/generate": {
      "post": {
        "operationId": "generateBrandQuestions",
        "tags": [
          "Questions"
        ],
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:create"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/BrandId"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MarketInput"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Question generation queued or existing set returned"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientCredits"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/brands/{brandId}/questions": {
      "get": {
        "operationId": "listBrandQuestions",
        "tags": [
          "Questions"
        ],
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/BrandId"
          },
          {
            "name": "active",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tracked question list"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "addBrandQuestion",
        "tags": [
          "Questions"
        ],
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:create"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/BrandId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuestionInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Tracked question created"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/brands/{brandId}/questions/{questionId}": {
      "patch": {
        "operationId": "setBrandQuestionActive",
        "tags": [
          "Questions"
        ],
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:create"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/BrandId"
          },
          {
            "$ref": "#/components/parameters/QuestionId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "active": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "active"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Question state updated"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/brands/{brandId}/audits": {
      "post": {
        "operationId": "runBrandAudit",
        "tags": [
          "Audits"
        ],
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:create"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/BrandId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuditOptions"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Audit queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Audit"
                }
              }
            }
          },
          "402": {
            "$ref": "#/components/responses/InsufficientCredits"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/audits": {
      "post": {
        "operationId": "runAudit",
        "tags": [
          "Audits"
        ],
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:create"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuditInput"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Audit queued"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientCredits"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "get": {
        "operationId": "listAudits",
        "tags": [
          "Audits"
        ],
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "brandId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Audit list"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/audits/{id}": {
      "get": {
        "operationId": "getAudit",
        "tags": [
          "Audits"
        ],
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "200": {
            "description": "Audit status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Audit"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/audits/{id}/results": {
      "get": {
        "operationId": "getAuditResults",
        "tags": [
          "Audits"
        ],
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "200": {
            "description": "Scores computed from the audit’s answers: rates overall, by engine and by question type, the other brands the answers offered the buyer (namedBrands, the top 20 by share, with namedBrandCount for all) and the cited sites, ranked by share, a table of every tracked question with what each engine said, and the newest report. Available once the audit has finished and has at least one answer."
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/audits/{id}/runs": {
      "get": {
        "operationId": "getAuditRuns",
        "tags": [
          "Audits"
        ],
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "200": {
            "description": "Every answer with the sites it cited and how it was judged: whether it mentioned or recommended the brand, the other brands it offered the buyer (namedBrands) and the reasons it gave. Raw model payloads, provider usage and cost are never included."
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/audits/{id}/cancel": {
      "post": {
        "operationId": "cancelAudit",
        "tags": [
          "Audits"
        ],
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:cancel"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "200": {
            "description": "Cancellation requested"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/technical-audits": {
      "post": {
        "operationId": "runTechnicalAudit",
        "tags": [
          "Technical audits"
        ],
        "description": "Queue a public-domain technical eligibility audit. Discover from sitemap XML and raw HTML links, up to maxPages (default 50, maximum 500). Browser coverage is a bounded key-page/template sample of up to maxRenderedPages (default 10, maximum 50). No paid model calls; browser usage applies. Shared REST/MCP audit scopes and separate technical admission quotas apply.",
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:create"
            ]
          }
        ],
        "responses": {
          "202": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TechnicalAudit"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "$ref": "#/components/responses/InsufficientCredits"
          },
          "403": {
            "description": "Insufficient scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found or not owned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Results pending or idempotency key conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "description": "Internal error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TechnicalAuditInput"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listTechnicalAudits",
        "tags": [
          "Technical audits"
        ],
        "description": "List owned technical audits.",
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "audits": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TechnicalAudit"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found or not owned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Results pending or idempotency key conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "brandId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    },
    "/v1/technical-audits/{id}": {
      "get": {
        "operationId": "getTechnicalAudit",
        "tags": [
          "Technical audits"
        ],
        "description": "Read status. Results are immutable on completion.",
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TechnicalAudit"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found or not owned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Results pending or idempotency key conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ]
      }
    },
    "/v1/technical-audits/{id}/results": {
      "get": {
        "operationId": "getTechnicalResults",
        "tags": [
          "Technical audits"
        ],
        "description": "Read immutable technical eligibility findings. For schemaVersion 2, page evidence and checks are paginated; site checks and full grouped findings accompany each page. Unmeasured or failed rendering is unknown.",
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TechnicalResults"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found or not owned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Results pending or idempotency key conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          }
        ]
      }
    },
    "/v1/technical-audits/{id}/cancel": {
      "post": {
        "operationId": "cancelTechnicalAudit",
        "tags": [
          "Technical audits"
        ],
        "description": "Cancel queued or running work. In-flight network requests may finish; results are discarded. Terminal states remain unchanged.",
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:cancel"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TechnicalAudit"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found or not owned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Results pending or idempotency key conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ]
      }
    },
    "/v1/agent-readiness-audits": {
      "post": {
        "operationId": "runAgentReadinessAudit",
        "tags": [
          "Agent readiness audits"
        ],
        "description": "Run the whole readiness assessment of a website in one asynchronous operation: create or reuse the brand, run the technical audit, generate tracked questions automatically (unreviewed) and run the AI visibility audit. Supply website, brandId or both. The market is the one the brand's site serves by default; country and language narrow the visibility audit to one market (the technical half is market-independent). Returns 202; poll the status, then read the results. Spend is capped by visibility.maxCostUsd and service limits. One active readiness audit per account. Brand-profile failure after its output retry fails the whole parent and cancels child work; no visibility audit starts. A known profile failure prevents technical dispatch.",
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:create"
            ]
          }
        ],
        "responses": {
          "202": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentReadinessAudit"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "$ref": "#/components/responses/InsufficientCredits"
          },
          "403": {
            "description": "Insufficient scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found or not owned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Results pending or idempotency key conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "description": "Internal error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentReadinessAuditInput"
              }
            }
          }
        },
        "summary": "Run an agent readiness audit"
      },
      "get": {
        "operationId": "listAgentReadinessAudits",
        "tags": [
          "Agent readiness audits"
        ],
        "description": "List owned agent readiness audits, newest first, optionally for one brand.",
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "audits"
                  ],
                  "properties": {
                    "audits": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AgentReadinessAudit"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found or not owned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Results pending or idempotency key conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "brandId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "summary": "List agent readiness audits"
      }
    },
    "/v1/agent-readiness-audits/{id}": {
      "get": {
        "operationId": "getAgentReadinessAudit",
        "tags": [
          "Agent readiness audits"
        ],
        "description": "Read status, stage and the status of the technical and visibility halves.",
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentReadinessAudit"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found or not owned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Results pending or idempotency key conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "summary": "Get agent readiness audit status"
      }
    },
    "/v1/agent-readiness-audits/{id}/results": {
      "get": {
        "operationId": "getAgentReadinessResults",
        "tags": [
          "Agent readiness audits"
        ],
        "description": "Read the combined data once the audit is terminal: brand, technical results (first page of page evidence), visibility results, the questions used, market, cost and limitations. Produces no score or interpretation. Returns 409 until terminal. Costs include known failed/retried request charges. unknownRequestCount counts recorded requests without known charges; complete=false also covers historical fallback. Incomplete totals are not complete bills.",
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentReadinessResults"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found or not owned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Results pending or idempotency key conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "summary": "Get agent readiness results"
      }
    },
    "/v1/agent-readiness-audits/{id}/cancel": {
      "post": {
        "operationId": "cancelAgentReadinessAudit",
        "tags": [
          "Agent readiness audits"
        ],
        "description": "Cancel a queued or running audit and request cancellation of its technical and visibility audits.",
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:cancel"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentReadinessAudit"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found or not owned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Results pending or idempotency key conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "summary": "Cancel an agent readiness audit"
      }
    },
    "/v1/billing": {
      "get": {
        "operationId": "getBilling",
        "tags": [
          "Billing"
        ],
        "summary": "Credit balance and price list",
        "description": "The account balance and what each kind of work costs. The first read of a new account grants its free credit. MCP: get_credit_balance.",
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Balance and pricing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditBalance"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/billing/transactions": {
      "get": {
        "operationId": "listCreditTransactions",
        "tags": [
          "Billing"
        ],
        "summary": "Credit history",
        "description": "Top-ups, free credit, charges and refunds, newest first. Model calls are rolled up: one line per audit and one per brand setup, never per call or per model. MCP: list_credit_transactions.",
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "before",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of transactions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "transactions": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CreditTransaction"
                      }
                    },
                    "nextBefore": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time",
                      "description": "Pass as before to read the next page; null on the last page."
                    }
                  },
                  "required": [
                    "transactions",
                    "nextBefore"
                  ]
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/billing/top-ups": {
      "post": {
        "operationId": "createTopUp",
        "tags": [
          "Billing"
        ],
        "summary": "Start a payment to add credit",
        "description": "Returns a Stripe Checkout link for a person to open and pay. Credit is added when Stripe confirms the payment. Answers 503 payments_unavailable when payments are not configured. MCP: create_credit_top_up.",
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:create"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TopUpInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Checkout created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TopUp"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "Payments are not configured, or the payment provider could not start the payment (502).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/stripe-webhook": {
      "post": {
        "operationId": "stripeWebhook",
        "tags": [
          "Billing"
        ],
        "summary": "Stripe payment events",
        "description": "Called by Stripe, not by clients. The body is verified against the Stripe-Signature header, and a paid checkout.session.completed or checkout.session.async_payment_succeeded event adds its amount to the account named in client_reference_id exactly once per session. Any other event is acknowledged and ignored.",
        "security": [],
        "parameters": [
          {
            "name": "Stripe-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Event received",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "received": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "received"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/enrollments/{id}/refresh": {
      "post": {
        "operationId": "refreshEnrollment",
        "tags": [
          "Enrollment"
        ],
        "summary": "Get a new approval link",
        "description": "For an enrollment whose one-hour link expired or was lost: returns a new claimUrl and code and keeps the same enrollmentId and pollToken, so the agent does not start over. Only the holder of the pollToken can ask, and only while nobody has approved the enrollment (409 otherwise). MCP: refresh_signup_link.",
        "security": [
          {
            "enrollmentToken": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "200": {
            "description": "A new link",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentRefreshed"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/audits/estimate": {
      "post": {
        "operationId": "estimateAudit",
        "tags": [
          "Audits"
        ],
        "summary": "Estimate an audit",
        "description": "Free. Takes the same input as POST /v1/audits (without an Idempotency-Key) and returns what the audit would cost, without starting it. Call it before running an audit, and add credit first when canStart is false. MCP: estimate_visibility_audit.",
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:read"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuditInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The estimate",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Estimate"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/agent-readiness-audits/estimate": {
      "post": {
        "operationId": "estimateAgentReadinessAudit",
        "tags": [
          "Agent readiness audits"
        ],
        "summary": "Estimate an agent readiness audit",
        "description": "Free. Takes the same input as POST /v1/agent-readiness-audits (without an Idempotency-Key) and returns what the audit would cost, without starting it. MCP: estimate_agent_readiness_audit.",
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:read"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentReadinessAuditInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The estimate",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Estimate"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/audits/{id}/report": {
      "post": {
        "operationId": "generateAuditReport",
        "tags": [
          "Audits"
        ],
        "summary": "Write the verdict and recommended actions for a finished audit",
        "description": "Writes a new version of the report in the background. Read it with the audit’s results or GET /v1/brands/{brandId}/visibility; report.status is pending until it is ready. Use it for an audit started without generateReport, or whose report failed or should be written again. Only one report is written at a time per audit. Charged to the account like other work, and only if it succeeds.",
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:create"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "202": {
            "description": "Report requested",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "auditId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "report": {
                      "$ref": "#/components/schemas/Report"
                    }
                  },
                  "required": [
                    "auditId",
                    "report"
                  ]
                }
              }
            }
          },
          "402": {
            "$ref": "#/components/responses/InsufficientCredits"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/brands/{brandId}/visibility": {
      "get": {
        "operationId": "getBrandVisibility",
        "tags": [
          "Brands"
        ],
        "summary": "How a brand appears in AI answers, in one call",
        "description": "The summary of the brand’s latest finished audit that has answers, or the audit named by auditId: rates overall, by engine and by question type; the other brands the answers offered the buyer (namedBrands, the top 20, with namedBrandCount for all) and the cited sites, with their share of answers; a table of every tracked question; the newest report (a verdict and recommended actions); the headline rates of the last 10 audits; and inProgress when an audit is running. audit is null when no audit has answers yet. Raw answers are in GET /v1/audits/{id}/runs.",
        "security": [
          {
            "agentToken": []
          },
          {
            "oauth": [
              "audits:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/BrandId"
          },
          {
            "name": "auditId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Brand visibility. For a preview audit, upgrade holds the full audit's questions, estimatedCostUsd, requiredCreditUsd, availableCreditUsd and canStart; it is null otherwise."
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "oauth": {
        "type": "oauth2",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://clerk.ako.tools/oauth/authorize",
            "tokenUrl": "https://clerk.ako.tools/oauth/token",
            "refreshUrl": "https://clerk.ako.tools/oauth/token",
            "scopes": {
              "openid": "Sign in",
              "email": "The account's email address",
              "offline_access": "Renew access without signing in each time",
              "audits:read": "Read brands, questions, audits and results (granted to every OAuth connection)",
              "audits:create": "Create brands and questions and run audits (granted to every OAuth connection)",
              "audits:cancel": "Cancel audits (granted to every OAuth connection)"
            }
          }
        },
        "description": "Clerk is the authorization server; read it from /.well-known/oauth-protected-resource on the API host. Use PKCE S256 and resource=https://api.ako.tools/mcp (or resource=https://api.buyeros.ai/mcp on that host), and request openid email offline_access. A token is accepted only by the host named in its resource. An OAuth connection has full access to the account. Add the MCP URL to an OAuth-capable client; the client discovers authorization automatically."
      },
      "agentToken": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "br_agent_\u2026"
      },
      "enrollmentToken": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "br_enroll_\u2026"
      }
    },
    "parameters": {
      "Id": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "BrandId": {
        "name": "brandId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "QuestionId": {
        "name": "questionId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 20
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 8
        }
      }
    },
    "responses": {
      "RateLimited": {
        "description": "Account request limit, audit concurrency limit, or the service’s capacity is temporarily limited. Do not retry before retryAfterSeconds. No new paid work was accepted.",
        "headers": {
          "X-Request-Id": {
            "description": "The request id: the caller’s X-Request-Id when one was sent, otherwise assigned by the service. Also present on successful responses.",
            "schema": {
              "type": "string"
            }
          },
          "Retry-After": {
            "description": "Seconds until retry.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error": {
        "description": "Machine-readable error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        },
        "headers": {
          "X-Request-Id": {
            "description": "The request id: the caller’s X-Request-Id when one was sent, otherwise assigned by the service. Also present on successful responses.",
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "InsufficientCredits": {
        "description": "The account does not have the credit this work needs. Nothing was queued or charged. requiredUsd is what must be available, availableUsd what is, and credit can be added with POST /v1/billing/top-ups. An audit already running when credit runs out stops with the results it has: status partial and error code insufficient_credits.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        },
        "headers": {
          "X-Request-Id": {
            "description": "The request id: the caller’s X-Request-Id when one was sent, otherwise assigned by the service. Also present on successful responses.",
            "schema": {
              "type": "string"
            }
          }
        }
      }
    },
    "schemas": {
      "EnrollmentCreated": {
        "type": "object",
        "required": [
          "enrollmentId",
          "claimUrl",
          "code",
          "pollToken",
          "expiresAt",
          "pollUrl",
          "nextSteps"
        ],
        "properties": {
          "enrollmentId": {
            "type": "string",
            "format": "uuid"
          },
          "claimUrl": {
            "type": "string",
            "format": "uri",
            "description": "Share this clickable approval link with the user in the current conversation. No email has been sent."
          },
          "code": {
            "type": "string",
            "description": "Human-readable approval code, already included in claimUrl."
          },
          "pollToken": {
            "type": "string",
            "description": "Private enrollment polling credential. Retain securely; do not share with the user."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Enrollment expires one hour after creation."
          },
          "pollUrl": {
            "type": "string",
            "format": "uri",
            "description": "Where to read this enrollment’s status."
          },
          "pollEveryMs": {
            "type": "integer",
            "description": "Minimum time between plain polls. Prefer waiting with ?wait."
          },
          "maxWaitSeconds": {
            "type": "integer",
            "description": "The longest ?wait a status request accepts."
          },
          "nextSteps": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What to do next, in order, written for the agent. Follow these to finish setup."
          }
        }
      },
      "EnrollmentInput": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "description": "Optional restriction: only the account with this email can approve the enrollment. It does not send an invitation or sign-in email. Omit unless the user has specified the approving email address."
          },
          "agentName": {
            "type": "string",
            "default": "AI agent"
          },
          "scopes": {
            "type": "array",
            "items": {
              "enum": [
                "audits:create",
                "audits:read",
                "audits:cancel"
              ]
            }
          }
        }
      },
      "BrandInput": {
        "type": "object",
        "properties": {
          "website": {
            "type": "string",
            "format": "uri"
          },
          "country": {
            "type": "string",
            "description": "Market the brand is researched and audited for. When omitted, the brand takes the market its site serves once profile research has read it (shown as inferredMarket), which may be Global."
          },
          "language": {
            "type": "string",
            "description": "Language of the brand's market. When omitted, the language its site serves."
          }
        },
        "required": [
          "website"
        ]
      },
      "Brand": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "website": {
            "type": "string",
            "format": "uri"
          },
          "profileStatus": {
            "enum": [
              "pending",
              "queued",
              "crawling",
              "planning",
              "ready",
              "failed"
            ]
          },
          "questionStatus": {
            "enum": [
              "not_started",
              "queued",
              "planning",
              "ready",
              "failed"
            ]
          },
          "activeQuestionCount": {
            "type": "integer"
          },
          "profile": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true
          },
          "inferredMarket": {
            "type": [
              "object",
              "null"
            ],
            "description": "Country and language the site appears to serve, read from its pages. Informational; the brand market is the one it was created for.",
            "properties": {
              "country": {
                "type": "string"
              },
              "language": {
                "type": "string"
              }
            }
          }
        },
        "required": [
          "id",
          "website",
          "profileStatus",
          "questionStatus",
          "activeQuestionCount"
        ]
      },
      "MarketInput": {
        "type": "object",
        "properties": {
          "country": {
            "type": "string"
          },
          "language": {
            "type": "string"
          }
        }
      },
      "QuestionInput": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "minLength": 5
          },
          "category": {
            "enum": [
              "discovery",
              "customer_need",
              "purchase_constraint",
              "comparison",
              "branded"
            ]
          },
          "country": {
            "type": "string"
          },
          "language": {
            "type": "string"
          }
        },
        "required": [
          "text",
          "category"
        ]
      },
      "AuditOptions": {
        "type": "object",
        "properties": {
          "country": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "config": {
            "$ref": "#/components/schemas/AuditConfig"
          },
          "generateReport": {
            "type": "boolean",
            "default": false,
            "description": "Also write a verdict and recommended actions when the audit finishes, as part of the audit’s cost. Off by default, except for a preview, which writes one unless this is false. Request them later for a finished audit with POST /v1/audits/{id}/report."
          },
          "preview": {
            "type": "boolean",
            "default": false,
            "description": "A taste of a full audit for a new account: asks three of the brand’s active questions (discovery, comparison and a customer need where possible) of every engine in config.models (all six by default) and, unless generateReport is false, writes the report. About a fifth of a full audit’s cost. The audit and the brand’s latest results are marked preview, and GET /v1/brands/{brandId}/visibility adds an upgrade offer with the full audit’s estimate."
          }
        }
      },
      "AuditInput": {
        "allOf": [
          {
            "$ref": "#/components/schemas/AuditOptions"
          },
          {
            "type": "object",
            "properties": {
              "brandId": {
                "type": "string",
                "format": "uuid"
              }
            },
            "required": [
              "brandId"
            ]
          }
        ]
      },
      "AuditConfig": {
        "type": "object",
        "properties": {
          "repetitions": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5,
            "default": 1
          },
          "models": {
            "type": "array",
            "minItems": 1,
            "maxItems": 6,
            "items": {
              "type": "string",
              "minLength": 3
            },
            "description": "Replaces the default six-engine panel when supplied. Engines named app/... (app/chatgpt, app/gemini) use the consumer app; every other engine is a search-assisted API response.",
            "default": [
              "app/chatgpt",
              "app/gemini",
              "anthropic/claude-sonnet-5",
              "x-ai/grok-4.7",
              "meta/muse-spark-1.3",
              "perplexity/sonar"
            ]
          },
          "maxCostUsd": {
            "type": "number",
            "exclusiveMinimum": 0,
            "maximum": 100,
            "description": "The most this audit may cost the account. The audit stops with the results it has when it reaches the limit. Defaults to 20% above the audit’s estimate, so normal variation does not cut it short."
          }
        },
        "additionalProperties": false
      },
      "Audit": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "brandId": {
            "type": "string",
            "format": "uuid"
          },
          "website": {
            "type": "string",
            "format": "uri"
          },
          "country": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "status": {
            "enum": [
              "queued",
              "testing",
              "evaluating",
              "completed",
              "partial",
              "cancelled",
              "failed"
            ]
          },
          "progress": {
            "type": "object",
            "additionalProperties": true
          },
          "costUsd": {
            "type": "number",
            "minimum": 0,
            "description": "What this audit has cost the account so far. It grows as calls succeed and never includes work that failed; a run that produces no result is refunded when the audit ends."
          },
          "error": {
            "type": [
              "object",
              "null"
            ]
          },
          "estimatedCostUsd": {
            "type": [
              "number",
              "null"
            ],
            "minimum": 0,
            "description": "What the audit was expected to cost when accepted, from typical call costs for the chosen models. The cost can differ: Gemini and Grok decide how many searches to run, so their calls vary widely. Unless a limit is set in config.maxCostUsd, the audit stops if its cost reaches 20% over this estimate. Null for audits created before credits."
          },
          "preview": {
            "type": "boolean",
            "description": "Whether this was a preview audit of three questions."
          }
        },
        "required": [
          "id",
          "brandId",
          "website",
          "country",
          "language",
          "status",
          "progress",
          "costUsd"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "retryAfterSeconds": {
                "type": "integer",
                "minimum": 1
              },
              "requiredUsd": {
                "type": "number",
                "description": "Present with insufficient_credits: the credit the work needs available before it starts."
              },
              "availableUsd": {
                "type": "number",
                "description": "Present with insufficient_credits: the credit the account has available now."
              },
              "requestId": {
                "type": "string",
                "description": "The request id, also returned in the X-Request-Id response header. Quote it when reporting a problem."
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "TechnicalAuditInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "website": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2048,
            "description": "Public HTTP(S) hostname URL without credentials, custom ports or query parameters. Bare hostnames accepted. Discovery begins at its domain homepage. Optional when brandId is supplied, in which case the brand's website is used."
          },
          "brandId": {
            "type": "string",
            "format": "uuid",
            "description": "Optional owned brand to link the audit to. Must be on the brand's domain (www ignored) when website is also supplied. Unlinked audits remain supported."
          },
          "options": {
            "$ref": "#/components/schemas/TechnicalOptions"
          }
        },
        "anyOf": [
          {
            "required": [
              "website"
            ]
          },
          {
            "required": [
              "brandId"
            ]
          }
        ]
      },
      "TechnicalAudit": {
        "type": "object",
        "required": [
          "id",
          "website",
          "brandId",
          "status",
          "checkerVersion",
          "cancelRequested",
          "createdAt",
          "updatedAt",
          "completedAt",
          "error"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "website": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "testing",
              "completed",
              "partial",
              "failed",
              "cancelled"
            ]
          },
          "checkerVersion": {
            "type": "string"
          },
          "cancelRequested": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "error": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "code": {
                "type": "string"
              }
            }
          },
          "options": {
            "$ref": "#/components/schemas/TechnicalOptions"
          },
          "progress": {
            "type": "object",
            "description": "How far a running audit has got; only what has been reported so far.",
            "properties": {
              "stage": {
                "type": "string"
              },
              "discovered": {
                "type": "integer"
              },
              "processed": {
                "type": "integer"
              },
              "rendered": {
                "type": "integer"
              }
            }
          },
          "brandId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Linked brand, or null for a standalone audit."
          },
          "costUsd": {
            "type": [
              "number",
              "null"
            ],
            "minimum": 0,
            "description": "What the audit cost the account, per page read, once its report is saved. Null until it finishes; a failed audit costs nothing."
          }
        }
      },
      "TechnicalCheck": {
        "type": "object",
        "required": [
          "checkId",
          "url",
          "status",
          "severity",
          "provider",
          "evidence",
          "explanation",
          "suggestedFix"
        ],
        "properties": {
          "checkId": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pass",
              "warn",
              "fail",
              "unknown",
              "not_applicable"
            ]
          },
          "severity": {
            "type": "string",
            "enum": [
              "blocker",
              "high",
              "medium",
              "info"
            ]
          },
          "provider": {
            "type": "string"
          },
          "evidence": {
            "type": "object",
            "additionalProperties": true
          },
          "explanation": {
            "type": "string"
          },
          "suggestedFix": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "TechnicalResults": {
        "type": "object",
        "properties": {
          "auditId": {
            "type": "string",
            "format": "uuid"
          },
          "checkerVersion": {
            "type": "string"
          },
          "website": {
            "type": "string"
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "type": "string",
            "enum": [
              "completed",
              "partial"
            ]
          },
          "options": {
            "$ref": "#/components/schemas/TechnicalOptions"
          },
          "agentConfigVersion": {
            "type": "string"
          },
          "coverage": {
            "type": "object",
            "properties": {
              "discovered": {
                "type": "integer"
              },
              "audited": {
                "type": "integer"
              },
              "rendered": {
                "type": "integer"
              },
              "renderAttempted": {
                "type": "integer"
              },
              "capped": {
                "type": "boolean"
              },
              "sitemapTruncated": {
                "type": "boolean"
              },
              "parityUnmeasured": {
                "type": "integer"
              },
              "skippedByRobots": {
                "type": "integer",
                "description": "Crawl-discovered URLs excluded by robots.txt and therefore not audited."
              }
            },
            "required": [
              "discovered",
              "audited",
              "rendered",
              "renderAttempted",
              "capped",
              "sitemapTruncated",
              "parityUnmeasured",
              "skippedByRobots"
            ]
          },
          "pages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TechnicalPage"
            }
          },
          "checks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TechnicalCheck"
            }
          },
          "findings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TechnicalFinding"
            }
          },
          "providers": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "provider": {
                  "type": "string"
                },
                "version": {
                  "type": "string"
                }
              },
              "required": [
                "provider",
                "version"
              ]
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "pagination": {
            "type": "object",
            "properties": {
              "offset": {
                "type": "integer"
              },
              "limit": {
                "type": "integer"
              },
              "totalPages": {
                "type": "integer"
              },
              "nextOffset": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            },
            "required": [
              "offset",
              "limit",
              "totalPages",
              "nextOffset"
            ]
          }
        },
        "required": [
          "auditId",
          "checkerVersion",
          "website",
          "generatedAt",
          "status",
          "options",
          "agentConfigVersion",
          "coverage",
          "pages",
          "checks",
          "findings",
          "providers",
          "warnings",
          "pagination"
        ],
        "description": "Computed from the audit’s saved pages and checks whenever it is read. Findings group the failed and warned checks across the whole audit; pages and checks are paginated. The thresholds a check used are in its evidence."
      },
      "TechnicalOptions": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "maxPages": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500,
            "default": 50
          },
          "maxRenderedPages": {
            "type": "integer",
            "minimum": 1,
            "maximum": 50,
            "default": 10,
            "description": "Maximum pages rendered in a browser: key pages and one representative page per path template."
          },
          "vertical": {
            "type": "string",
            "enum": [
              "generic",
              "saas",
              "ecommerce",
              "local"
            ],
            "default": "generic"
          }
        }
      },
      "TechnicalFetch": {
        "type": "object",
        "properties": {
          "requestedUrl": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "bytes": {
            "type": "integer"
          },
          "truncated": {
            "type": "boolean"
          },
          "ttfbMs": {
            "type": "number"
          },
          "redirects": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "url": {
                  "type": "string"
                },
                "status": {
                  "type": "integer"
                },
                "location": {
                  "type": "string"
                }
              },
              "required": [
                "url",
                "status",
                "location"
              ]
            }
          },
          "error": {
            "type": "string"
          }
        },
        "required": [
          "requestedUrl",
          "url",
          "status",
          "headers",
          "bytes",
          "truncated",
          "ttfbMs",
          "redirects"
        ]
      },
      "TechnicalExtracted": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "h1": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "canonical": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "words": {
            "type": "integer"
          },
          "excerpt": {
            "type": "string"
          },
          "facts": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "linkCount": {
            "type": "integer"
          },
          "structuredDataBlocks": {
            "type": "integer"
          },
          "description": {
            "type": "string"
          },
          "lang": {
            "type": "string"
          }
        },
        "required": [
          "title",
          "description",
          "lang",
          "h1",
          "canonical",
          "words",
          "excerpt",
          "facts",
          "linkCount",
          "structuredDataBlocks"
        ]
      },
      "TechnicalPage": {
        "type": "object",
        "properties": {
          "requestedUrl": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "enum": [
              "home",
              "sitemap",
              "link"
            ]
          },
          "keyPage": {
            "type": "boolean"
          },
          "fetchedAt": {
            "type": "string",
            "format": "date-time"
          },
          "raw": {
            "$ref": "#/components/schemas/TechnicalFetch"
          },
          "extracted": {
            "$ref": "#/components/schemas/TechnicalExtracted"
          },
          "rendered": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string"
                  },
                  "status": {
                    "type": "integer"
                  },
                  "complete": {
                    "type": "boolean"
                  },
                  "elapsedMs": {
                    "type": "number"
                  },
                  "error": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "extracted": {
                    "$ref": "#/components/schemas/TechnicalExtracted"
                  },
                  "blockedRequests": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "method": {
                          "type": "string"
                        },
                        "url": {
                          "type": "string"
                        },
                        "telemetry": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "method",
                        "url",
                        "telemetry"
                      ]
                    }
                  }
                },
                "required": [
                  "url",
                  "status",
                  "complete",
                  "elapsedMs",
                  "error",
                  "extracted",
                  "blockedRequests"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "artifacts": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Private object keys, not public download URLs; artifacts may expire independently of the report."
          }
        },
        "required": [
          "requestedUrl",
          "url",
          "source",
          "keyPage",
          "fetchedAt",
          "raw",
          "extracted",
          "rendered",
          "artifacts"
        ]
      },
      "TechnicalFinding": {
        "type": "object",
        "properties": {
          "checkId": {
            "type": "string"
          },
          "severity": {
            "type": "string",
            "enum": [
              "blocker",
              "high",
              "medium",
              "info"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "fail",
              "warn"
            ]
          },
          "template": {
            "type": "string"
          },
          "affectedUrlCount": {
            "type": "integer"
          },
          "examples": {
            "type": "array",
            "maxItems": 3,
            "items": {
              "type": "object",
              "properties": {
                "url": {
                  "type": "string"
                },
                "evidence": {
                  "type": "object",
                  "additionalProperties": true
                }
              },
              "required": [
                "url",
                "evidence"
              ]
            }
          },
          "explanation": {
            "type": "string"
          },
          "suggestedFix": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "checkId",
          "severity",
          "status",
          "template",
          "affectedUrlCount",
          "examples",
          "explanation",
          "suggestedFix"
        ]
      },
      "AgentReadinessAuditInput": {
        "type": "object",
        "additionalProperties": false,
        "anyOf": [
          {
            "required": [
              "website"
            ]
          },
          {
            "required": [
              "brandId"
            ]
          }
        ],
        "properties": {
          "website": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2048,
            "description": "Public HTTP(S) hostname URL. Optional when brandId is supplied. A brand is created for it if none exists."
          },
          "brandId": {
            "type": "string",
            "format": "uuid",
            "description": "Owned brand to audit. A supplied website must be on its domain."
          },
          "country": {
            "type": "string",
            "description": "Market for the visibility audit and its questions. Omit for the brand's own market, or, when it has no questions, the one market that does. Does not change the brand profile or the technical audit."
          },
          "language": {
            "type": "string",
            "description": "Language of the market. Omit for the brand's own."
          },
          "technical": {
            "$ref": "#/components/schemas/TechnicalOptions"
          },
          "visibility": {
            "$ref": "#/components/schemas/AuditConfig"
          },
          "refreshProfile": {
            "type": "boolean",
            "default": false,
            "description": "Re-run brand profile research first, even if the brand profile is ready."
          }
        }
      },
      "AgentReadinessAudit": {
        "type": "object",
        "required": [
          "id",
          "website",
          "status",
          "stage",
          "technical",
          "visibility",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "website": {
            "type": "string"
          },
          "brandId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "completed",
              "partial",
              "failed",
              "cancelled"
            ],
            "description": "Profile failure after its output retry fails the parent immediately and cancels active children; terminal parents do not restart after manual profile recovery."
          },
          "stage": {
            "type": "string",
            "enum": [
              "brand",
              "questions",
              "auditing",
              "done"
            ]
          },
          "market": {
            "type": "object",
            "description": "Market as supplied; null means the brand's own.",
            "properties": {
              "country": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "language": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "options": {
            "type": "object",
            "additionalProperties": true
          },
          "technical": {
            "type": "object",
            "required": [
              "auditId",
              "status",
              "error"
            ],
            "properties": {
              "auditId": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uuid"
              },
              "status": {
                "type": "string",
                "description": "Child audit status, \"pending\" before it starts, or \"failed\" when it could not start."
              },
              "error": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "code": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "visibility": {
            "type": "object",
            "required": [
              "auditId",
              "status",
              "error"
            ],
            "properties": {
              "auditId": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uuid"
              },
              "status": {
                "type": "string",
                "description": "Child audit status, \"pending\" before it starts, or \"failed\" when it could not start."
              },
              "error": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "code": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "cancelRequested": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "AgentReadinessResults": {
        "type": "object",
        "required": [
          "auditId",
          "schemaVersion",
          "status",
          "market",
          "technical",
          "visibility",
          "costUsd",
          "limitations"
        ],
        "properties": {
          "auditId": {
            "type": "string",
            "format": "uuid"
          },
          "schemaVersion": {
            "type": "integer",
            "const": 1
          },
          "status": {
            "type": "string",
            "enum": [
              "completed",
              "partial",
              "failed",
              "cancelled"
            ]
          },
          "website": {
            "type": "string"
          },
          "market": {
            "type": "object",
            "properties": {
              "country": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "language": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "source": {
                "type": "string",
                "enum": [
                  "supplied",
                  "brand"
                ]
              }
            }
          },
          "brand": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Brand"
              },
              {
                "type": "null"
              }
            ]
          },
          "technical": {
            "type": "object",
            "properties": {
              "auditId": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "status": {
                "type": "string"
              },
              "error": {
                "type": [
                  "object",
                  "null"
                ]
              },
              "results": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/TechnicalResults"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          "visibility": {
            "type": "object",
            "properties": {
              "auditId": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "status": {
                "type": "string"
              },
              "error": {
                "type": [
                  "object",
                  "null"
                ]
              },
              "results": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": true
              },
              "questions": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": true,
                  "description": "Active tracked question for the audited market; origin is \"generated\" when created automatically."
                }
              }
            }
          },
          "costUsd": {
            "type": "object",
            "properties": {
              "profile": {
                "type": "number",
                "minimum": 0
              },
              "questionGeneration": {
                "type": "number",
                "minimum": 0
              },
              "technical": {
                "type": "number",
                "minimum": 0
              },
              "visibility": {
                "type": "number",
                "minimum": 0
              },
              "total": {
                "type": "number",
                "minimum": 0
              }
            },
            "description": "What the account paid, by stage, for work since this audit began. Work that failed is not included.",
            "required": [
              "profile",
              "questionGeneration",
              "technical",
              "visibility",
              "total"
            ]
          },
          "limitations": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "CreditTransaction": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "enum": [
              "top_up",
              "grant",
              "charge",
              "refund"
            ]
          },
          "amountUsd": {
            "type": "number",
            "description": "Positive for credit added or refunded, negative for a charge."
          },
          "description": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "kind",
          "amountUsd",
          "description",
          "createdAt"
        ]
      },
      "Pricing": {
        "type": "object",
        "description": "Fixed prices and top-up limits. Model work is priced by the estimate returned from the estimate endpoints, and is charged only if it succeeds.",
        "properties": {
          "technicalPagePriceUsd": {
            "type": "number"
          },
          "minTopUpUsd": {
            "type": "number"
          },
          "maxTopUpUsd": {
            "type": "number"
          }
        },
        "required": [
          "technicalPagePriceUsd",
          "minTopUpUsd",
          "maxTopUpUsd"
        ]
      },
      "CreditBalance": {
        "type": "object",
        "properties": {
          "balanceUsd": {
            "type": "number",
            "description": "Credit added minus charges. A new account is first granted free credit."
          },
          "heldUsd": {
            "type": "number",
            "description": "Held for paid calls whose outcome is not yet known; returned, less the real charge if the call succeeded, when they finish."
          },
          "availableUsd": {
            "type": "number",
            "description": "balanceUsd minus heldUsd: what new work can use."
          },
          "pricing": {
            "$ref": "#/components/schemas/Pricing"
          }
        },
        "required": [
          "balanceUsd",
          "heldUsd",
          "availableUsd",
          "pricing"
        ]
      },
      "TopUpInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "amountUsd": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Between pricing.minTopUpUsd and pricing.maxTopUpUsd."
          }
        },
        "required": [
          "amountUsd"
        ]
      },
      "TopUp": {
        "type": "object",
        "properties": {
          "amountUsd": {
            "type": "number"
          },
          "checkoutUrl": {
            "type": "string",
            "format": "uri",
            "description": "Open this to pay. Credit is added when the payment is confirmed, not when it is created."
          }
        },
        "required": [
          "amountUsd",
          "checkoutUrl"
        ]
      },
      "EnrollmentRefreshed": {
        "type": "object",
        "required": [
          "enrollmentId",
          "claimUrl",
          "code",
          "expiresAt",
          "pollUrl",
          "nextSteps"
        ],
        "properties": {
          "enrollmentId": {
            "type": "string",
            "format": "uuid",
            "description": "The same enrollment; keep using its pollToken."
          },
          "claimUrl": {
            "type": "string",
            "format": "uri",
            "description": "A new approval link. The previous link no longer works."
          },
          "code": {
            "type": "string"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "One hour from now."
          },
          "pollUrl": {
            "type": "string",
            "format": "uri"
          },
          "nextSteps": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "Estimate": {
        "type": "object",
        "description": "What the work would cost, before deciding to run it. Nothing is created or charged. The estimate is exactly what the work is admitted with, and every amount is what the account pays.",
        "properties": {
          "estimatedCostUsd": {
            "type": "number",
            "minimum": 0,
            "description": "The expected cost, from typical call costs for the chosen engines. The actual cost can differ."
          },
          "maxCostUsd": {
            "type": "number",
            "minimum": 0,
            "description": "The most a visibility audit may cost: config.maxCostUsd if set, otherwise a little over the estimate. Not returned for readiness audits."
          },
          "requiredCreditUsd": {
            "type": "number",
            "minimum": 0,
            "description": "What must be available to start."
          },
          "availableCreditUsd": {
            "type": "number"
          },
          "canStart": {
            "type": "boolean",
            "description": "Whether availableCreditUsd covers requiredCreditUsd. If false, add credit first (POST /v1/billing/top-ups)."
          },
          "questions": {
            "type": "integer"
          },
          "answers": {
            "type": "integer",
            "description": "AI answers the audit will collect: questions times engines times repetitions."
          }
        },
        "required": [
          "estimatedCostUsd",
          "requiredCreditUsd",
          "availableCreditUsd",
          "canStart",
          "questions",
          "answers"
        ]
      },
      "Report": {
        "type": "object",
        "description": "A verdict and recommended actions written from an audit’s results. status is pending while it is being written, ready once it can be read, and failed with an error if it could not be written.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "version": {
            "type": "integer",
            "minimum": 1,
            "description": "Each request for a report writes a new version; the newest is returned."
          },
          "status": {
            "enum": [
              "pending",
              "ready",
              "failed"
            ]
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "verdict": {
            "type": [
              "string",
              "null"
            ],
            "description": "Where the brand stands and the single biggest opportunity."
          },
          "actions": {
            "type": "array",
            "description": "Most valuable first.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Stable identifier of the action."
                },
                "position": {
                  "type": "integer",
                  "minimum": 1
                },
                "title": {
                  "type": "string"
                },
                "priority": {
                  "enum": [
                    "high",
                    "medium",
                    "low"
                  ]
                },
                "action": {
                  "type": "string",
                  "description": "What is wrong, numbered steps to carry out and which question should change on the next audit. Written so a person or an AI agent can act on it without asking questions."
                },
                "evidence": {
                  "type": "string",
                  "description": "What in the audit supports the action. It quotes at least one tracked question exactly."
                },
                "confidence": {
                  "enum": [
                    "strong",
                    "directional"
                  ],
                  "description": "strong only with at least 30 answers and at least two questions behind the action; otherwise directional."
                }
              },
              "required": [
                "id",
                "position",
                "title",
                "priority",
                "action",
                "evidence",
                "confidence"
              ]
            }
          }
        },
        "required": [
          "id",
          "version",
          "status",
          "actions"
        ]
      },
      "BrandUpdateInput": {
        "type": "object",
        "properties": {
          "country": {
            "type": "string",
            "description": "Market the brand is audited for, for example India. Global is a market too."
          },
          "language": {
            "type": "string",
            "description": "Language of the market."
          },
          "description": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2000,
            "description": "What the business does, in a sentence or two. Needs a ready profile."
          },
          "offers": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 160
            },
            "description": "The full list of what the business offers; replaces the current list. Needs a ready profile."
          }
        },
        "minProperties": 1
      },
      "BrandUpdate": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Brand"
          },
          {
            "type": "object",
            "required": [
              "questionGeneration"
            ],
            "properties": {
              "questionGeneration": {
                "description": "Set when the market changed: the question generation for the new market (status queued, or ready when it already had questions), or status failed with the error that stopped it. Null otherwise.",
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "type": "object",
                    "required": [
                      "status"
                    ],
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": [
                          "queued",
                          "ready",
                          "failed"
                        ]
                      },
                      "brandId": {
                        "type": "string",
                        "format": "uuid"
                      },
                      "country": {
                        "type": "string"
                      },
                      "language": {
                        "type": "string"
                      },
                      "questionCount": {
                        "type": "integer"
                      },
                      "error": {
                        "$ref": "#/components/schemas/Error/properties/error"
                      }
                    }
                  }
                ]
              }
            }
          }
        ]
      }
    }
  }
}
