MMeerPartners docs

API error codes

The unified MeerPartners API error format, HTTP codes and a table of domain codes with explanations. How a client should react to 401, 403, 409, 422, 429 and 5xx during integration.

The MeerPartners API returns errors in a unified format with a stable string code. Route your logic by the code field, not by the message text: the text may change and be localized, the code will not.

Error format

{
  "error": {
    "code": "POSTBACK_BAD_SIGNATURE",
    "message": "Signature is invalid",
    "details": {}
  }
}
FieldValue
codeA stable constant in SCREAMING_SNAKE_CASE — the client makes its decision based on it
messageA human-readable explanation (may change)
detailsExtra context: for validation — a field map; sometimes limit, tenants, etc.

The main rule

Never parse message for logic. Branch on code and the HTTP status. message is only for logs and for showing to a human.

HTTP codes

HTTPMeaningWhat the client should do
400Bad request (syntax/semantics, a stale timestamp)Fix the request, do not retry blindly
401Not authenticated: missing/broken token or signatureCheck the key/signature/token
403No rights: scope, role, another tenantCheck the key scope / role / tenant
404Resource not found or not visibleCheck the identifier
409State/idempotency conflict (including replay)Rebuild the request (new timestamp/idempotency key)
410The resource is "stale" or disabled (the link/offer is inactive)Do not retry
422Field validation errorFix the body per details
429Rate limit exceededRetry with backoff, look at Retry-After
500Internal errorRetry with backoff; if it persists — escalate
503A dependency is unavailable (fail-closed)Retry later with backoff

Domain codes

Authentication and keys

CodeHTTPWhen
TENANT_API_KEY_INVALID401Key is unknown, inactive, revoked or expired; X-Api-Key-Id is missing
TENANT_API_KEY_SCOPE_DENIED403The key lacks the required scope (postback / sso)
TENANT_SUSPENDED403The business (tenant) is inactive
TOKEN_EXPIRED401The JWT has expired
TOKEN_INVALID401The JWT did not parse / is invalid
TOKEN_WRONG_TYPE401A refresh was expected but another type arrived (or vice versa)
TOKEN_REVOKED401The refresh token has already been used/revoked
ACCESS_REVOKED401Access revoked on the MeerID side (ban/deletion)
EMBED_SCOPE_DENIED403The action requires a full token, but an embed-scoped one arrived

Postback

CodeHTTPWhen
POSTBACK_BAD_SIGNATURE401The HMAC signature did not match
POSTBACK_STALE_TIMESTAMP400X-Timestamp outside the ±300 s window
POSTBACK_REPLAY409The same signature replayed within the memory window
POSTBACK_TENANT_MISMATCH403X-Tenant-Id did not match the key's tenant
POSTBACK_MISSING_FIELD422A required field for the event_type is missing (or an invalid body)
POSTBACK_UNKNOWN_REF200No attributable click — accepted:false (not an error)
POSTBACK_REFUND_NO_CONVERSION200Refund for a non-existent conversion — accepted:false
POSTBACK_RATE_LIMITED429Too many postbacks per key

Codes on 200 are not failures

POSTBACK_UNKNOWN_REF and POSTBACK_REFUND_NO_CONVERSION arrive with HTTP 200 and accepted:false. These are normal outcomes (organic / a non-applicable refund), not connectivity errors — do not retry them.

Token-exchange (SSO)

CodeHTTPWhen
EXCHANGE_DENIED401An invalid signature, X-Timestamp missing/expired, the tenant is inactive
EXCHANGE_REPLAY401A replay of the same signature
USER_BANNED403The user is banned

Webhooks

CodeHTTPWhen
DEPOSIT_WEBHOOK_UNCONFIGURED503The deposit webhook secret is not set (fail-closed)
DEPOSIT_WEBHOOK_SIGNATURE_INVALID401Missing headers / invalid signature / timestamp outside the window / replay
DEPOSIT_WEBHOOK_REPLAY_STORE_UNAVAILABLE503The replay-protection store is unavailable
INVALID_PAYLOAD400Invalid JSON in the body
LOGOUT_TOKEN_INVALID401An invalid logout_token (MeerID back-channel logout)
WEBHOOK_TIMESTAMP_STALE401A MeerID identity webhook outside the freshness window

Tracking

CodeHTTPWhen
TRACKING_LINK_NOT_FOUND404An unknown link {code}
LINK_INACTIVE410The link is disabled (no fallback)
OFFER_INACTIVE410The offer is inactive (no fallback)
TRACKING_RATE_LIMITED429Explicit flooding of a tracking endpoint

General

CodeHTTPWhen
VALIDATION_ERROR422A body validation error (field map in details)
FORBIDDEN403Insufficient rights/role
TENANT_HEADER_REQUIRED400Several businesses and no X-Tenant-Id specified (details.tenants)
TOO_MANY_REQUESTS429Limit exceeded (the Retry-After header)
SERVICE_UNAVAILABLE503A dependency is unavailable (fail-closed)
INTERNAL_SERVER_ERROR500An unhandled error

Cabinet user-facing errors

The codes a human sees in the cabinet interface (e.g. BELOW_MIN_PAYOUT, KYC_REQUIRED, INSUFFICIENT_BALANCE, OFFER_PAUSED, SELF_REFERRAL_FORBIDDEN) are described in the user reference. The full list with human-readable wording is on the Error reference page.

What's next