API conventions for authentication, pages, errors and rate limits
Every operation of the SrvYard API follows the same small set of rules. Learn them once and you can read any endpoint in the reference without surprises: how you authenticate, what a list looks like, how to ask for the next page, what an error contains, and what to do when you are slowed down.
This article walks through those rules in the order a script meets them, and shows where each one is written down in the dashboard. It assumes you have a token already; if not, start with Create an API token and pick scopes.
Before you begin
- A token with the scopes you need. Each operation names the scope it requires. A token can never do more than the role of its owner allows.
- A plan with API access. Without it every call is answered
403with the codeplan_required. - Any HTTP client. The examples use
curl, but nothing is specific to it. Always sendAccept: application/json.
1. Authenticate every request
The API lives under /api/v1 on your SrvYard address, and every request carries the token in a header:
curl -H "Authorization: Bearer $SRVYARD_TOKEN" \
-H "Accept: application/json" \
https://srvyard.example/api/v1/servers
The token decides which organisation you are talking to, so no organisation id appears in any URL. Resources of another organisation answer 404, never 403, so a token cannot be used to find out which ids exist elsewhere.
The cheapest way to test a token is GET /api/v1/token. It needs no scope and returns the token's name, organisation, scopes, expiry and last use.
Four things can go wrong before the request reaches an endpoint, and each has its own message:
| Status | Code | What it means |
|---|---|---|
401 |
unauthenticated |
No header, not a srv_ token, or the token is unknown or revoked. |
401 |
token_expired |
The token passed its expiry date. |
403 |
plan_required |
The organisation's plan has no API access. |
403 |
missing_scope |
The token lacks the scope this operation needs; the answer names it. |
2. Read an operation in the reference
Open Settings > API tokens > Reference, choose a group and open an operation. Every operation row follows the same pattern.
- The scope badge.
servers:viewis the permission the token needs. Your role must hold it as well. - Parameters. For a list:
page,per_page,sortand thefilter[...]fields this endpoint understands, each with a one-line description. A red star marks a required one. - Example response and example request. The response is an example of the shape, not real data; values such as
stringare placeholders. The example request is acurlcommand you can copy.
Underneath, the line Errors lists the failure statuses the operation can return.
3. Lists: pages, sorting and filters
Every list answers with a data array plus paging information:
pagestarts at 1.per_pagedefaults to 25 and is capped at 100. Larger values are lowered to 100.sorttakes a comma-separated list of fields; a leading-means descending, for examplesort=-created_at. The allowed fields are listed on each operation, and an unknown one is rejected with422.filter[name]=...narrows the list. Most filters match exactly, and several values can be given separated by commas (filter[status]=ready,disconnected);filter[name]matches names that contain the text. An unknown filter is rejected with422and the message lists the allowed ones.include=...on the operations that support it adds related data.
curl -G -H "Authorization: Bearer $SRVYARD_TOKEN" -H "Accept: application/json" \
--data-urlencode "filter[status]=ready" \
--data-urlencode "sort=-created_at" \
--data-urlencode "per_page=50" \
https://srvyard.example/api/v1/servers
Ids are always UUIDs, dates are ISO-8601, and no internal numeric ids or secrets ever appear. A secret that SrvYard generates for you (a new database password, a backup passphrase) is returned once, in the response that created it.
4. Find the operations a scope unlocks
When you build a token you often know the scope and need the endpoints, or the reverse.
- Search endpoints, scopes. Matches the method, the path, the summary, the operation name and the scope. Typing
sites:manage-deploysshows the groups that contain operations with that scope. - The result list. Each row shows the method, the path, what it does, an async badge where relevant and the scope.
Use this to choose the smallest set of scopes for a token.
5. Work that runs in the background
Anything that needs the server (deploying, installing, rebooting, creating a server) does not make you wait. The call returns 202 Accepted straight away with the resource and a status_url, which is also sent in the Location header.
- async. The operation answers
202and finishes later. - The scope. Here
sites:manage-deploys, the same permission as the Deploy button in the dashboard. - The response. Contains the new resource and its
status_url. The example shows the shape of a deployment object; a deployment you have just queued starts asqueued.
Poll status_url with GET until status reaches a final value: ready or failed for servers and sites, finished, failed or cancelled for deployments. Every few seconds is plenty. A delete that needs remote work returns the resource in a deleting state first and answers 404 once it is gone.
6. Errors
Every error from /api/* has the same shape (RFC 9457, content type application/problem+json):
{
"type": "https://srvyard.example/api/v1#forbidden",
"title": "Forbidden",
"status": 403,
"detail": "Your API token or the role of its user does not allow this action.",
"code": "forbidden",
"missing_scope": "servers:create",
"request_id": "..."
}
- Branch on
code, not on the wording ofdetail. Common codes:validation_failed(422),unauthenticated,token_expired,forbidden,missing_scope,plan_required,plan_limit(402),not_found,idempotency_conflict(409) andrate_limited(429). - A
422carries anerrorsobject with one list of messages per field. - A
402withplan_limitmeans the organisation hit a limit of its plan, for example the number of servers. - Every response, success or failure, has an
X-Request-Idheader, repeated in the body asrequest_id. Quote it when you contact support.
- The summary line. JSON over HTTPS, versioned under
/api/v1, 60 requests a minute per token. - The error paragraph. An example
403and what401,403and429mean, always visible on the Tokens tab.
7. Retry safely with idempotency keys
A network timeout on a POST leaves you unsure whether the deployment was queued. Send an Idempotency-Key header (1 to 255 printable characters, no spaces, unique per action) on POST, PUT, PATCH and DELETE:
curl -X POST -H "Authorization: Bearer $SRVYARD_TOKEN" -H "Accept: application/json" \
-H "Idempotency-Key: deploy-2026-10-24-build-1187" \
https://srvyard.example/api/v1/sites/<site-id>/deployments
- The same key with the same request within 24 hours replays the first response, with the header
Idempotent-Replayed: true. Nothing is queued twice. - The same key with a different body or URL answers
409 idempotency_conflict. A request that is still running with that key also answers409. - Keys belong to one token. Server errors and rate-limit answers are not stored, so those can be retried with the same key.
- The
.envupdate and token creation are never stored, because their bodies hold secrets.
8. Rate limits
A token may make 60 requests a minute. The heavier operations (scans, exports, installs) allow 10 a minute in a separate bucket. Every answer carries X-RateLimit-Limit and X-RateLimit-Remaining; when you run out you get 429 with the code rate_limited and a Retry-After header holding the seconds to wait.
Do not loop faster than you need. Poll a status_url every five seconds rather than every hundred milliseconds, ask for per_page=100 instead of walking small pages, and wait for Retry-After before trying again.
Changes are announced ahead of time: a breaking change would ship as /api/v2, and an operation being retired is flagged with the Deprecation and Sunset headers and deprecated: true in openapi.json. Every successful change you make through a token is written to the activity log with the actor token:<name>, without the request body.
Troubleshooting
422with "Unknown filter" or "Unknown sort". You used a field the endpoint does not support. The message lists the allowed ones; the reference shows the same list.404for something you can see in the dashboard. The token belongs to another organisation, or the id is from a different one. CheckGET /api/v1/token.403 missing_scope. Readmissing_scopein the answer and create a token that includes it.409 idempotency_conflict. You reused a key for a different request. Generate a new key per action, and reuse one only for retries of the same call.429even though you are slow. Several jobs may share one token. The limit is per token; give each job its own.- The list is shorter than expected. Lists are paged at 25 by default. Add
per_page=100, or follow the pages. - A
202call never finishes. Pollstatus_urland readlast_erroror the log of the deployment. See A deployment failed.
Related
- Create an API token and pick scopes: the token these rules apply to.
- List servers and sites, trigger actions: the first calls to make.
- Event payloads and signatures: the other direction, SrvYard calling you.
- Rotate tokens and review the sign-in log: keep tokens short-lived.