Auto Schedule API

Errors

Seven codes, one envelope. The endpoint has no request body, so almost every failure is about the key, the id or the plan rather than about what you sent.

The error envelope

404 Not Found
{
  "success": false,
  "error_code": "web_page_not_found",
  "error_message": "Web page not found."
}
FieldTypeDefaultDescription
successboolean—Always false on an error.
error_codestring—A stable token. Branch on this, never on the message.
error_messagestring—Human-readable. Its wording is not part of the contract.
retry_after_secondsinteger—Present on rate_limited. Mirrored in the Retry-After header. Absent on every other code.

Nothing internal travels with it: no wrapper object, no internal code, no details and no stack trace. It is the same envelope the Instant Snap API uses, so one error handler can serve both.

Every code

Error code, the status it arrives with, and what to do.
FieldTypeDefaultDescription
api_key_invalid401Do not retryMissing, malformed, deleted or unknown key. All four answer identically, so the endpoint cannot be used to discover which keys exist.
web_page_id_invalid400Do not retryThe path segment is not a UUID. A malformed id is a client mistake, so it is a 400 rather than a 404.
web_page_not_found404Do not retryNo such scheduled page for this key’s account — including a page that exists but belongs to somebody else. See below.
no_trigger_allowance403Do not retryThe subscription has no capture allowance left, or is not permitted to start one right now.
feature_not_available403Do not retryThe plan does not include API triggering. Not a 402: no amount of waiting or usage turns it into a yes, only a different plan does.
sitemap_schedule_not_triggerable409Do not retryThe web page is a sitemap schedule. Sitemap schedules run only on their schedule - a run captures up to 1,000 pages over hours - so they cannot be triggered.
rate_limited429RetryPast your plan's API rate limit, or too many requests from your address — or the bad-key lockout, which answers with a fifteen-minute Retry-After.
service_unavailable503RetryThe trigger could not be handed to the capture service. Temporary; retry_after_seconds says when to try again. The same token and status as on the Instant Snap API.

Why 404 and not 403

Not an existence oracle

A web page id that belongs to another account answers web_page_not_found, exactly as an id that never existed does. Answering 403 instead would confirm that the id is real, and anyone could then map out which ids exist by trying them.

So a 404 means one of three things, and the API will not tell you which:

  • The id is wrong — a typo, or an id from a different environment.
  • The schedule was deleted.
  • The key belongs to a different account from the schedule.

The third is the one worth checking first when a call that used to work stops working after a key rotation.

Answers that are not errors

already_pending is a success

It arrives as 200 with "success": true. Code that treats any answer other than triggered as a failure will report errors that never happened — and, worse, will often retry into a capture that is already running.
Branching correctly
const result = await response.json();

if (!result.success) {
  if (result.error_code === "rate_limited") return retryAfter(result);
  throw new Error(result.error_code);
}

if (result.status === "already_pending") {
  // Not an error. A capture is already running.
  return;
}

Read success first to separate failures from successes, then read status to tell the two successes apart.

What to retry

ValueMeaning
Retry: 429, 503Throttling and an unreachable capture service both clear on their own. Honour retry_after_seconds where it is given, cap your attempts, add jitter.
Never retry: 400, 401, 403, 404The identical call will fail identically. The id, the key or the plan has to change first.

Codes this page does not list

Every refusal this service can produce is in the table above; a code outside it would be reported as internal_error. If you meet one, treat it as a transient fault — log it, retry once, and do not branch on it.

Did this page answer your question?

Tell us what is missing