{
  "openapi": "3.1.1",
  "info": {
    "title": "PageSpeedAudit API",
    "description": "The **PageSpeedAudit API** turns the same expert PageSpeed audit you can buy on the\r\nwebsite into a programmable workflow: purchase an audit, run it against one URL, poll until it\r\nfinishes, then pull a customer-ready HTML report and a machine-readable findings document\r\n(`pagespeed-audit/findings@1`). It's a small, predictable REST API — JSON in, JSON out, one\r\nlong-running job type.\r\n\r\n## Base URL\r\n\r\n```\r\nhttps://pagespeedaudit.com/api/v1\r\n```\r\n\r\nAll paths below are relative to this base. The API is versioned in the path; breaking changes\r\nship under a new version, never on `v1`.\r\n\r\n## Authentication\r\n\r\nAuthenticate every request with an API key in the **`X-Api-Key`** header:\r\n\r\n```bash\r\ncurl https://pagespeedaudit.com/api/v1/me \\\r\n  -H \"X-Api-Key: psa_live_your_key_here\"\r\n```\r\n\r\nKeys look like `psa_live_…`, are created and revoked from your dashboard, and are shown in full\r\nexactly once. Only a SHA-256 hash is stored server-side — we cannot recover a lost key, so store\r\nit in your secret manager. Treat it like a password: it grants full access to your account's\r\naudits. Key management itself (`/apikeys`) is dashboard-only and cannot be driven by an API key.\r\n\r\n## The audit lifecycle\r\n\r\n1. **Buy an audit** — send your customer to Checkout (`POST /checkout/sessions`) or buy on the\r\n   site. A paid purchase grants one *audit entitlement*: **1 URL, 3 runs (1 + 2 re-runs), valid\r\n   30 days from the first run**. Price: $497.\r\n2. **Find the entitlement** — `GET /me` or `GET /audits` lists your audits and how many runs\r\n   remain.\r\n3. **Start a run** — `POST /audits/{auditId}/runs` with `{ \"url\": \"https://example.com/\" }`.\r\n   The first run **locks that URL** to the audit and starts the 30-day window; re-runs must\r\n   reuse the same URL. Returns **202 Accepted** with a `runId`.\r\n4. **Poll the run** — `GET /runs/{runId}` until `status` is `Succeeded` (or `Failed`/`TimedOut`).\r\n   Runs complete in less than 24 hours. `GET /runs/{runId}/events` streams a human-readable timeline.\r\n5. **Fetch the report** — `GET /runs/{runId}/report?format=json` for the findings document, or\r\n   `?format=html` for the rendered, self-contained customer report.\r\n\r\nA failed or timed-out run does **not** consume one of your three runs.\r\n\r\n## Rate limits\r\n\r\nAuthenticated endpoints allow **60 requests per minute per account** (token bucket). Anonymous\r\nendpoints (checkout, newsletter, contact) allow **10 requests per minute per IP**. Over the\r\nlimit returns **429 Too Many Requests** — back off and retry.\r\n\r\n## Errors\r\n\r\nErrors use [RFC 7807 problem+json](https://datatracker.ietf.org/doc/html/rfc7807) with a stable\r\nmachine-readable `code`:\r\n\r\n```json\r\n{ \"status\": 409, \"code\": \"runs_exhausted\", \"detail\": \"All included runs have been used.\" }\r\n```\r\n\r\n| Status | When |\r\n|---|---|\r\n| `400` | Invalid input — e.g. `url_required`, `invalid_url`, `invalid_format` |\r\n| `401` | Missing or invalid API key |\r\n| `403` | Authenticated but not allowed (e.g. an API key calling a dashboard-only endpoint) |\r\n| `404` | The resource doesn't exist **or** isn't yours (ownership failures look identical, by design) |\r\n| `409` | Entitlement conflict — `url_locked`, `run_in_progress`, `runs_exhausted`, `expired`, `revoked` |\r\n| `429` | Rate limited |\r\n\r\n## Idempotency & polling\r\n\r\nStarting a run is safe to retry: a second `POST` while a run is active returns `409 run_in_progress`\r\nrather than starting a duplicate. Poll `GET /runs/{runId}` (a few seconds between calls is plenty);\r\nthere are no webhooks for run completion in `v1`.\r\n\r\n## Support\r\n\r\nQuestions or a higher rate limit? Email the address in the contact block below, or use the\r\n[contact form](https://pagespeedaudit.com/contact).",
    "termsOfService": "https://pagespeedaudit.com/legal/terms",
    "contact": {
      "name": "PageSpeedAudit support",
      "url": "https://pagespeedaudit.com/contact",
      "email": "support@pagespeedaudit.com"
    },
    "license": {
      "name": "Proprietary — © 2026 PageSpeedAudit"
    },
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://pagespeedaudit.com",
      "description": "Production"
    }
  ],
  "paths": {
    "/api/v1/checkout/sessions": {
      "post": {
        "tags": [
          "Checkout"
        ],
        "summary": "Start a checkout",
        "description": "Creates a hosted Stripe Checkout session and returns its URL. Redirect the buyer there; on payment, an audit entitlement is created for their email. Pass `email` to prefill the buyer's address.",
        "operationId": "createCheckoutSession",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/CreateCheckoutRequest"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateCheckoutResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contact": {
      "post": {
        "tags": [
          "Contact"
        ],
        "summary": "Send a contact message",
        "description": "Acknowledges the sender by email; genuine (non-spam) messages are forwarded internally after an automated classification. Requires a valid email and a message of at most 5000 characters.",
        "operationId": "submitContact",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/r/{code}": {
      "get": {
        "tags": [
          "Affiliate"
        ],
        "summary": "Referral link",
        "description": "The affiliate referral link. Sets the signed 30-day last-click attribution cookie and redirects. Optional query parameters: `to` (internal path to land on, e.g. `/pricing` — external URLs fall back to `/`), `subid` (also `clickid`/`s1`; your own click id, echoed in reporting and postbacks) and `campaign` (a broader reporting bucket). Unknown or suspended codes redirect without setting anything.",
        "operationId": "referralRedirect",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Found"
          }
        }
      }
    },
    "/api/v1/me": {
      "get": {
        "tags": [
          "Audits"
        ],
        "summary": "Who am I",
        "description": "Returns the authenticated account and the list of audit entitlements it owns.",
        "operationId": "getMe",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MeDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/audits": {
      "get": {
        "tags": [
          "Audits"
        ],
        "summary": "List audits",
        "description": "Lists every audit entitlement on the account, with runs used/remaining and expiry.",
        "operationId": "listAudits",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AuditDto"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/audits/{auditId}": {
      "get": {
        "tags": [
          "Audits"
        ],
        "summary": "Get an audit",
        "description": "Fetches one audit by id. Returns 404 if it does not exist or belongs to another account.",
        "operationId": "getAudit",
        "parameters": [
          {
            "name": "auditId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/audits/{auditId}/runs": {
      "get": {
        "tags": [
          "Audits"
        ],
        "summary": "List runs of an audit",
        "description": "Lists every run of one audit, newest first, with the report formats available for each.",
        "operationId": "listRuns",
        "parameters": [
          {
            "name": "auditId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RunDto"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      },
      "post": {
        "tags": [
          "Audits"
        ],
        "summary": "Start an audit run",
        "description": "Queues a run. On the **first** run, pass `url` — it gets locked to this audit and starts the\r\n30-day window; re-runs must reuse the same URL. Up to 3 runs total (1 + 2 re-runs). Returns\r\n**202 Accepted** with the `runId`; poll `GET /runs/{runId}` for completion. Conflicts\r\n(`url_locked`, `run_in_progress`, `runs_exhausted`, `expired`, `revoked`) return 409.",
        "operationId": "createRun",
        "parameters": [
          {
            "name": "auditId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/CreateRunRequest"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateRunResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/runs/{runId}": {
      "get": {
        "tags": [
          "Audits"
        ],
        "summary": "Get run status",
        "description": "Returns the run's status and timestamps. Poll until `status` is `Succeeded`, then fetch the report. No token or cost data is ever included.",
        "operationId": "getRun",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/runs/{runId}/events": {
      "get": {
        "tags": [
          "Audits"
        ],
        "summary": "Get run timeline",
        "description": "Returns the human-readable progress timeline of a run (summaries only).",
        "operationId": "getRunEvents",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RunEventDto"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/runs/{runId}/report": {
      "get": {
        "tags": [
          "Audits"
        ],
        "summary": "Download the report",
        "description": "Streams a deliverable for a succeeded run. `format=json` returns the machine-readable findings\r\ndocument (schema `pagespeed-audit/findings@1`); `format=html` returns the rendered, self-contained\r\ncustomer report. `inline=true` streams without an attachment disposition (for embedding).",
        "operationId": "getRunReport",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "inline",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/apikeys": {
      "get": {
        "tags": [
          "API keys"
        ],
        "summary": "List API keys",
        "description": "Lists the account's API keys — prefixes and metadata only; the secret is never retrievable. Dashboard session required.",
        "operationId": "listApiKeys",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ApiKeyDto"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      },
      "post": {
        "tags": [
          "API keys"
        ],
        "summary": "Create an API key",
        "description": "Creates a key and returns the plaintext secret **exactly once** — store it immediately. Dashboard session required (API keys cannot create keys). Returns 409 if an active key already uses the name.",
        "operationId": "createApiKey",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateApiKeyRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateApiKeyResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/apikeys/{keyId}": {
      "delete": {
        "tags": [
          "API keys"
        ],
        "summary": "Revoke an API key",
        "description": "Immediately revokes a key by id. Returns 204 on success, 404 if the key isn't found on this account. Dashboard session required.",
        "operationId": "revokeApiKey",
        "parameters": [
          {
            "name": "keyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/newsletter/subscribe": {
      "post": {
        "tags": [
          "Newsletter"
        ],
        "summary": "Subscribe to the newsletter",
        "description": "Double opt-in: a confirmation email is sent. The response is identical whether or not the address was already subscribed (no subscriber enumeration).",
        "operationId": "subscribeNewsletter",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubscribeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/affiliate/me": {
      "get": {
        "tags": [
          "Affiliate"
        ],
        "summary": "Your affiliate profile",
        "description": "Referral code + link, effective commission rate, attribution window, discount coupons, payout-onboarding state, and the current postback configuration.",
        "operationId": "affiliateMe",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AffiliateMeResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/affiliate/stats": {
      "get": {
        "tags": [
          "Affiliate"
        ],
        "summary": "Your traffic & earnings stats",
        "description": "Clicks (bots excluded), unique visitors, conversions, conversion rate, EPC, and lifetime earnings by status. `from`/`to` bound the period ([inclusive, exclusive); default all time). Pass `groupBy=subid` or `groupBy=campaign` for the per-placement breakdown — which content converts.",
        "operationId": "affiliateStats",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "groupBy",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AffiliateStatsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/affiliate/referrals": {
      "get": {
        "tags": [
          "Affiliate"
        ],
        "summary": "Your conversions",
        "description": "Your referred sales and their commissions, newest first, 50 per page. Filter with `status=` (pending | approved | reversed | paid). No buyer data is exposed — only amounts, dates, and your own subid/campaign tags.",
        "operationId": "affiliateReferrals",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AffiliateReferralsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/affiliate/payouts": {
      "get": {
        "tags": [
          "Affiliate"
        ],
        "summary": "Your payout history",
        "operationId": "affiliatePayouts",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AffiliatePayoutDto"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/affiliate/postback": {
      "put": {
        "tags": [
          "Affiliate"
        ],
        "summary": "Configure your S2S postback",
        "description": "Set the server-to-server conversion callback: an https URL on a public host (validated), plus which events fire it (sale, approved, reversed; default sale). Macros like {click_id}, {transaction_id}, {sale_amount}, {commission}, {status} are substituted at delivery. Send an empty url to clear the configuration.",
        "operationId": "affiliateSetPostback",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AffiliatePostbackUpdateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AffiliatePostbackDto"
                }
              }
            }
          }
        }
      }
    },
    "/admin/errors/dismiss": {
      "post": {
        "tags": [
          "PageSpeedAudit.Web"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DismissErrorRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/admin/errors/dismiss-all": {
      "post": {
        "tags": [
          "PageSpeedAudit.Web"
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/admin/errors/restore": {
      "post": {
        "tags": [
          "PageSpeedAudit.Web"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DismissErrorRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AffiliateCouponDto": {
        "required": [
          "percent",
          "code"
        ],
        "type": "object",
        "properties": {
          "percent": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "code": {
            "type": "string"
          }
        }
      },
      "AffiliateEarningsDto": {
        "required": [
          "pendingCents",
          "approvedCents",
          "paidCents",
          "reversedCents"
        ],
        "type": "object",
        "properties": {
          "pendingCents": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "approvedCents": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "paidCents": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "reversedCents": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          }
        }
      },
      "AffiliateGroupDto": {
        "required": [
          "key",
          "clicks",
          "uniqueVisitors",
          "conversions",
          "conversionRatePercent",
          "earnedCents",
          "epcCents"
        ],
        "type": "object",
        "properties": {
          "key": {
            "type": "string"
          },
          "clicks": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "uniqueVisitors": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "conversions": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "conversionRatePercent": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "earnedCents": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "epcCents": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          }
        }
      },
      "AffiliateMeResponse": {
        "required": [
          "referralCode",
          "referralLink",
          "commissionPercent",
          "cookieWindowDays",
          "coupons",
          "payoutsEnabled",
          "stripeOnboarded",
          "postback"
        ],
        "type": "object",
        "properties": {
          "referralCode": {
            "type": "string"
          },
          "referralLink": {
            "type": "string"
          },
          "commissionPercent": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "cookieWindowDays": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "coupons": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AffiliateCouponDto"
            }
          },
          "payoutsEnabled": {
            "type": "boolean"
          },
          "stripeOnboarded": {
            "type": "boolean"
          },
          "postback": {
            "$ref": "#/components/schemas/AffiliatePostbackDto"
          }
        }
      },
      "AffiliatePayoutDto": {
        "required": [
          "id",
          "createdAtUtc",
          "amountCents",
          "referralCount",
          "status"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAtUtc": {
            "type": "string",
            "format": "date-time"
          },
          "amountCents": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "referralCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "AffiliatePostbackDto": {
        "required": [
          "url",
          "events"
        ],
        "type": "object",
        "properties": {
          "url": {
            "type": [
              "null",
              "string"
            ]
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "AffiliatePostbackUpdateRequest": {
        "required": [
          "url",
          "events"
        ],
        "type": "object",
        "properties": {
          "url": {
            "type": [
              "null",
              "string"
            ]
          },
          "events": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            }
          }
        }
      },
      "AffiliateReferralDto": {
        "required": [
          "id",
          "createdAtUtc",
          "saleNetCents",
          "couponPercent",
          "commissionPercent",
          "commissionCents",
          "status",
          "maturesAtUtc",
          "subId",
          "campaign"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAtUtc": {
            "type": "string",
            "format": "date-time"
          },
          "saleNetCents": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "couponPercent": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "uint8"
          },
          "commissionPercent": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "commissionCents": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "status": {
            "type": "string"
          },
          "maturesAtUtc": {
            "type": "string",
            "format": "date-time"
          },
          "subId": {
            "type": [
              "null",
              "string"
            ]
          },
          "campaign": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "AffiliateReferralsResponse": {
        "required": [
          "page",
          "pageSize",
          "total",
          "referrals"
        ],
        "type": "object",
        "properties": {
          "page": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "pageSize": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "total": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "referrals": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AffiliateReferralDto"
            }
          }
        }
      },
      "AffiliateStatsResponse": {
        "required": [
          "fromUtc",
          "toUtc",
          "clicks",
          "uniqueVisitors",
          "conversions",
          "reversed",
          "conversionRatePercent",
          "epcCents",
          "earnings",
          "groupBy",
          "groups"
        ],
        "type": "object",
        "properties": {
          "fromUtc": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "toUtc": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "clicks": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "uniqueVisitors": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "conversions": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "reversed": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "conversionRatePercent": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "epcCents": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "earnings": {
            "$ref": "#/components/schemas/AffiliateEarningsDto"
          },
          "groupBy": {
            "type": [
              "null",
              "string"
            ]
          },
          "groups": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AffiliateGroupDto"
            }
          }
        }
      },
      "ApiKeyDto": {
        "required": [
          "id",
          "name",
          "keyPrefix",
          "createdAtUtc",
          "lastUsedAtUtc",
          "revoked"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "keyPrefix": {
            "type": "string"
          },
          "createdAtUtc": {
            "type": "string",
            "format": "date-time"
          },
          "lastUsedAtUtc": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "revoked": {
            "type": "boolean"
          }
        }
      },
      "AuditDto": {
        "required": [
          "id",
          "url",
          "status",
          "runsAllowed",
          "runsUsed",
          "runsRemaining",
          "hasActiveRun",
          "urlLockedAtUtc",
          "expiresAtUtc",
          "createdAtUtc"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": [
              "null",
              "string"
            ]
          },
          "status": {
            "type": "string"
          },
          "runsAllowed": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "runsUsed": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "runsRemaining": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "hasActiveRun": {
            "type": "boolean"
          },
          "urlLockedAtUtc": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "expiresAtUtc": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "createdAtUtc": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ContactRequest": {
        "required": [
          "email",
          "message"
        ],
        "type": "object",
        "properties": {
          "email": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "CreateApiKeyRequest": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          }
        }
      },
      "CreateApiKeyResponse": {
        "required": [
          "id",
          "name",
          "keyPrefix",
          "key",
          "notice"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "keyPrefix": {
            "type": "string"
          },
          "key": {
            "type": "string"
          },
          "notice": {
            "type": "string"
          }
        }
      },
      "CreateCheckoutRequest": {
        "required": [
          "email"
        ],
        "type": "object",
        "properties": {
          "email": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "CreateCheckoutResponse": {
        "required": [
          "checkoutUrl"
        ],
        "type": "object",
        "properties": {
          "checkoutUrl": {
            "type": "string"
          }
        }
      },
      "CreateRunRequest": {
        "required": [
          "url"
        ],
        "type": "object",
        "properties": {
          "url": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "CreateRunResponse": {
        "required": [
          "runId",
          "auditId",
          "runNumber",
          "status"
        ],
        "type": "object",
        "properties": {
          "runId": {
            "type": "string",
            "format": "uuid"
          },
          "auditId": {
            "type": "string",
            "format": "uuid"
          },
          "runNumber": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "DismissErrorRequest": {
        "required": [
          "fingerprint",
          "sample"
        ],
        "type": "object",
        "properties": {
          "fingerprint": {
            "type": "string"
          },
          "sample": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "MeDto": {
        "required": [
          "userId",
          "email",
          "audits"
        ],
        "type": "object",
        "properties": {
          "userId": {
            "type": "string",
            "format": "uuid"
          },
          "email": {
            "type": "string"
          },
          "audits": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AuditDto"
            }
          }
        }
      },
      "ProblemDetails": {
        "type": "object",
        "properties": {
          "type": {
            "type": [
              "null",
              "string"
            ]
          },
          "title": {
            "type": [
              "null",
              "string"
            ]
          },
          "status": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "detail": {
            "type": [
              "null",
              "string"
            ]
          },
          "instance": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "RunDto": {
        "required": [
          "id",
          "auditId",
          "runNumber",
          "status",
          "queuedAtUtc",
          "startedAtUtc",
          "finishedAtUtc",
          "errorCode",
          "availableReportFormats"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "auditId": {
            "type": "string",
            "format": "uuid"
          },
          "runNumber": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "status": {
            "type": "string"
          },
          "queuedAtUtc": {
            "type": "string",
            "format": "date-time"
          },
          "startedAtUtc": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "finishedAtUtc": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "errorCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "availableReportFormats": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "RunEventDto": {
        "required": [
          "type",
          "summary",
          "createdAtUtc"
        ],
        "type": "object",
        "properties": {
          "type": {
            "type": "string"
          },
          "summary": {
            "type": [
              "null",
              "string"
            ]
          },
          "createdAtUtc": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SubscribeRequest": {
        "required": [
          "email"
        ],
        "type": "object",
        "properties": {
          "email": {
            "type": "string"
          }
        }
      }
    },
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "description": "Your secret key, formatted `psa_live_…`. Send it in the **`X-Api-Key`** header on every request. Create and revoke keys from your dashboard; the secret is shown only once at creation.",
        "name": "X-Api-Key",
        "in": "header"
      }
    }
  },
  "tags": [
    {
      "name": "Checkout",
      "description": "Start a hosted Stripe Checkout for the one-time audit purchase. No authentication required."
    },
    {
      "name": "Contact",
      "description": "Contact-form intake. No authentication required."
    },
    {
      "name": "Affiliate"
    },
    {
      "name": "Audits",
      "description": "Your audit entitlements and runs — the core integration surface. Authenticated with an API key."
    },
    {
      "name": "API keys",
      "description": "Manage the keys that authenticate API requests. Dashboard-session only: an API key cannot mint or revoke keys."
    },
    {
      "name": "Newsletter",
      "description": "Double-opt-in newsletter subscription. No authentication required."
    },
    {
      "name": "PageSpeedAudit.Web"
    }
  ]
}