Get started
Errors
The error format, when to retry, and every code the API can return.
An error always has the same shape, whatever the call:
{
"error": {
"type": "invalid_request",
"code": "parameter_invalid",
"message": "Invalid parameter: limit.",
"param": "limit",
"doc_url": "https://docs.rustine.io/api/errors#parameter_invalid"
}
}
type: the category, to know who must act (you, your plan, or Rustine).code: the exact case. This is what your code should test.message: a sentence for a human, in the language of the key’s owner. Log it, do not test it: its wording may change.param: withinvalid_request, the parameter at fault.doc_url: the line of this page that explains the code.upgrade_url: withplan_limit, where to change plans or buy a pack.
Every response also carries a Request-Id header: give it to support if an error keeps coming back.
When to retry
429: yes, after the number of seconds in theRetry-Afterheader.500,502and503: yes, a little later. For a write, send the sameIdempotency-Keyagain: the action will not run twice.409 idempotency_in_progress: yes, in a moment.- Other
4xx: no. The same request will get the same answer; fix it first, or change plans for a402.
Every code
| error.code | HTTP | What it means |
|---|---|---|
| body_invalid | 400 | The request body is not valid JSON. Check the Content-Type: application/json header. |
| cursor_invalid | 400 | starting_after is not the id of an item of this list. |
| idempotency_key_invalid | 400 | The Idempotency-Key header must be 1 to 255 printable characters. |
| parameter_invalid | 400 | A parameter is missing or invalid; param names it. |
| reason_required | 400 | Marking a false positive or an accepted risk needs a reason, 10 to 500 characters. |
| target_kind_invalid | 400 | The scan kind does not fit the target: repository for a GitHub repository, quick or audit for a site. |
| url_invalid | 400 | The address is not the valid URL of a public site. |
| url_private | 400 | Rustine only scans public sites, never a local or private address. |
| authentication_required | 401 | No key in the request. Pass it in the Authorization: Bearer rst_… header, never in the address. |
| invalid_api_key | 401 | The key or OAuth token is wrong, revoked or expired. Check it is copied in full, or create a new key. |
| address_limit_reached | 402 | The project already follows as many addresses as your plan allows. |
| api_plan_required | 402 | The workspace is on the Free plan. The API comes with Pro, or on a 14-day trial with Solo. |
| api_trial_ended | 402 | Solo's 14-day trial is over. Move to Pro: your keys work again at once. |
| audit_not_in_plan | 402 | The Free plan runs quick scans only; the full audit comes with Solo and Pro. |
| audit_quota_exceeded | 402 | This period's full audits are used up, and no pack credit is left. |
| domain_taken | 402 | On the Free plan, a domain another free account already follows cannot be added or scanned. |
| fix_quota_exceeded | 402 | This period's fixes are used up, and no pack credit is left. A fix already unlocked stays readable. |
| plan_limit | 402 | Your plan does not include this action. upgrade_url leads to the plan that allows it. |
| project_limit_reached | 402 | All your plan's projects are in use. Add an extra project or change plans. |
| project_paused | 402 | The project is paused: your plan covers fewer projects than your workspace has. Its issues stay readable, but nothing new runs. |
| repositories_not_in_plan | 402 | GitHub repository analyses come with Solo and Pro. |
| scan_quota_exceeded | 402 | This period's quick scans are used up, and no pack credit is left. |
| scope_missing | 403 | The OAuth token lacks the permission this route needs (shown on its page). Reconnect the agent to grant it. An API key has every permission. |
| fix_locked | 404 | The fix of this issue is not unlocked yet: POST /issues/{issue_id}/fix unlocks it. |
| resource_not_found | 404 | Nothing with this id in the key's workspace. An object of another workspace answers the same: its existence is never revealed. |
| route_not_found | 404 | This route does not exist. Check the method and the path in the reference. |
| conflict | 409 | The request does not fit the object's current state. Read it again, then retry. |
| github_unavailable | 409 | GitHub repository analyses are not available right now. |
| idempotency_conflict | 409 | This Idempotency-Key was already used for another request (method, path or body). A new action takes a new key. |
| idempotency_in_progress | 409 | A request with this Idempotency-Key is still running. Retry in a moment. |
| issue_already_fixed | 409 | The issue is fixed: there is nothing to mark. |
| proof_required | 409 | The site must first be proved yours (full audit, fix, marking). Prove it in the app: DNS, file or meta tag. |
| site_excluded | 409 | The owner of this site asked not to be scanned. Rustine will not scan it. |
| target_exists | 409 | The project already follows this address. |
| rate_limited | 429 | Too many requests for this key (120 per minute). Wait Retry-After seconds. |
| recheck_limit_reached | 429 | Too many rechecks on this project today (60 per day). Try again tomorrow. |
| repository_analyses_limit_reached | 429 | The workspace started many repository analyses in the last 24 hours. Try again later. |
| internal_error | 500 | An error on our side, reported automatically. Retry later; give the Request-Id to support if it comes back. |
| recheck_failed | 502 | The recheck could not complete (site unreachable?). Check the site answers, then retry. |
| platform_busy | 503 | Rustine is not starting new scans for a few minutes. Retry later; nothing was charged. |
| service_unavailable | 503 | Rustine is unavailable for a moment. Retry with the same Idempotency-Key. |
Types
Test type to decide what to do, code to know exactly what happened.
| error.type | What it means |
|---|---|
| invalid_request | The request itself needs fixing. |
| authentication | The key or token is not accepted, or lacks the permission. |
| plan_limit | The plan or the quota does not allow it; upgrade_url says what to do. |
| not_found | The object or the route does not exist for this key. |
| rate_limited | Too many requests, or a ceiling reached: wait a little. |
| conflict | The action does not fit the current state (unproved site, key already used…). |
| api_error | A problem on Rustine's side: retry. |