{
  "openapi": "3.1.0",
  "info": {
    "title": "Zerocost API",
    "version": "1.0.0",
    "summary": "Public API for Zerocost, the monetization platform for AI apps and SaaS.",
    "description": "Read-only public endpoints (docs search, pricing, page index) need no authentication. Account endpoints under /api/v1/me use OAuth 2.0 (authorization code + PKCE, dynamic client registration at /oauth/register) with least-privilege scopes. SDK endpoints authenticate with an app API key in the `x-api-key` header. See https://zerocost.app/auth.md.\n\n**Rate limits:** 120 requests per 60 seconds per client IP on /api/v1, /mcp, /docs/mcp, /ask, /a2a and the OAuth registration and token endpoints. Every response carries RateLimit-Policy and RateLimit headers (draft-ietf-httpapi-ratelimit-headers) plus X-RateLimit-*; over the limit you get 429 with Retry-After. Limits are enforced per edge instance, so treat them as a ceiling, not a guarantee.\n\n**Pagination:** list endpoints use opaque cursors. Pass `pagination.next_cursor` back as `cursor` until `has_more` is false.\n\n**Sandbox:** call any /api/v1/me endpoint, /api/v1/batch or the MCP account tools with `Authorization: Bearer zc_sandbox` to get fixed demo data (marked \"sandbox\": true, plus a Zerocost-Sandbox: true header) without an account. It never touches real accounts.\n\n**Versioning and deprecation:** the version is in the path (/api/v1) and in the API-Version response header. Within v1 changes are additive only (new endpoints, new optional parameters, new response fields). Breaking changes ship as a new version (/api/v2). Before a v1 endpoint is removed it gets a Deprecation header (RFC 9745) and a Sunset header (RFC 8594) at least 90 days ahead, with a Link to the migration notes. Policy: https://zerocost.app/developers/versioning",
    "contact": {
      "name": "Zerocost",
      "url": "https://zerocost.app/contact"
    },
    "termsOfService": "https://zerocost.app/terms",
    "x-deprecation-policy": "https://zerocost.app/developers/versioning"
  },
  "externalDocs": {
    "description": "Zerocost documentation",
    "url": "https://zerocost.app/docs"
  },
  "servers": [
    {
      "url": "https://zerocost.app",
      "description": "Production. Account endpoints also accept the public sandbox token \"zc_sandbox\" (see the Sandbox security scheme), which returns demo data only."
    }
  ],
  "tags": [
    {
      "name": "API",
      "description": "API entry point and batching."
    },
    {
      "name": "Docs",
      "description": "Search and browse Zerocost documentation."
    },
    {
      "name": "Pricing",
      "description": "Machine-readable pricing."
    },
    {
      "name": "Account",
      "description": "The signed-in user's own data. Require an OAuth 2.0 access token with the listed scope."
    },
    {
      "name": "SDK",
      "description": "Endpoints used by the @zerocost/sdk package. Require an API key."
    },
    {
      "name": "OAuth",
      "description": "OAuth 2.0 client registration (RFC 7591)."
    }
  ],
  "paths": {
    "/api/v1": {
      "get": {
        "operationId": "getApiIndex",
        "tags": [
          "API"
        ],
        "summary": "API entry point",
        "description": "Lists public and account endpoints. Without a bearer token it answers 401 with a WWW-Authenticate challenge pointing at the protected resource metadata; the body still lists the public endpoints.",
        "security": [
          {},
          {
            "OAuth2": []
          }
        ],
        "responses": {
          "200": {
            "description": "Index, with the scopes of the presented token.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "version": {
                      "type": "string"
                    },
                    "openapi": {
                      "type": "string",
                      "format": "uri"
                    },
                    "auth": {
                      "type": "string",
                      "format": "uri"
                    },
                    "public_endpoints": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "method": {
                            "type": "string"
                          },
                          "path": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "account_endpoints": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "method": {
                            "type": "string"
                          },
                          "path": {
                            "type": "string"
                          },
                          "scope": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "token": {
                      "type": "object",
                      "properties": {
                        "scopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "expires_at": {
                          "type": "integer"
                        }
                      }
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "No or invalid token. The WWW-Authenticate header names the resource metadata URL; the body also lists the public endpoints.",
            "headers": {
              "WWW-Authenticate": {
                "description": "Bearer challenge with resource_metadata.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Wait Retry-After seconds.",
            "headers": {
              "Retry-After": {
                "description": "Seconds until you may retry.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/batch": {
      "post": {
        "operationId": "batchRequests",
        "tags": [
          "API"
        ],
        "summary": "Run several requests in one call",
        "description": "Runs up to 20 API v1 GET requests (search, pricing, pages, me, me/apps, me/earnings, me/api-keys) in parallel and returns each status and body. The Authorization header is applied to every operation. All operations are reads, so a batch is safe to retry; an Idempotency-Key is echoed back.",
        "security": [
          {},
          {
            "OAuth2": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Client-chosen unique key (1-255 visible ASCII characters). Retrying a request with the same key and body returns the original result instead of performing the operation again.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x21-\\x7e]+$"
            },
            "example": "b7c1e4a0-6f4e-4d8e-9a77-2f3b1c9e0d11"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "requests"
                ],
                "properties": {
                  "requests": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 20,
                    "items": {
                      "type": "object",
                      "required": [
                        "path"
                      ],
                      "properties": {
                        "id": {
                          "type": [
                            "string",
                            "integer"
                          ],
                          "description": "Your label for matching the result; defaults to the index."
                        },
                        "method": {
                          "type": "string",
                          "enum": [
                            "GET"
                          ],
                          "default": "GET"
                        },
                        "path": {
                          "type": "string",
                          "description": "An API v1 path with query string, e.g. /api/v1/search?q=payouts."
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One result per operation, in request order.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "responses"
                  ],
                  "properties": {
                    "responses": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "status",
                          "body"
                        ],
                        "properties": {
                          "id": {
                            "type": [
                              "string",
                              "integer"
                            ]
                          },
                          "status": {
                            "type": "integer"
                          },
                          "body": {
                            "description": "The JSON body the operation returned."
                          }
                        }
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Malformed batch.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Wait Retry-After seconds.",
            "headers": {
              "Retry-After": {
                "description": "Seconds until you may retry.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/search": {
      "get": {
        "operationId": "searchDocs",
        "tags": [
          "Docs"
        ],
        "summary": "Search Zerocost documentation",
        "description": "Keyword search across Zerocost docs, product pages and llms.txt sections.",
        "security": [],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Search query.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1-20).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 5
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque cursor from a previous response (pagination.next_cursor).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matching documentation sections.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "query",
                    "count",
                    "results",
                    "pagination"
                  ],
                  "properties": {
                    "query": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "title",
                          "url",
                          "score",
                          "snippet"
                        ],
                        "properties": {
                          "title": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string",
                            "format": "uri"
                          },
                          "score": {
                            "type": "number"
                          },
                          "snippet": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "required": [
                        "next_cursor",
                        "has_more",
                        "limit"
                      ],
                      "properties": {
                        "next_cursor": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Pass as `cursor` to get the next page; null on the last page."
                        },
                        "has_more": {
                          "type": "boolean"
                        },
                        "limit": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid query parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Wait Retry-After seconds.",
            "headers": {
              "Retry-After": {
                "description": "Seconds until you may retry.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/pricing": {
      "get": {
        "operationId": "getPricing",
        "tags": [
          "Pricing"
        ],
        "summary": "Get current pricing",
        "description": "Publisher revenue share, advertiser CPMs and dataset prices in USD.",
        "security": [],
        "parameters": [
          {
            "name": "audience",
            "in": "query",
            "required": false,
            "description": "Limit the answer to one kind of customer.",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "publisher",
                "advertiser",
                "data_buyer"
              ],
              "default": "all"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current pricing.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "currency",
                    "live",
                    "publisher_ad_revenue_share",
                    "platform_ad_fee",
                    "publisher_data_revenue_share"
                  ],
                  "properties": {
                    "currency": {
                      "type": "string",
                      "const": "USD"
                    },
                    "live": {
                      "type": "boolean",
                      "description": "False when live settings were unavailable and defaults are returned."
                    },
                    "publisher_ad_revenue_share": {
                      "type": "number",
                      "description": "Fraction of ad revenue paid to the publisher."
                    },
                    "platform_ad_fee": {
                      "type": "number",
                      "description": "Fraction of ad revenue kept by Zerocost."
                    },
                    "publisher_data_revenue_share": {
                      "type": "number",
                      "description": "Fraction of data sales paid to the publisher."
                    },
                    "advertiser_cpm_usd": {
                      "type": "object",
                      "properties": {
                        "floating_video": {
                          "type": "number"
                        },
                        "tooltip": {
                          "type": "number"
                        },
                        "sponsored_card": {
                          "type": "number"
                        },
                        "inline_text": {
                          "type": "number"
                        }
                      }
                    },
                    "dataset_prices_usd": {
                      "type": "object",
                      "properties": {
                        "per_ai_interaction_row": {
                          "type": "number"
                        },
                        "per_ux_session_recording": {
                          "type": "number"
                        },
                        "per_gb_bundle": {
                          "type": "number"
                        }
                      }
                    },
                    "exclusive_license_multiplier": {
                      "type": "number"
                    },
                    "min_payout_usd": {
                      "type": "number"
                    },
                    "markdown": {
                      "type": "string",
                      "format": "uri"
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Unknown audience.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Wait Retry-After seconds.",
            "headers": {
              "Retry-After": {
                "description": "Seconds until you may retry.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/pages": {
      "get": {
        "operationId": "listPages",
        "tags": [
          "Docs"
        ],
        "summary": "List public pages",
        "description": "Every public, indexable page on zerocost.app with its title, description and markdown twin.",
        "security": [],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Pages per response (1-100).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque cursor from a previous response (pagination.next_cursor).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Public pages.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "total",
                    "pages",
                    "pagination"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "total": {
                      "type": "integer"
                    },
                    "pages": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "path",
                          "url",
                          "title",
                          "description"
                        ],
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string",
                            "format": "uri"
                          },
                          "title": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "required": [
                        "next_cursor",
                        "has_more",
                        "limit"
                      ],
                      "properties": {
                        "next_cursor": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Pass as `cursor` to get the next page; null on the last page."
                        },
                        "has_more": {
                          "type": "boolean"
                        },
                        "limit": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Wait Retry-After seconds.",
            "headers": {
              "Retry-After": {
                "description": "Seconds until you may retry.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/me": {
      "get": {
        "operationId": "getMyProfile",
        "tags": [
          "Account"
        ],
        "summary": "Get my profile",
        "description": "Name, email, company and role of the user who authorized the token.",
        "security": [
          {
            "OAuth2": [
              "profile:read"
            ]
          },
          {
            "Sandbox": []
          }
        ],
        "responses": {
          "200": {
            "description": "Profile.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "user_id": {
                      "type": "string"
                    },
                    "email": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "name": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "company": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "role": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "member_since": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired access token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token lacks the profile:read scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Wait Retry-After seconds.",
            "headers": {
              "Retry-After": {
                "description": "Seconds until you may retry.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Account data could not be loaded; authorize again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/me/apps": {
      "get": {
        "operationId": "listMyApps",
        "tags": [
          "Account"
        ],
        "summary": "List my apps and placements",
        "description": "The user's apps and ad placements with impressions, clicks, revenue, fill rate and RPM.",
        "security": [
          {
            "OAuth2": [
              "apps:read"
            ]
          },
          {
            "Sandbox": []
          }
        ],
        "parameters": [
          {
            "name": "placement_status",
            "in": "query",
            "required": false,
            "description": "Only placements with this status.",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "active",
                "paused"
              ],
              "default": "all"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Apps and placements.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "apps": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "slug": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          },
                          "category": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "placements": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "format": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          },
                          "impressions": {
                            "type": "integer"
                          },
                          "clicks": {
                            "type": "integer"
                          },
                          "revenue_usd": {
                            "type": "number"
                          },
                          "fill_rate": {
                            "type": "number"
                          },
                          "rpm_usd": {
                            "type": "number"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid filter parameter.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired access token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token lacks the apps:read scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Wait Retry-After seconds.",
            "headers": {
              "Retry-After": {
                "description": "Seconds until you may retry.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Account data could not be loaded; authorize again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/me/earnings": {
      "get": {
        "operationId": "getMyEarnings",
        "tags": [
          "Account"
        ],
        "summary": "Get my earnings",
        "description": "Tracked ad revenue, impressions, clicks and payout history in USD.",
        "security": [
          {
            "OAuth2": [
              "earnings:read"
            ]
          },
          {
            "Sandbox": []
          }
        ],
        "parameters": [
          {
            "name": "payout_limit",
            "in": "query",
            "required": false,
            "description": "How many recent payouts to include.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 50,
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Earnings.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "currency": {
                      "type": "string",
                      "const": "USD"
                    },
                    "ad_revenue_tracked_usd": {
                      "type": "number"
                    },
                    "impressions": {
                      "type": "integer"
                    },
                    "clicks": {
                      "type": "integer"
                    },
                    "payouts_paid_usd": {
                      "type": "number"
                    },
                    "payouts_pending_usd": {
                      "type": "number"
                    },
                    "payouts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "period": {
                            "type": "string"
                          },
                          "amount_usd": {
                            "type": "number"
                          },
                          "status": {
                            "type": "string"
                          },
                          "paid_at": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "requested_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "note": {
                      "type": "string"
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid filter parameter.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired access token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token lacks the earnings:read scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Wait Retry-After seconds.",
            "headers": {
              "Retry-After": {
                "description": "Seconds until you may retry.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Account data could not be loaded; authorize again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/me/api-keys": {
      "get": {
        "operationId": "listMyApiKeys",
        "tags": [
          "Account"
        ],
        "summary": "List my API keys",
        "description": "The user's SDK API keys, masked, with environment and status.",
        "security": [
          {
            "OAuth2": [
              "api_keys:read"
            ]
          },
          {
            "Sandbox": []
          }
        ],
        "parameters": [
          {
            "name": "environment",
            "in": "query",
            "required": false,
            "description": "Only keys with this environment label.",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "development",
                "production"
              ],
              "default": "all"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Only keys with this status.",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "active",
                "revoked"
              ],
              "default": "all"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "API keys.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "api_keys": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "key_hint": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "First 8 and last 4 characters only."
                          },
                          "environment": {
                            "type": "string",
                            "enum": [
                              "development",
                              "production"
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "active",
                              "revoked"
                            ]
                          },
                          "last_used": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid filter parameter.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired access token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token lacks the api_keys:read scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Wait Retry-After seconds.",
            "headers": {
              "Retry-After": {
                "description": "Seconds until you may retry.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Account data could not be loaded; authorize again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/oauth/register": {
      "post": {
        "operationId": "registerOAuthClient",
        "tags": [
          "OAuth"
        ],
        "summary": "Register an OAuth client",
        "description": "RFC 7591 dynamic client registration. Send an Idempotency-Key to make retries safe: the same key and the same metadata always return the same client_id and client_secret, so a retried request never creates a second client.",
        "security": [],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Client-chosen unique key (1-255 visible ASCII characters). Retrying a request with the same key and body returns the original result instead of performing the operation again.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x21-\\x7e]+$"
            },
            "example": "b7c1e4a0-6f4e-4d8e-9a77-2f3b1c9e0d11"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "redirect_uris"
                ],
                "properties": {
                  "client_name": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "redirect_uris": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 10,
                    "items": {
                      "type": "string",
                      "format": "uri"
                    },
                    "description": "https URLs, loopback http URLs (127.0.0.1, localhost, [::1]) or private-use schemes for native apps."
                  },
                  "token_endpoint_auth_method": {
                    "type": "string",
                    "enum": [
                      "none",
                      "client_secret_post",
                      "client_secret_basic"
                    ],
                    "default": "none"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Client registered.",
            "headers": {
              "Idempotency-Key": {
                "description": "Echo of the request Idempotency-Key, when one was sent.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "client_id",
                    "redirect_uris",
                    "token_endpoint_auth_method"
                  ],
                  "properties": {
                    "client_id": {
                      "type": "string"
                    },
                    "client_id_issued_at": {
                      "type": "integer",
                      "description": "Omitted for idempotent registrations."
                    },
                    "client_secret": {
                      "type": "string",
                      "description": "Only for confidential clients."
                    },
                    "client_secret_expires_at": {
                      "type": "integer",
                      "const": 0
                    },
                    "client_name": {
                      "type": "string"
                    },
                    "redirect_uris": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uri"
                      }
                    },
                    "token_endpoint_auth_method": {
                      "type": "string",
                      "enum": [
                        "none",
                        "client_secret_post",
                        "client_secret_basic"
                      ]
                    },
                    "grant_types": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "const": "authorization_code"
                      }
                    },
                    "response_types": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "const": "code"
                      }
                    },
                    "scope": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid client metadata or Idempotency-Key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "error_description": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Wait Retry-After seconds.",
            "headers": {
              "Retry-After": {
                "description": "Seconds until you may retry.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Policy": {
                "description": "Quota policy, e.g. \"default\";q=120;w=60.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Remaining quota and seconds until reset, e.g. \"default\";r=119;t=60.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time when the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "API version that served the request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "OAuth is not configured on this deployment.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "error_description": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/functions/v1/validate-key": {
      "get": {
        "operationId": "validateApiKey",
        "tags": [
          "SDK"
        ],
        "summary": "Validate an SDK API key",
        "description": "Checks that an API key exists and is active, and returns its environment.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "The key is valid.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "valid",
                    "key"
                  ],
                  "properties": {
                    "valid": {
                      "type": "boolean",
                      "const": true
                    },
                    "key": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "environment": {
                          "type": "string",
                          "enum": [
                            "development",
                            "production"
                          ]
                        },
                        "created_at": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing x-api-key header.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "valid",
                    "error"
                  ],
                  "properties": {
                    "valid": {
                      "type": "boolean",
                      "const": false
                    },
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key is revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "valid",
                    "error"
                  ],
                  "properties": {
                    "valid": {
                      "type": "boolean",
                      "const": false
                    },
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "The key does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "valid",
                    "error"
                  ],
                  "properties": {
                    "valid": {
                      "type": "boolean",
                      "const": false
                    },
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "Client-chosen unique key (1-255 visible ASCII characters). Retrying a request with the same key and body returns the original result instead of performing the operation again.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255,
          "pattern": "^[\\x21-\\x7e]+$"
        },
        "example": "b7c1e4a0-6f4e-4d8e-9a77-2f3b1c9e0d11"
      }
    },
    "securitySchemes": {
      "Sandbox": {
        "type": "http",
        "scheme": "bearer",
        "description": "Public sandbox: send the literal token \"zc_sandbox\" as a bearer token. It grants every account scope but only returns fixed demo data, marked \"sandbox\": true."
      },
      "OAuth2": {
        "type": "oauth2",
        "description": "OAuth 2.0 authorization code flow with PKCE (S256). Register a client dynamically (RFC 7591) at /oauth/register. Access tokens are read-only and last up to one hour; there are no refresh tokens. Metadata: https://zerocost.app/.well-known/oauth-authorization-server",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://zerocost.app/oauth/authorize",
            "tokenUrl": "https://zerocost.app/oauth/token",
            "scopes": {
              "profile:read": "See your name, company, role and email.",
              "apps:read": "See your apps and ad placements, including impressions, clicks and revenue.",
              "earnings:read": "See your earnings totals and payout history.",
              "api_keys:read": "See the names, environments and status of your API keys (keys are masked)."
            }
          }
        },
        "x-registration-url": "https://zerocost.app/oauth/register"
      },
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "App API key from https://zerocost.app/startup/api-keys. Each key is scoped to a single app and a single environment (development or production) and only grants SDK capabilities for that app: fetching placements, recording ad events and submitting consented data. It cannot read earnings or change settings."
      }
    },
    "schemas": {
      "ClientRegistrationRequest": {
        "type": "object",
        "required": [
          "redirect_uris"
        ],
        "properties": {
          "client_name": {
            "type": "string",
            "maxLength": 80
          },
          "redirect_uris": {
            "type": "array",
            "minItems": 1,
            "maxItems": 10,
            "items": {
              "type": "string",
              "format": "uri"
            },
            "description": "https URLs, loopback http URLs (127.0.0.1, localhost, [::1]) or private-use schemes for native apps."
          },
          "token_endpoint_auth_method": {
            "type": "string",
            "enum": [
              "none",
              "client_secret_post",
              "client_secret_basic"
            ],
            "default": "none"
          }
        }
      },
      "ClientRegistration": {
        "type": "object",
        "required": [
          "client_id",
          "redirect_uris",
          "token_endpoint_auth_method"
        ],
        "properties": {
          "client_id": {
            "type": "string"
          },
          "client_id_issued_at": {
            "type": "integer",
            "description": "Omitted for idempotent registrations."
          },
          "client_secret": {
            "type": "string",
            "description": "Only for confidential clients."
          },
          "client_secret_expires_at": {
            "type": "integer",
            "const": 0
          },
          "client_name": {
            "type": "string"
          },
          "redirect_uris": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            }
          },
          "token_endpoint_auth_method": {
            "type": "string",
            "enum": [
              "none",
              "client_secret_post",
              "client_secret_basic"
            ]
          },
          "grant_types": {
            "type": "array",
            "items": {
              "type": "string",
              "const": "authorization_code"
            }
          },
          "response_types": {
            "type": "array",
            "items": {
              "type": "string",
              "const": "code"
            }
          },
          "scope": {
            "type": "string"
          }
        }
      },
      "OAuthError": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "error_description": {
            "type": "string"
          }
        }
      },
      "Profile": {
        "type": "object",
        "properties": {
          "user_id": {
            "type": "string"
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "company": {
            "type": [
              "string",
              "null"
            ]
          },
          "role": {
            "type": [
              "string",
              "null"
            ]
          },
          "member_since": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "Placement": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "format": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "impressions": {
            "type": "integer"
          },
          "clicks": {
            "type": "integer"
          },
          "revenue_usd": {
            "type": "number"
          },
          "fill_rate": {
            "type": "number"
          },
          "rpm_usd": {
            "type": "number"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "AppsResponse": {
        "type": "object",
        "properties": {
          "apps": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "slug": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                },
                "category": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            }
          },
          "placements": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Placement"
            }
          }
        }
      },
      "Earnings": {
        "type": "object",
        "properties": {
          "currency": {
            "type": "string",
            "const": "USD"
          },
          "ad_revenue_tracked_usd": {
            "type": "number"
          },
          "impressions": {
            "type": "integer"
          },
          "clicks": {
            "type": "integer"
          },
          "payouts_paid_usd": {
            "type": "number"
          },
          "payouts_pending_usd": {
            "type": "number"
          },
          "payouts": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "period": {
                  "type": "string"
                },
                "amount_usd": {
                  "type": "number"
                },
                "status": {
                  "type": "string"
                },
                "paid_at": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "requested_at": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            }
          },
          "note": {
            "type": "string"
          }
        }
      },
      "ApiKeyList": {
        "type": "object",
        "properties": {
          "api_keys": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "key_hint": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "First 8 and last 4 characters only."
                },
                "environment": {
                  "type": "string",
                  "enum": [
                    "development",
                    "production"
                  ]
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "active",
                    "revoked"
                  ]
                },
                "last_used": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "status",
              "code",
              "message"
            ],
            "properties": {
              "status": {
                "type": "integer",
                "description": "HTTP status code."
              },
              "code": {
                "type": "string",
                "description": "Machine-readable error code.",
                "examples": [
                  "unauthorized",
                  "invalid_token",
                  "insufficient_scope",
                  "invalid_parameter",
                  "invalid_cursor",
                  "missing_query",
                  "not_found",
                  "rate_limited",
                  "upstream_error"
                ]
              },
              "message": {
                "type": "string",
                "description": "Human-readable explanation."
              },
              "docs": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "SearchResult": {
        "type": "object",
        "required": [
          "title",
          "url",
          "score",
          "snippet"
        ],
        "properties": {
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "score": {
            "type": "number"
          },
          "snippet": {
            "type": "string"
          }
        }
      },
      "Pagination": {
        "type": "object",
        "required": [
          "next_cursor",
          "has_more",
          "limit"
        ],
        "properties": {
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          },
          "has_more": {
            "type": "boolean"
          },
          "limit": {
            "type": "integer"
          }
        }
      },
      "SearchResponse": {
        "type": "object",
        "required": [
          "query",
          "count",
          "results",
          "pagination"
        ],
        "properties": {
          "query": {
            "type": "string"
          },
          "count": {
            "type": "integer"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchResult"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        }
      },
      "ApiIndex": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "openapi": {
            "type": "string",
            "format": "uri"
          },
          "auth": {
            "type": "string",
            "format": "uri"
          },
          "public_endpoints": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "method": {
                  "type": "string"
                },
                "path": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                }
              }
            }
          },
          "account_endpoints": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "method": {
                  "type": "string"
                },
                "path": {
                  "type": "string"
                },
                "scope": {
                  "type": "string"
                }
              }
            }
          },
          "token": {
            "type": "object",
            "properties": {
              "scopes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "expires_at": {
                "type": "integer"
              }
            }
          },
          "error": {
            "type": "object",
            "properties": {
              "status": {
                "type": "integer"
              },
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      },
      "BatchRequest": {
        "type": "object",
        "required": [
          "requests"
        ],
        "properties": {
          "requests": {
            "type": "array",
            "minItems": 1,
            "maxItems": 20,
            "items": {
              "type": "object",
              "required": [
                "path"
              ],
              "properties": {
                "id": {
                  "type": [
                    "string",
                    "integer"
                  ],
                  "description": "Your label for matching the result; defaults to the index."
                },
                "method": {
                  "type": "string",
                  "enum": [
                    "GET"
                  ],
                  "default": "GET"
                },
                "path": {
                  "type": "string",
                  "description": "An API v1 path with query string, e.g. /api/v1/search?q=payouts."
                }
              }
            }
          }
        }
      },
      "BatchResponse": {
        "type": "object",
        "required": [
          "responses"
        ],
        "properties": {
          "responses": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "status",
                "body"
              ],
              "properties": {
                "id": {
                  "type": [
                    "string",
                    "integer"
                  ]
                },
                "status": {
                  "type": "integer"
                },
                "body": {
                  "description": "The JSON body the operation returned."
                }
              }
            }
          }
        }
      },
      "Pricing": {
        "type": "object",
        "required": [
          "currency",
          "live",
          "publisher_ad_revenue_share",
          "platform_ad_fee",
          "publisher_data_revenue_share"
        ],
        "properties": {
          "currency": {
            "type": "string",
            "const": "USD"
          },
          "live": {
            "type": "boolean",
            "description": "False when live settings were unavailable and defaults are returned."
          },
          "publisher_ad_revenue_share": {
            "type": "number",
            "description": "Fraction of ad revenue paid to the publisher."
          },
          "platform_ad_fee": {
            "type": "number",
            "description": "Fraction of ad revenue kept by Zerocost."
          },
          "publisher_data_revenue_share": {
            "type": "number",
            "description": "Fraction of data sales paid to the publisher."
          },
          "advertiser_cpm_usd": {
            "type": "object",
            "properties": {
              "floating_video": {
                "type": "number"
              },
              "tooltip": {
                "type": "number"
              },
              "sponsored_card": {
                "type": "number"
              },
              "inline_text": {
                "type": "number"
              }
            }
          },
          "dataset_prices_usd": {
            "type": "object",
            "properties": {
              "per_ai_interaction_row": {
                "type": "number"
              },
              "per_ux_session_recording": {
                "type": "number"
              },
              "per_gb_bundle": {
                "type": "number"
              }
            }
          },
          "exclusive_license_multiplier": {
            "type": "number"
          },
          "min_payout_usd": {
            "type": "number"
          },
          "markdown": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "Page": {
        "type": "object",
        "required": [
          "path",
          "url",
          "title",
          "description"
        ],
        "properties": {
          "path": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        }
      },
      "PageList": {
        "type": "object",
        "required": [
          "count",
          "total",
          "pages",
          "pagination"
        ],
        "properties": {
          "count": {
            "type": "integer"
          },
          "total": {
            "type": "integer"
          },
          "pages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Page"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        }
      },
      "KeyValidation": {
        "type": "object",
        "required": [
          "valid",
          "key"
        ],
        "properties": {
          "valid": {
            "type": "boolean",
            "const": true
          },
          "key": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "environment": {
                "type": "string",
                "enum": [
                  "development",
                  "production"
                ]
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      },
      "KeyValidationError": {
        "type": "object",
        "required": [
          "valid",
          "error"
        ],
        "properties": {
          "valid": {
            "type": "boolean",
            "const": false
          },
          "error": {
            "type": "string"
          }
        }
      }
    }
  }
}