Account

Rate Limits

Per-key request limits, rate limit headers, and the size limits that apply to requests and posts.

Relaycast limits how fast each access key can call the API, and how large requests and posts can be. Platforms also enforce their own limits, which are covered in the platform guides.

Request rate limit

Each access key can make 120 requests per minute by default. The limit applies per key, so separate keys (for example one per service) each get their own allowance.

The window is fixed to the clock minute: the count resets at the start of each minute rather than sliding.

Headers

Authenticated responses include:

HeaderDescription
X-RateLimit-LimitRequests allowed per minute for this key.
X-RateLimit-RemainingRequests left in the current minute.
HTTP/1.1 201 Created
Content-Type: application/json
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 117
X-Request-Id: 2f6c0a3e-...

When you hit the limit

Requests over the limit get 429:

{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded, retry in a minute"
  }
}

There's no Retry-After header. Wait until the next minute starts, then retry with exponential backoff. For POST /v1/posts, retry with the same Idempotency-Key so a request that did get through isn't duplicated. See Idempotency & Retries.

retry.ts
async function withRateLimitRetry(doRequest: () => Promise<Response>, maxAttempts = 4) {
  for (let attempt = 1; ; attempt++) {
    const res = await doRequest();
    if (res.status !== 429 || attempt >= maxAttempts) return res;
    // Wait for the next minute window, plus a little jitter.
    const msToNextMinute = 60_000 - (Date.now() % 60_000);
    await new Promise((r) => setTimeout(r, msToNextMinute + Math.random() * 1_000));
  }
}

Rate-limited requests appear in Request Logs with status 429.

If the rate limiter itself is briefly unavailable, requests are allowed through rather than blocked, and the rate limit headers are left out of those responses. Don't treat missing headers as an error.

Staying under the limit

  • Fan out in one request. A single post can target up to 20 accounts, which counts as one request.
  • Use webhook notifications instead of polling GET /v1/posts/{id}.
  • Cache GET /v1/accounts. Accounts change rarely.
  • Use one key per service so a busy job can't starve another.

Size limits

LimitValue
Request body1 MB
content and targets[].content10,000 characters (platform limits are usually lower)
Targets per post1–20
Media items per post10
Media url length2,048 characters
Media altText1,000 characters
Media title (documents)400 characters
GET /v1/posts page sizelimit 1–100, default 20
Media library upload150 MB per file (dashboard)

Requests over 1 MB are rejected with 413 (payload_too_large) before they're processed. Media is passed by URL, so the body limit only covers the JSON itself.

Platform limits

Each platform has its own rules on text length, media count, file size, video duration and how often an account may post. Relaycast validates the static rules (such as character counts and media counts) when you create the post, so you get a 400 right away. Limits that only the platform knows, such as daily posting caps, surface at publish time as a failed target with errorCode: "rate_limited", which is retried automatically with backoff. See the platform guides.

Credits

Rate limits and credits are separate. A request within the rate limit can still fail with 402 if your project is out of credits. See Credits & Usage.

This page is also available as Markdown.