url_requiredHTTP 400
- When
- The first run of an audit was started without a URL.
- Recovery
- Pass
urlon the first run; it is locked to the audit from then on. - Answered by
- POST
/api/v1/audits/{auditId}/runs
PageSpeedAudit Developers · Error catalog
Every refusal the API makes on purpose is RFC 9457 problem+json. Branch on code — it is
stable — and never on detail, which is free to improve. The type on every
such response is a link to its row on this page, so the error in your terminal is one click from its
recovery. Three answers carry no body: a bare 401, 429 and 500.
{
"type": "https://pagespeedaudit.com/docs/errors#runs_exhausted",
"title": "Conflict",
"status": 409,
"detail": "All included runs have been used.",
"code": "runs_exhausted"
}43 codes
url_requiredHTTP 400
url on the first run; it is locked to the audit from then on./api/v1/audits/{auditId}/runsinvalid_urlHTTP 400
https://example.com/; private, local and non-http addresses are refused.invalid_formatHTTP 400
format was something other than json or html.format=json for the findings document or format=html for the customer report./api/v1/runs/{runId}/reportinvalid_quantityHTTP 400
quantity is below 1 or above the per-order maximum.detail; split larger volumes into several orders./api/v1/ordersidempotency_key_requiredHTTP 400
Idempotency-Key header (or idempotencyKey in the body)./api/v1/ordersunknown_scopeHTTP 400
read, run and purchase./api/v1/apikeysunusable_emailHTTP 400
email and let Checkout collect it./api/v1/checkout/sessionsinvalid_dateHTTP 400
from or to is not an ISO 8601 date.2026-07-01 or 2026-07-01T00:00:00Z./api/v1/affiliate/statsinvalid_group_byHTTP 400
groupBy was something other than subid or campaign.groupBy=subid, groupBy=campaign, or omit it for totals only./api/v1/affiliate/statsinvalid_statusHTTP 400
status was not one of the referral states.pending, approved, reversed or paid, or omit it./api/v1/affiliate/referralsinvalid_postback_eventsHTTP 400
events named an event the postback cannot fire on.sale, approved, reversed; omit the list for sale only./api/v1/affiliate/postbackinvalid_postback_urlHTTP 400
detail says which.url to clear it./api/v1/affiliate/postbackinvalid_emailHTTP 400
disposable_emailHTTP 400
/api/v1/newsletter/subscribeinvalid_messageHTTP 400
/api/v1/contactauthentication_requiredHTTP 402
orderId and a checkoutUrl.checkoutUrl from the problem body in a browser to finish the payment; poll GET /orders/{orderId} for completed. Nothing was charged./api/v1/orderscard_declinedHTTP 402
detail says which. The problem carries the recorded order's orderId.detail says declined, nothing was charged: ask the account holder to update the card under Billing, then order again with a new Idempotency-Key. If detail says the charge did not complete, the outcome is unknown: read GET /orders/{orderId} before retrying./api/v1/ordersinsufficient_scopeHTTP 403
detail names it.purchase is never implicit./api/v1/audits/{auditId}/runsPOST /api/v1/ordersGET /api/v1/orders/{orderId}GET /api/v1/ordersPOST /api/v1/target-finder/analysesGET /api/v1/meGET /api/v1/auditsGET /api/v1/audits/{auditId}GET /api/v1/audits/{auditId}/runsGET /api/v1/runs/{runId}GET /api/v1/runs/{runId}/eventsGET /api/v1/runs/{runId}/reportGET /api/v1/target-finder/analyses/{analysisId}GET /api/v1/target-finder/analysesdashboard_session_requiredHTTP 403
api_key_requiredHTTP 403
purchase scope, or buy on /pricing. A session is deliberately never enough to place an order here.customers_onlyHTTP 403
/api/v1/target-finder/analysesnot_an_affiliateHTTP 403
cross_site_requestHTTP 403
X-Api-Key credential — the supported way to call this API from anywhere — or make the request from this site's own origin. This is a cross-site request forgery guard, not a permission check: the credential is fine, the origin is not.not_foundHTTP 404
GET /audits, GET /orders or GET /target-finder/analyses listings; an audit listed as Revoked has no readable runs.report_not_readyHTTP 404
GET /runs/{runId} until status is Succeeded; a Failed or TimedOut run has no report and did not consume a run./api/v1/runs/{runId}/reportaccount_not_foundHTTP 404
/api/v1/ordersurl_lockedHTTP 409
url or send the same one. A different page needs its own audit./api/v1/audits/{auditId}/runsrun_in_progressHTTP 409
/api/v1/audits/{auditId}/runsruns_exhaustedHTTP 409
/api/v1/audits/{auditId}/runsexpiredHTTP 409
/api/v1/audits/{auditId}/runsrevokedHTTP 409
/api/v1/audits/{auditId}/runsidempotency_key_reusedHTTP 409
Idempotency-Key was already used for an order with different parameters./api/v1/orderswholesale_unavailableHTTP 409
/api/v1/ordersaccount_email_missingHTTP 409
/api/v1/ordersurl_already_lockedHTTP 409
/api/v1/target-finder/analysesduplicate_key_nameHTTP 409
/api/v1/apikeyskey_limit_reachedHTTP 409
/api/v1/apikeysdaily_limit_reachedHTTP 429
/api/v1/ordersanalysis_limit_reachedHTTP 429
/api/v1/target-finder/analysescheckout_unavailableHTTP 502
/api/v1/checkout/sessionsordering_disabledHTTP 503
/api/v1/ordersordering_pausedHTTP 503
/api/v1/orderstarget_finder_disabledHTTP 503
/api/v1/target-finder/analysesHTTP 401empty body
X-Api-Key header is missing, malformed, revoked, or the account is blocked. Empty body.X-Api-Key. A revoked key never works again — create a new one.HTTP 429empty body
POST /orders (dry runs included). Empty body.HTTP 500empty body
POST /orders, read GET /orders first: the outcome is unknown and a charge may have completed. Elsewhere, retry once after a short wait, then contact support with the time and path.No code matches that filter.
How to branch
switch (problem.code) {
case "run_in_progress": // poll the active run; do not restart
case "runs_exhausted": // buy another audit or an extra run
case "url_locked": // reuse the locked URL
case "insufficient_scope": // create a key with the named scope
case "daily_limit_reached": // wait for 00:00 UTC
default: // surface status + detail; never retry blindly
}Three rules that keep an integration safe
card_declined whose detail says the charge did not complete. On a 500 from POST /orders the outcome is unknown: read GET /orders before retrying.run_in_progress and idempotency_key_reused exist so a retried request can never spend twice.