Errors use the standard envelope:
Branch on code, not on the message. Codes are stable; messages are not.
A job that ran and failed is reported as HTTP 200 with status: "failed" and a terminal error — the request succeeded, the scrape did not. Only failures that happen before or instead of a job use the error envelope above. See Jobs & Webhooks.

Your request needs changing

Retrying these unchanged will fail the same way. endpoint_not_enabled is not a token problem, and minting a new key will not fix it. A few endpoints are restricted to organizations that have been granted them; the restriction is on the organization, not the credential. Contact support to request access. This is distinct from insufficient_scope, which means the token you sent was issued without the scope this method needs — that one you can fix yourself by issuing a token that has it.

The target refused or had nothing

The request was fine; the target was the problem. challenge, login_required, and forbidden all mean you received no content, so all three are refunded. They are reported separately because they call for different responses: a challenge may succeed from a different route, while a login wall never will.

Temporary — retry with backoff

All of these are refunded. provider_error and provider_data_missing are permanent for a given attempt despite the 502 — an immediate repeat reaches the same answer — so both are refunded but neither is worth retrying straight away. provider_data_missing differs in that the target may simply have no data yet: a scrape scheduled for later is still worth running, where a rejected input will keep being rejected.

Ours

Refunds

You are not charged for a job that returned no content. Refunds are automatic and land within a minute — you do not need to ask. Confirm with:
creditsSpent and creditsRefunded are reported separately per action, so you can see refunds rather than inferring them from a smaller total. What is not refunded is a job that gave you a correct answer you did not want: not_found, domain_parked, bad_feed, and the caller-error codes. We did the work and the answer is real — the target genuinely is not there.