PageSpeedAudit Developers · Changelog

What changed, when, and what you have to do.

Every entry is dated to the day it reached production and says whether it was additive, a change to existing behaviour, or a fix toward what the contract already promised. A breaking change would ship under a new path version and be announced here first — none has. Dates are the days the repository's history records each surface reaching production.

Version
v1.0.0 · /api/v1
Last contract change
Findings document
pagespeed-audit/findings@1
OpenAPI
/openapi/v1.json

Entries

    • Additive Dry-run quotes on POST /orders

      { "dryRun": true } resolves the unit price, wholesale discount, daily ceilings and payment route exactly as a real order would, then creates nothing and charges nothing. It needs no Idempotency-Key and is the request the interactive reference sends by default. The operation's burst limit — 5 requests per minute per account — counts dry runs.

      Action required
      None. Existing orders behave exactly as before.
    • Changed Ordering needs an API key; a signed-in session is refused

      POST /orders, GET /orders and GET /orders/{orderId} now answer 403 api_key_required to a browser session. Scopes narrow keys, not people, so a signed-in session used to pass the purchase check — which meant the request console on the reference page could place a real order for anyone who was merely signed in. The dashboard never ordered through these operations, so nothing that worked by design stops working.

      Action required
      None for integrations, which always used a key. A script that reused a browser cookie to order must use a purchase-scoped key.
    • Additive 402 problems carry the order they refused

      402 authentication_required and 402 card_declined now carry the recorded order's orderId as a problem member, and authentication_required also carries the checkoutUrl that finishes the payment in a browser. Before, a caller had to list GET /orders to find either.

      Action required
      None. New members beside the existing code, status, detail.
    • Additive Every problem response links to its catalog entry

      Problem responses now carry a type of https://pagespeedaudit.com/docs/errors#{code} and a title (the status's reason phrase) beside the unchanged code, status and detail. Ownership failures that answered an empty 404 now carry a problem body with code not_found. The checkout, newsletter and contact refusals, which carried only a message, now carry codes too: unusable_email, checkout_unavailable, invalid_email, disposable_email, invalid_message — the message moved from title to detail on the two checkout refusals.

      Action required
      None for clients that branch on status or code. A client that read the checkout refusal's title as the message reads detail.
    • Fixed Affiliate validation errors use the documented problem+json shape

      Invalid dates, an unknown groupBy or status, and an unusable postback answered { "error": "…" }, contrary to the contract. They are now problem+json with codes invalid_date, invalid_group_by, invalid_status, invalid_postback_events and invalid_postback_url; an account without an affiliate profile is 403 not_an_affiliate on every affiliate operation. Status codes are unchanged.

      Action required
      A client that parsed the old error field — on the three operations with input validation, or on the 403 every affiliate operation returns — reads detail (the same text) and code instead.
    • Fixed API-key management is documented as dashboard-session only

      The OpenAPI document declared the API-keys operations behind the X-Api-Key scheme, which they have always refused. They now declare the DashboardSession cookie scheme, and an API key that calls them gets 403 dashboard_session_required with a body instead of an empty 403. 409 on key creation now carries duplicate_key_name or key_limit_reached.

      Action required
      None for correct integrations; keys are still created and revoked at /account/api-keys.
    • Changed Developer portal at /docs; the interactive reference moved to /docs/reference

      /docs is now the guides, quickstart, schemas and error catalog; the generated reference lives at /docs/reference. /openapi/v1.json and /docs/openapi/v1.json are unchanged.

      Action required
      Update bookmarks to the reference; the OpenAPI document URL is the same.
    • Additive Saved-card charging on POST /orders

      An account that saved a card under Billing and consented to off-session charging is charged immediately: the response is 202 with paymentRoute: charge and the credits arrive when settlement lands. A card that needs the cardholder present is 402 authentication_required with a Checkout URL on the order; a declined card is 402 card_declined. Accounts without a saved card still get 201 and a Checkout URL.

      Action required
      None unless the account saves a card — then poll GET /orders/{orderId} for completed instead of sending a buyer to a URL.
    • Additive Ordering through the API: POST /orders, GET /orders, GET /orders/{orderId}

      Orders audit credits on the account with a required Idempotency-Key; an approved reseller's wholesale price is applied server-side. Guardrails: 5 orders per minute, per-account daily ceilings (429 daily_limit_reached), a platform backstop (503 ordering_paused) and a kill switch (503 ordering_disabled).

      Action required
      None. Requires a key created with the purchase scope.
    • Additive API key scopes: read, run, purchase

      Keys carry scopes chosen at creation. A key created without a list gets read and run — the authority every existing key already had — so nothing that worked stopped working. purchase is never implicit. Calling an operation without its scope is 403 insufficient_scope, naming the scope. Starting a run and creating a Target Finder analysis need run; everything else on audits and analyses needs read.

      Action required
      None for existing keys. Create a purchase key only for an integration that orders.
    • Additive Lead attribution on affiliate stats

      GET /affiliate/stats carries a leads object — unconfirmed, confirmed and converted leads, split by source. Lifetime figures; they ignore from/to.

      Action required
      None.
    • Additive API v1 — first recorded in this repository

      Checkout sessions, audits and runs (start, poll, timeline, report download as findings JSON or self-contained HTML), dashboard-session API-key management, the affiliate API (profile, stats, referrals, payouts, postback), newsletter subscription and contact intake. OpenAPI 3.1 at /openapi/v1.json; problem+json errors with a stable code. This is the earliest date the repository's history records for the surface.

      Action required

Versioning and deprecation

The rules a change has to follow.

Additive on v1

New operations, new optional fields, new error codes and new example values may appear on /api/v1 at any time. Existing fields are never removed, renamed or retyped; existing status codes and code values keep their meaning.

Breaking means a new path

Anything a correct v1 client could not absorb ships as /api/v2. v1 keeps working through a published sunset window; the window and the migration notes appear on this page before the new version does.

The findings document

The schema id pagespeed-audit/findings@1 covers additive change the same way. A change that breaks a consumer of the document becomes a new schema id, announced here, with both formats available for a window.

Fixes toward the contract

When the implementation is found to differ from what the reference already documents — a wrong error shape, a missing security scheme — it is fixed and recorded as Fixed, with the old and new behaviour stated, so a client that depended on the mistake can see what to do.

Operational status

Live, from the same checks the deploy gate reads.

Checked · refreshed at most once a minute

  • API and database Operational
  • Audit processing (worker heartbeats) Operational

Machine-readable: /healthz/ready answers 200 when the API can serve and 503 when it cannot. No incident history is published yet; when one is, it will live here.