API errors and rate limits

Every error code the API can return, what each one means, and the rate limits and plan limits that apply to a key.

By YalangoUpdated October 1, 2026

The error shape

Every failure comes back in the same envelope, with the HTTP status telling you the broad category and code telling you exactly what happened:

{
  "error": {
    "code": "invalid_card",
    "message": "cards[3].target must be at most 2000 characters.",
    "param": "cards[3].target",
    "request_id": "req_8fKd2mXp4LvNc7Bh"
  }
}
  • code is stable and safe to branch on in your script.
  • message is written for a human and may be reworded over time, so do not match on it.
  • param names the exact field, including its index in a batch.
  • request_id also appears in our logs. Quote it if you contact support and we can find the exact request.

Error codes

Authentication - 401

CodeMeaning
invalid_api_keyThe key is missing, malformed, or not one we issued
revoked_api_keyThe key was revoked. Create a new one in settings
expired_api_keyThe key passed its expiry date

Permissions - 403

CodeMeaning
insufficient_scopeThe key lacks the scope this endpoint needs. The message names it
deck_not_ownedThe deck exists but belongs to another account
account_pending_deletionThe account is scheduled for deletion

Not found - 404

CodeMeaning
deck_not_foundNo deck with that doc_id
card_not_foundNo card with that id. param names which entry in a batch
card_not_in_deckThe card exists but is in a different deck than the one in the URL
custom_field_not_foundNo custom field with that id on the deck
not_foundNo such endpoint
unknown_api_versionThe version in the URL does not exist. The message lists the ones that do

Bad request - 400

CodeMeaning
invalid_requestA required field is missing, or a value is the wrong type or too long
invalid_cardOne card in the batch is invalid. param names which
invalid_custom_fieldA custom field key is not defined on the deck, or its value is invalid
invalid_languageA language code is not in a recognised form
batch_too_largeMore than 100 cards in one request
field_not_patchableYou tried to change a field the API does not let you change
invalid_field_typeA custom field's type is not text or list
too_many_custom_fieldsThe deck already has 50 custom fields
deck_not_emptyA language change was attempted on a deck that already has cards
invalid_cursorThe pagination cursor is not one we issued
unknown_field / unknown_parameterA field or query parameter we do not recognise
invalid_jsonThe body is not valid JSON
idempotency_key_reuseThe same Idempotency-Key was used for a different request

Limits - 402, 413, 429

CodeStatusMeaning
quota_exceeded402You reached your plan's deck or card limit
payload_too_large413The request body is over 256 KB
rate_limited429Too many requests. See the rate limits below

Conflicts - 409

CodeStatusMeaning
custom_field_exists409The deck already has a custom field with that name. The message gives you its id

Everything else - 415, 503, 500

CodeStatusMeaning
unsupported_media_type415The body was not sent as application/json
method_not_allowed405Wrong HTTP method for that path
temporarily_unavailable503The API is paused for maintenance. Retry after the interval in Retry-After
internal500Something broke on our side. Quote the request_id

Nothing is written on a 503, and the request is safe to retry.

Rate limits

Limits are counted per key, not per account.

  • 60 requests per minute
  • 5000 requests per day

Requests are not all counted equally. A read counts as one; a write counts for more, because of the work it sets off behind it. Creating a deck, editing or deleting a batch of cards, and deleting a custom field are the heaviest - the last two because they each ripple out into your vocabulary and, for a card edit, into regenerated audio.

The practical consequence is that a batch request is much cheaper than the same work split into separate requests. Editing 100 cards in one call costs a fraction of editing them one at a time.

Every response, not just a 429, carries the current state:

HeaderMeaning
X-RateLimit-LimitRequests allowed in the current window
X-RateLimit-RemainingHow many you have left
X-RateLimit-ResetWhen the window resets, as a Unix timestamp in seconds

On a 429 you also get Retry-After, in seconds.

Backing off

On a 429, wait for the interval in Retry-After and try again. For 500 and 503, use exponential backoff with a few retries, and pair it with an Idempotency-Key on writes so a retry after a timeout cannot duplicate anything.

Do not retry a 4xx other than 429: the request will fail the same way until you change it.

Plan limits

Rate limits cap how fast you can call the API. Plan limits cap how much you can store, and are the same limits the web app enforces:

FreePremium
Decks100Unlimited
Cards10,000Unlimited

Crossing one returns 402 quota_exceeded, with a message saying how many you have and how many you can still add. Nothing is written when a request is rejected for quota.

See free plan limits for the full picture, or Yalango Premium to lift them.

Was this article helpful?
0

Comments

Sign in to join the conversation.