Developers
API Guide: Errors And Rate Limits
The error shape, every status and code, and the per-minute request limits with the headers that report them.
Every error from /v1 and /mcp has the same JSON shape and a status code. Branch on error.code, never on the message. The OAuth routes use the standard OAuth error shape instead.
Steps
Read the status, then error.code.
{
"error": {
"code": "validationFailed",
"message": "Send center as { latitude, longitude } — where the itinerary is.",
"details": { "field": "center" },
"requestId": "req_0f3a9c2d7b1e4a6f8c5d2e91"
}
}details appears only when there is more to say, for example details.field, details.required (a missing scope) or details.itineraryId.
Keep the requestId. It is also in the X-Request-Id response header. Quote it if you contact support.
On 429, wait. The Retry-After header is in seconds. Do not retry sooner.
curl -i https://api.travelyfe.com/v1/itineraries \
-H "Authorization: Bearer YOUR_TOKEN"Every response carries the limit for that kind of request:
RateLimit-Limit: 120
RateLimit-Policy: 120;w=60What You Get
| Code | Status | Meaning |
|---|---|---|
unauthenticated | 401 | The token is missing, expired or revoked |
forbidden | 403 | The token lacks a scope (details.required names it), or you are not allowed to see or change that |
subscriptionRequired | 403 | The traveller needs Travelyfe Pro; details.section says for what |
notFound | 404 | It does not exist, or this traveller cannot see it |
itineraryModified | 409 | Out-of-date ETag. The response carries the current ETag |
duplicateItinerary | 409 | Same destination and start date already exists; details.itineraryId names it |
conflict | 409 | It conflicts with the current state |
itineraryTooLarge | 413 | The itinerary is over 256 KB |
validationFailed | 422 | Bad input; details.field names it when it can |
idempotencyKeyReused | 422 | The same Idempotency-Key with a different body |
imageRejected | 422 | The image could not be used |
documentNotSealed | 422 | A document was not encrypted before upload |
preconditionRequired | 428 | Send the If-Match you were given |
rateLimited | 429 | Too many requests; wait Retry-After seconds |
upstreamFailed | 502 | Something behind the API did not answer; try again shortly |
featureUnavailable | 503 | Integrations are paused; try again later |
If It Doesn't Work
- Retry
429,502and503after waiting. Retry aPOSTonly with the sameIdempotency-Key(see Versions, ETags And Retries). - Do not retry
4xxerrors other than429and409 itineraryModifiedwithout changing the request. - A browser call that fails before any status shows may be a blocked origin. Call the API from your server.
Limits
Requests are counted per minute for each traveller and app, by kind:
| Kind | Per minute | Used by |
|---|---|---|
| Read | 120 | Reading itineraries, days, flights, hotels, packing, expenses, marks, documents and wallet passes |
| Search | 30 | Explore, activity suggestions for a stop, optimising a day |
| Write | 60 | Creating, changing and deleting, likes and saves, reports |
| Image | 20 | Uploading and setting images |
| Document | 10 | Uploading documents |