What do RevenueDot's API errors mean?

RevenueDot answers errors in the format each API's clients already parse: SDK endpoints and REST v1 send { "code", "message" } with RevenueCat's backend codes, and REST v2 sends an error object with a type. For receipts, the HTTP status class matters most: a 4xx makes the SDK finish the transaction for good, and a 5xx makes it retry. See 4xx or 5xx on a receipt.

SDK and REST v1 error codes#

JSON
{
  "code": 7103,
  "message": "The receipt is not a valid Test Store purchase token."
}
Code Name HTTP status Meaning
7000 BAD_REQUEST / INVALID_PLATFORM 400 The request is malformed, a secret-key receipt post has no X-Platform app, the store action does not exist for this store, a hosted checkout was asked for a package with no web product, or purchases-js asked for its own Web Billing checkout (rcb_ keys), which RevenueDot does not have.
7101 STORE_PROBLEM 400 or 503 The store refused the request (400), or the store or its credentials could not be used right now (503, retry later).
7102 RECEIPT_ALREADY_IN_USE 400 The purchase belongs to another customer and the project's transfer behaviour is keep or transfer_if_no_active.
7103 INVALID_RECEIPT 400 The receipt, signed transaction or purchase token is not valid, or it belongs to another bundle id or package name.
7110 INTERNAL 500 An unexpected server error. The SDK keeps the transaction and retries.
7220 INVALID_APP_USER_ID 400 The app user id is empty or longer than 100 characters.
7224 INVALID_AUTH_TOKEN 401 A Google Pub/Sub push token is missing or invalid (store notifications only).
7225 INVALID_API_KEY 401 or 403 The API key is unknown (401), or a REST v1 endpoint was called with a public key (403).
7226 BAD_REQUEST_PARAMS 400 A store action got parameters it cannot use, or a required field (such as aad_attribution_token or generate_offers) is missing.
7234 INVALID_APPLE_SUBSCRIPTION_KEY 400 or 500 A StoreKit 1 receipt arrived for an App Store app without an in-app purchase key, or the key is incomplete (500, so the SDK retries once you add the key). A promotional offer cannot be signed without the key (400; the SDK reports invalidAppleSubscriptionKeyError for that offer).
7259 NOT_FOUND 404 The customer, entitlement, offering or subscription does not exist.
7263 INVALID_SUBSCRIBER_ATTRIBUTES 400 Some attributes were not saved; attribute_errors lists them.
7662 UNSUPPORTED_RECEIPT 400 Receipts for this app's store are not supported yet (Web Billing), and the Android SDK's Amazon receipt lookup with a key that is not an Amazon app's.
7849 INVALID_WEB_REDEMPTION_TOKEN 400 A web purchase redemption token is unknown, malformed or from another project. The SDKs return the invalidToken result.
7852 PURCHASE_BELONGS_TO_OTHER_USER 400 Another customer already redeemed this web purchase. The SDKs return purchaseBelongsToOtherUser.
7853 EXPIRED_WEB_REDEMPTION_TOKEN 400 The redemption link expired. purchase_redemption_error_info.obfuscated_email names where a new link was emailed. The SDKs return expired.
7877 INVALID_OPERATION_SESSION 400 A Web Billing checkout session does not exist.

REST API v2 error types#

JSON
{
  "object": "error",
  "type": "parameter_error",
  "message": "app_id: Required",
  "param": "app_id",
  "doc_url": "https://revenuedot.app/docs/api/errors#parameter-error",
  "retryable": false
}

Every v2 error has object: "error", type, message, doc_url (a link to the section below) and retryable. param names the field at fault when there is one.

parameter_error#

A field or query parameter is missing or invalid. param names it. Fix the request; do not retry it unchanged.

resource_already_exists#

An object with this id or lookup key already exists (409). Fetch it instead of creating it.

resource_missing#

The object does not exist in this project (404). Another project's ids also answer 404, so ids cannot be probed.

idempotency_error#

Reserved for RevenueCat compatibility. RevenueDot does not send it today.

rate_limit_error#

Too many requests of one kind: project invites (50 per project per day). The error is retryable; try again later. The dashboard's password reset and email verification endpoints answer 429 with the same type.

authentication_error#

No API key, an unknown key, or no dashboard session (401).

authorization_error#

The key lacks a permission, a public app key was used, or the action needs a dashboard admin (403).

store_error#

The App Store or Google Play refused the action, or could not be reached (retryable: true). Always 422.

server_error#

RevenueDot failed (500, retryable: true). Retry with backoff.

resource_locked_error#

The object is busy, or changed while the request ran (409): a commit of the same product file or of another file of the same app, a run of the same data export, or a webhook delivery being sent (retryable: true; wait for it to finish, then try again), or an experiment whose status another request changed (reload it first).

unprocessable_entity_error#

The request is valid but not possible in this state or for this store (422), for example archiving the current offering or refunding an App Store purchase.

invalid_request#

The body is not valid JSON (400); a package would get two products of one app with overlapping eligibility (409); or a product file is not in a state that allows the action, such as committing a file with errors (409).

entity_references_archived_entities#

The action would make an archived object current (422). Unarchive it first.

plan_required#

Live data is paused on RevenueDot Cloud (402) because the project's owner has no plan. upgrade_url is where the owner starts Pro.

What triggers it. The owner's account made its first live sale (a production purchase that earned money) more than 14 days ago and has not started Pro. Then reads of live data answer 402: overview metrics, charts, customer lists, transactions, subscriptions and purchases lists, exports, attribution, benchmarks, ads revenue, payment recovery, win-back and AI insights. Creating or editing paywalls, experiments and targeting answers 402 too. The same reads with environment=sandbox, a secret key reading one customer, subscription or purchase, and every SDK endpoint keep working, and every purchase still unlocks.

How to fix it. The owner opens the Billing page and clicks Start Pro. Pro costs $0 until your apps make $10,000 a month. The 402 stops at once, and held webhooks are sent, oldest first. A teammate who is not the owner gets a message that names the owner, and asks them to start Pro. Do not retry the request unchanged before that. Self-hosted servers never send this error.

JSON
{
  "object": "error",
  "type": "plan_required",
  "message": "Live data is paused because this account has no plan. Start Pro on the Billing page: it costs $0 until your apps make $10,000 a month.",
  "doc_url": "https://revenuedot.app/docs/api/errors#plan-required",
  "retryable": false,
  "upgrade_url": "https://app.revenuedot.app/account/billing"
}