Errors, retries & limits

The error envelope, every code the machine rails return, rate limits, and what is safe to retry.

On this page

The envelope#

Every error on /partner/v1/… is JSON with a stable machine-readable code. Branch on code; the message is for your logs and may change.

409 Conflict
{
  "error": {
    "code": "pool_too_low",
    "message": "this order costs 6930 cents and the payouts pool holds 5000",
    "retryable": false
  }
}

retryable is our advice: true means the same request may succeed later without changes (an outage, a rate limit, a paused feature). Idempotency errors add an operationState field describing what became of the original attempt.

Error codes#

Authentication and shape

StatusCodeWhen
401partner_key_invalidMissing, unknown or revoked API key.
403partner_account_inactiveYour company is suspended.
400invalid_requestA body or filter the route could not use, with the reason in the message.
400unsupported_gameA game other than the ones we support.
409idempotency_key_conflictThe key was already used with a different payload.
409idempotency_in_progressThe original request with this key is still running.
422idempotency_key_requiredA mutating route was called without the header.
429rate_limit_exceededToo many requests for this company on this route. Wait for Retry-After and retry. On a read route the body is a plain {"detail": "too many requests"} rather than the envelope; the status and header are the same.

Customers

StatusCodeWhen
404customer_not_foundNo customer of yours matches the reference. Also the answer for someone linked to another partner.
404roblox_account_not_foundRoblox does not know that username.
409external_ref_in_useThat externalRef already names a different customer of yours.
409customer_not_readyThe customer is linked but has no MM2Empire account yet, so there is nothing to quote, sell or deliver to. It is created the first time they deposit.

MM2 Payments

StatusCodeWhen
409payments_disabledBuying is switched off in the console.
409item_not_acceptedYou (or MM2Empire, on our funding) do not buy this item, or the price falls below your minimum payout.
409stock_limit_reachedYou already hold the maximum number of copies you set for this item.
409pool_too_lowYour Payments pool cannot cover the payout.
409item_unavailableThe copy is listed, in a trade, being withdrawn or on hold and cannot move right now.
404record_not_foundNo payment of yours has that id.
404session_not_foundNo pop-up session of yours has that id.
429pricing_mode_cooldown · funding_source_cooldown · claim_cooldownA setting was changed, or earnings claimed, less than 15 minutes ago. Retry-After says when it reopens.

MM2 Payouts

StatusCodeWhen
409payouts_disabledSelling is switched off in the console.
409pool_too_lowYour Payouts float cannot cover the order.
400order_too_largeMore than 4 item types or 100 items, or over the per-order ceiling or daily cap you set.
409nothing_purchasedNone of the stacks were still available at the quoted prices.
409pool_is_sharedYou tried to fund or release the Payouts float while it shares the Payments pool.
404order_not_foundNo order of yours has that id.
503withdrawals_disabledItem delivery is paused platform-wide during an incident. Retryable.

Rate limits#

Limits are per company per route family, over a rolling minute, and shared across all of your API keys. A refused request returns 429 with a Retry-After header in seconds; inside a write carrying an Idempotency-Key the body is the error envelope with code rate_limit_exceeded, and on a read it is {"detail": "too many requests"}. The figures below are the current limits; they are generous for a real integration and tight enough that a runaway loop stops quickly.

Route familyRequests per minute
Reads: customers, sessions, payments, orders, withdrawals, listings, claims120
Link a customer · open or close a session · inventory · quote · rate card · deposits · pool60
Payout orders30
Sell · withdrawals20

What to retry#

  • Network timeouts and 5xx: retry with the same Idempotency-Key. That is what the header is for.
  • 429: wait for Retry-After, then retry with the same key.
  • 409 with `retryable: true` (for example withdrawals_disabled): the request is fine and the platform is not ready; back off for a minute.
  • Any other 4xx: do not retry unchanged. The request will be refused the same way every time.