Errors & rate limits
Status codes, what an error looks like, the limits that exist, and what is safe to retry.
An error is a status code and a plain-text sentence saying what went wrong and, usually, what to do about it:
HTTP/1.1 409 Conflict
request-id: 8f3d1b47-6a2e-4c90-b5d8-0e71fa3c26b9
content-type: text/plain; charset=utf-8
https://app.yourapp.com/webhooks is still sealing deliveries to this key. Assign that endpoint another key first.Branch on the status, log the sentence, and show neither to your users — the wording can change.
Every signed request gets a request-id header, error or not. It is the id of that call's
row in request logs, refused calls included — quote it in
Discord and we can see exactly what happened.
Status codes
| Status | Meaning | Retry? |
|---|---|---|
400 | The request is malformed | No — fix the call |
401 | The signature was refused — see Signing requests | No — fix the signature |
404 | No such resource, or not yours | No |
409 | Conflicts with current state | After re-reading |
422 | Valid, but not possible — e.g. a workout push to a provider without one | No |
429 | Rate limited | Yes, after a minute |
5xx | Our side | Yes, with backoff |
Rate limits
API reads are not metered. The limits that exist protect a third party:
| What | Limit |
|---|---|
| Pings and resends to one webhook endpoint | 10 per minute |
stridee trigger ping per listener | 10 per minute |
| Workout pushes to devices | 60 per minute |
Workout pushes are capped because providers rate-limit us across every customer at once. If you are polling to stay current, webhooks cost you nothing and arrive sooner.
Retrying safely
GETis always safe to retry. So isDELETE— a repeat gets a404, which is the state you wanted.POST /v1/connectis safe too: the sameexternal_user_idreturns the same user.- For other writes, read back before retrying a request whose response you never saw.
Something wrong or missing on this page? Tell us in Discord. Need something the API doesn’t do yet? Request it on the roadmap.