AgentMesh Catalog
document · railway.com

Railway API reliability

How the Railway API behaves under failure: the error convention and code catalog, rate limits and headers, retry/idempotency guidance, and the versioning/deprecation policy.

What it says

The document its publisher serves

the skill Read from the publisher's own address, not re-hosted.
# Railway API reliability

How the Railway API behaves under failure — errors, rate limits, retries, and
deprecation — in one place, so an agent can depend on it without guessing.

The public API is GraphQL at a single endpoint,
`https://backboard.railway.com/graphql/v2`. Authentication is covered in
<https://railway.com/auth.md>; the endpoint and OAuth surface are described in
<https://railway.com/openapi.json>.

## Errors

Railway follows the GraphQL error convention, not HTTP status alone. Always
inspect the `errors` array, not just the status code.

- **HTTP 200 with an `errors` array** — execution and authorization failures.
  A query that runs but is denied returns 200; the failure is in `errors`.
- **HTTP 400** — the request could not be parsed or validated (malformed JSON,
  unknown field, bad variable). `extensions.code` carries the reason.
- **HTTP 429** — rate limited. See below.

Every error object carries a `message`, an `extensions.code`, and a
`traceId`. Include the `traceId` when reporting a problem — it is how support
finds the request.

```json
{
  "errors": [
    {
      "message": "Cannot query field \"nope\" on type \"Query\".",
      "extensions": { "code": "GRAPHQL_VALIDATION_FAILED", "traceId": "7992771584715554281" }
    }
  ],
  "data": null
}
```

Common `extensions.code` values:

| Code | Meaning | HTTP |
| --- | --- | --- |
| `GRAPHQL_PARSE_FAILED` | The query is not valid GraphQL syntax | 400 |
| `GRAPHQL_VALIDATION_FAILED` | The query references unknown fields or types | 400 |
| `BAD_USER_INPUT` | A field or variable failed validation | 400 |
| `INTERNAL_SERVER_ERROR` | An unexpected error, or an authorization denial (message `Not Authorized`) | 200 |

## Rate limiting

The API is metered per hour, per account or workspace token. The base budget is
**1,000 requests per hour** (60-minute window). Some
plans raise this; the response headers below always report the limit that
applies to your token.

Authenticated responses carry standard rate-limit headers so you can
self-throttle:

| Header | Meaning |
| --- | --- |
| `X-RateLimit-Limit` | Requests allowed in the window |
| `X-RateLimit-Remaining` | Requests left in the current window |
| `X-RateLimit-Reset` | ISO-8601 time the window resets |
| `RateLimit-Policy` | The limit and window, advertised on every response (even unauthenticated) |

When you exceed the limit the API returns **HTTP 429** with a `Retry-After`
header (seconds). Back off until then; do not retry immediately.

## Retries

- **Reads (queries) are safe to retry.** They have no side effects.
- **Writes (mutations):** retry only on a network error or a 429/5xx where you
  did not receive a response. If you received a 200, the mutation ran — retrying
  may duplicate it. Most Railway mutations are keyed on the resource they act
  on, so a retry with the same arguments generally converges, but do not assume
  exactly-once.
- **Back off exponentially** and honor `Retry-After` on a 429.
- Carry the `traceId` from a failed response into any support request.

## Versioning and deprecation

Railway's public API is GraphQL, so **the schema is the contract**. New fields
and types are added without a version bump — additive changes never break an
existing query.

Fields being retired are marked `@deprecated` in the schema with a reason.
Introspect with `includeDeprecated: true` to see them:

```graphql
{ __type(name: "Project") { fields(includeDeprecated: true) { name isDeprecated deprecationReason } } }
```

Prefer non-deprecated fields; a deprecated field keeps working through its
sunset window and is removed only after it has been marked for a meaningful
period.

## Status and incidents

- **Status page:** <https://status.railway.com> — current platform status and
  incident history.
- **Webhooks:** react to deployment and service events instead of polling.
  Delivery is best-effort — each event is POSTed with a 30-second timeout and
  retried up to 3 times with exponential backoff, treated as delivered on any
  2xx/3xx — and carries no cryptographic signature, so authenticate the sender
  with a secret embedded in the webhook URL and reconcile against the API rather
  than treating a webhook as a guaranteed ledger. See
  <https://docs.railway.com/observability/webhooks>.

## Related

- Authentication: <https://railway.com/auth.md>
- OpenAPI description: <https://railway.com/openapi.json>
- API documentation: <https://docs.railway.com/integrations/api>
- Status: <https://status.railway.com>

## Open this page

<https://railway.com/api-reliability.md>
What this is

Document

text/markdownlast seen 2026-10-04

These are the publisher's own words, read from what they serve at their own address.

Terms

Somebody else's record

This listing was indexed rather than published here, so nobody has signed anything and this catalog cannot sign on their behalf. Treat it as a pointer to the publisher, not as terms.

Where it lives

The publisher's own address

https://railway.com/api-reliability.md

This catalog links to it and never serves a copy, so what you get is whatever railway.com is serving now.

In its own words

What its publisher says you would ask it

  • how does the Railway API report errors
  • is the Railway API safe to retry
  • what are the Railway API rate limits
Tags

How its publisher filed it

docsapireliability