Skip to main content

Overview

When a request fails, the Dodo Payments API returns an HTTP status code and a JSON body that names the error. Use this page to find what caused an error and how to resolve it. Each error response includes:
  • An HTTP status code that gives the general category of the error.
  • A code that identifies the exact error, for example UNSUPPORTED_COUNTRY.
  • A message that explains the error in plain language. The message can be null, for example for internal server errors.
Branch your error handling on code, not on message. Several codes return more than one message, depending on the cause. Use these error codes to:
  • Debug integration issues.
  • Handle errors correctly in your application.
  • Show meaningful feedback to your customers.
  • Keep your payment processing reliable.
These are API and business-logic errors. For card decline reasons returned on a failed payment (such as INSUFFICIENT_FUNDS or CARD_DECLINED), see the Transaction Failures reference instead.

Standard API Error Codes

The API uses these HTTP status codes for errors:

Error Response Format

An error response body contains two fields, code and message:

Error Codes Reference

The error codes below are grouped by the area of the API they relate to. Each entry lists the condition that triggers the error and the message the API returns. Placeholders such as {id} stand for values that the API fills in.

Authentication & Account

  • UNAUTHORIZED
    • Trigger: The request has no API key or an invalid one (HTTP 401), or the API key lacks the role that the action requires (HTTP 403)
    • Message: You are not authorised to perform this action
  • MERCHANT_NOT_LIVE
    • Trigger: A live mode request for a business that does not have live payments enabled (HTTP 403). This covers a business that has only used test mode, and a business whose live payments are not enabled yet because verification is incomplete. Test mode requests are unaffected.
    • Message: Live payments not enabled for merchant
  • BUSINESS_ARCHIVED
    • Trigger: Any customer-facing request for an archived business (HTTP 403). This covers checkout, payment links, the storefront, the Customer Portal, and license key activation.
    • Message: This business is archived and no longer accepts requests

Payments & Checkout

  • CHECKOUT_SESSION_CONSUMED
    • Trigger: The checkout session has already generated a payment (HTTP 403). Create a new checkout session instead.
    • Message: Payment with the given checkout session has already been generated.
  • MANUAL_RETRY_ALREADY_PAID
    • Trigger: Manual retry of a renewal invoice on which a payment has already succeeded. Sending again would charge the customer twice.
    • Message: A payment on this invoice has already succeeded
  • MANUAL_RETRY_HARD_DECLINE
    • Trigger: Manual retry when the latest failure on the invoice is a hard decline, or carries no classified error code. Another charge on the same card can’t succeed, so update the payment method instead.
    • Message: The last failure on this invoice is a hard decline, so retrying cannot succeed (or) The last failure on this invoice cannot be classified, so it cannot be retried
  • MANUAL_RETRY_IN_FLIGHT
    • Trigger: Manual retry while a payment on the invoice is processing or has no recorded status yet. Wait for the outcome of that payment instead of sending again.
    • Message: A payment on this invoice is still in progress
  • MANUAL_RETRY_LIMIT_REACHED
    • Trigger: Manual retry after all 3 sends on the invoice are spent, or before the cooldown has passed (HTTP 429). The second send waits 1 hour after the first, and the third waits 3 hours after the second. The body carries only code and message. To find when the next send is allowed, read retry_available_at from GET /payments/{payment_id}/retry.
    • Message: Every manual retry for this invoice is spent (or) Retry now is not available for this invoice yet
  • NO_ELIGIBLE_PAYMENT_METHODS
    • Trigger: No payment method remains available for the payment after filtering (HTTP 422)
    • Message: No eligible payment methods found
  • PAYMENT_NOT_PERMITTED
    • Trigger: A checkout or payment attempt by a customer on the merchant’s blocklist (HTTP 403). The code and the message deliberately name no cause.
    • Message: This payment cannot be processed.
  • PAYMENT_NOT_RETRYABLE
    • Trigger: Manual retry of a payment that manual retry doesn’t cover. The payment has no invoice, its invoice is not an open subscription renewal, no payment on the invoice has failed yet, the subscription has no recurring billing configured (for example, an on-demand subscription), or the customer is on the blocklist.
    • Message: Varies with the reason, for example: Only subscription renewal payments can be retried
  • PAYMENT_NOT_SUCCEEDED
    • Trigger: An attempt to refund or process a payment that has not succeeded
    • Message: The provided payment has not succeeded
  • PREVIOUS_PAYMENT_PENDING
    • Trigger: An attempt to create a charge while the previous payment is in a non-terminal state. Also returned for a manual retry when the newest payment on the invoice is neither failed nor in flight, for example requires_customer_action or cancelled.
    • Message: Cannot create new charge as previous payment is not successful yet (or) The most recent payment on this invoice has not failed
  • UNSUCCESSFUL_PAYMENT_ID
    • Trigger: The payment ID references a payment that has not succeeded
    • Message: The Payment ID has an unsuccessful status.

Connectors & BYOP

These errors relate to merchant-owned payment connectors (Bring Your Own Processor, or BYOP).
  • BYOP_CONNECTOR_DISABLED
    • Trigger: Updating the payment method of a subscription routed through a disabled BYOP connector. Dodo Payments doesn’t fall back to its own connectors, so re-enable the connector first.
    • Message: The subscription is routed through the merchant’s own (BYOP) connector which is currently disabled
  • BYOP_CUSTOM_INVOICE_ADDRESS_MISSING
    • Trigger: A payment routed through the merchant’s connector (BYOP) has no custom invoice address
    • Message: BYOP custom invoice address is required when a payment is routed through the merchant’s connector
  • CONNECTOR_LABEL_ALREADY_EXISTS
    • Trigger: Creating a connector with a label that already exists
    • Message: A connector with this label already exists. Please choose a different label.

Refunds

  • EXISTING_REFUND_REQUEST_PROCESSING
    • Trigger: A previous refund request is still being processed
    • Message: A refund request with status “Pending” is still being processed
  • LINE_ITEM_FULLY_REFUNDED
    • Trigger: An attempt to refund a line item that is already fully refunded
    • Message: Line item {id} has been fully refunded cannot be refunded further.
  • LINE_ITEM_NOT_FOUND
    • Trigger: The item ID is not part of the referenced payment
    • Message: Line item {id} not found in payment
  • LINE_ITEM_PRORATED
    • Trigger: A refund or update attempted on a prorated line item
    • Message: Line item {id} cannot be refunded because its prorated
  • LINE_ITEM_REFUND_AMOUNT_TOO_HIGH
    • Trigger: The refund amount, including tax, is higher than the paid amount
    • Message: Line item {id} requested refund amount including tax is {amount} which is above the paid amount {amount}
  • LINE_ITEM_REFUND_AMOUNT_TOO_LOW
    • Trigger: The refund amount is below the minimum threshold
    • Message: Line item {id} requested refund amount is {amount} which is too low
  • NOTHING_TO_REFUND
    • Trigger: No refundable amount remains, because all positive line items are already fully refunded
    • Message: No refundable amount remaining. All positive line items have been fully refunded.
  • PARTIAL_REFUND_NOT_ALLOWED
    • Trigger: A partial refund attempted on a payment method that supports only full refunds
    • Message: Partial refunds are not allowed for this payment method
  • PAYMENT_ALREADY_REFUNDED
    • Trigger: A duplicate refund
    • Message: This payment has already been refunded
  • PAYMENT_HAS_BEEN_REFUNDED
    • Trigger: The payment has been fully refunded
    • Message: The Payment ID has been fully refunded.
  • REFUND_AMOUNT_EXCEEDS_PAID_AMOUNT
    • Trigger: The total refund amount is higher than the paid amount
    • Message: The calculated refund amount is larger than the paid amount
  • REFUND_WINDOW_EXPIRED
    • Trigger: The refund is requested outside the allowed refund window
    • Message: Refunds cannot be initiated {days} days after payment creation. Contact support@dodopayments.com.
  • ZERO_AMOUNT_PAYMENT_REFUND_NOT_ALLOWED
    • Trigger: An attempt to refund a zero-amount payment
    • Message: Cannot refund a payment with zero currency amount

Subscriptions & Add-ons

  • ADDONS_IN_USAGE_BASED_BILLING_NOT_SUPPORTED
    • Trigger: An attempt to add add-ons to a usage-based billing subscription
    • Message: Addons in Subscriptions are not supported for Usage Based Billing
  • ADDONS_NOT_ALLOWED_FOR_ON_DEMAND
    • Trigger: An attempt to add add-ons to an on-demand subscription
    • Message: Addons are not allowed for on demand subscriptions
  • CANCEL_SCHEDULED_PLAN_CHANGE_FOR_CUSTOMER_PORTAL_DISABLED
    • Trigger: The Customer Portal attempts to cancel a scheduled plan change while the business has disabled that action
    • Message: Cancelling scheduled plan change is disabled for customer portal.
  • CHARGE_NOT_ALLOWED_FOR_SCHEDULED_CANCELLATION
    • Trigger: An attempt to charge a subscription that is scheduled for cancellation
    • Message: Subscription scheduled for cancellation
  • CUSTOMER_HAS_EXISTING_SUBSCRIPTION
    • Trigger: Creating a subscription for a customer who already has one, when the business doesn’t allow multiple subscriptions per customer
    • Message: Customer {id} has an existing subscription. To allow multiple subscriptions per customer, change business settings
  • DO_NOT_BILL_NOT_ALLOWED_IN_CUSTOMER_PORTAL
    • Trigger: The do_not_bill proration mode is used in a Customer Portal plan change
    • Message: do_not_bill proration mode is not allowed in the customer portal
  • DUPLICATE_ADDON_IDS_IN_REQUEST
    • Trigger: The same addon_id appears more than once in the request
    • Message: Duplicate addon IDs are not allowed
  • INACTIVE_SUBSCRIPTION_PLAN_CHANGE_NOT_SUPPORTED
    • Trigger: A plan change on an inactive subscription
    • Message: Changing plans is not supported for inactive subscriptions
  • INVALID_PRORATION_MODE_WITH_NEXT_BILLING_DATE
    • Trigger: A proration mode other than full_immediately used with effective_at: next_billing_date
    • Message: Only full_immediately proration mode is allowed with effective_at: next_billing_date
  • MISSING_ADDON_IDS
    • Trigger: The addon_id list is empty or contains unknown IDs
    • Message: One or more product IDs do not exist: {id}
  • ON_DEMAND_PLAN_CHANGE_NOT_SUPPORTED
    • Trigger: A plan change on an on-demand subscription
    • Message: Changing plans is not supported for on demand subscriptions
  • ON_DEMAND_USAGE_BASED_BILLING_NOT_SUPPORTED
    • Trigger: An attempt to use an on-demand subscription with usage-based billing
    • Message: On Demand Subscriptions are not supported for Usage Based Billing
  • ONE_TIME_PRODUCTS_NOT_ALLOWED_FOR_ON_DEMAND
    • Trigger: A one-time product added to an on-demand subscription
    • Message: One-time products are not allowed for on demand subscriptions
  • PENDING_PLAN_CHANGE_EXISTS
    • Trigger: A new plan change requested while a previous one is still awaiting payment
    • Message: A pending plan change already exists for this subscription. Please wait for the current payment to complete.
  • PLAN_CHANGE_FOR_CUSTOMER_PORTAL_DISABLED
    • Trigger: A plan change through the Customer Portal while the business has disabled it
    • Message: Subscription plan change for customer portal is disabled.
  • PLAN_CHANGE_NOT_ALLOWED_FOR_SCHEDULED_CANCELLATION
    • Trigger: A plan change on a subscription that is scheduled for cancellation
    • Message: Subscription scheduled for cancellation
  • SCHEDULE_PLAN_CHANGE_FOR_CUSTOMER_PORTAL_DISABLED
    • Trigger: Scheduling a plan change through the Customer Portal while the business has disabled it
    • Message: Scheduling plan changes is disabled for this business.
  • SCHEDULED_PLAN_CHANGE_EXISTS
    • Trigger: Creating a scheduled plan change when one already exists
    • Message: A scheduled plan change already exists for this subscription. Please cancel the existing scheduled change before creating a new one.
  • SCHEDULED_PLAN_CHANGE_NOT_FOUND
    • Trigger: Referencing or cancelling a scheduled plan change that does not exist
    • Message: No scheduled plan change found for this subscription.
  • SUBSCRIPTION_EXPIRED
    • Trigger: Billing a subscription after its expires_at date
    • Message: Subscription expired cannot create new charges
  • SUBSCRIPTION_HAS_NO_PAYMENT_METHOD
    • Trigger: Manual retry of a subscription that has no saved payment method to charge off-session
    • Message: This subscription has no saved payment method to charge
  • SUBSCRIPTION_INACTIVE
    • Trigger: The subscription status is not active
    • Message: Subscription is not active (or) This subscription is not live, so a cancellation cannot be scheduled
  • SUBSCRIPTION_NOT_ON_DEMAND
    • Trigger: An on-demand action on a subscription that bills on a fixed interval
    • Message: Subscription is already not on demand
  • SUBSCRIPTION_PAYMENT_RETRY_LIMIT_EXCEEDED
    • Trigger: The subscription payment retries exceeded the maximum number of attempts
    • Message: Maximum retry limit of 10 attempts exceeded for this subscription

Customers & Blocklist

  • CUSTOMER_ALREADY_BLOCKED
    • Trigger: Blocking a customer who is already on the blocklist and has no live subscriptions left to cancel (HTTP 409)
    • Message: This customer is already on the blocklist
  • PORTAL_ACTION_NOT_PERMITTED
    • Trigger: A blocked customer calls a Customer Portal write route: cancel, pause, resume, change plan, or update payment method (HTTP 403). Read routes stay open. The code and the message deliberately name no cause.
    • Message: This action is not available.

Products, Cart & Brands

  • BRAND_ALREADY_ARCHIVED
    • Trigger: Archiving a brand that is already archived
    • Message: Brand is already archived
  • BRAND_ARCHIVED
    • Trigger: Updating an archived brand, submitting it for verification, or tagging a new product, product collection, or subscription to it
    • Message: Brand is archived (or) Brand is archived and cannot be updated (or) Brand is archived and cannot be submitted for verification
  • BRAND_ARCHIVE_TARGET_REQUIRED
    • Trigger: Archiving a brand that still holds products, live subscriptions, or product collections without a move_products_to target
    • Message: Brand has {count} product(s). Set move_products_to to a target brand to re-tag them. The message names live subscriptions or product collections instead when those block the archive.
  • BRAND_MISMATCH
    • Trigger: The cart items belong to different brands
    • Message: All items in the product cart should belong to the same brand
  • BRAND_NOT_ENABLED
    • Trigger: The brand is disabled or not active
    • Message: Brand provided is not enabled
  • BRAND_SUBMISSION_NOT_ENABLED
    • Trigger: The brand verification resubmission feature is not enabled
    • Message: Brand verificatin resubmission is not enabled (spelled exactly as the API returns it)
  • CANNOT_ARCHIVE_PRIMARY_BRAND
    • Trigger: Archiving the primary brand, whose brand ID is the business ID
    • Message: The primary brand cannot be archived
  • FILE_IN_USE
    • Trigger: Deleting a digital product file that active entitlement grants still reference
    • Message: Digital file is referenced by active grants
  • INVALID_BRAND_ARCHIVE_TARGET
    • Trigger: move_products_to names the brand being archived, an archived brand, or a brand of another business
    • Message: move_products_to must be a brand of this business that is not archived (or) move_products_to cannot be the brand you archive
  • INVALID_SUGGESTED_PRICE
    • Trigger: A Pay What You Want suggested price is lower than the minimum price
    • Message: Suggested Price cannot be lower than minimum price. In case of pay what you want, price is considered as minimum accepted amount
  • LOCALIZED_PRICE_ALREADY_EXISTS
    • Trigger: A localized price already exists for this product and country or currency
    • Message: A localized price for this product and country/currency already exists
  • LOCALIZED_PRICE_DUPLICATES_BASE
    • Trigger: The localized price duplicates the base currency or country of the product
    • Message: Localized price duplicates the product’s base currency/country
  • LOCALIZED_PRICE_SHAPE_MISMATCH
    • Trigger: The localized price shape does not match the pricing_mode of the product
    • Message: Localized price shape does not match the product’s pricing_mode
  • MISSING_PRODUCT_INFORMATION
    • Trigger: The product exists, but mandatory information is missing
    • Message: Product {id} exists but other mandatory information is missing or invalid
  • PAY_AS_YOU_WANT_AMOUNT_REQUIRED
    • Trigger: The amount is missing for a Pay What You Want product
    • Message: Amount is mandatory for pay as you want product
  • PRODUCT_CART_EMTPY
    • Trigger: An empty product cart is submitted
    • Message: product_cart is empty (the error code is intentionally spelled EMTPY to match the exact value the API returns)
  • PRODUCT_COLLECTION_IS_DELETED
    • Trigger: Operating on a product collection that has been deleted
    • Message: No message
  • PRODUCT_COLLECTION_MUST_HAVE_PRODUCTS
    • Trigger: Removing the last product, or the last group with products, from a collection
    • Message: Cannot delete the last product in a collection. Archive the collection instead. (or) Cannot delete the last group with products. Archive the collection instead.
  • PRODUCT_IS_DELETED
    • Trigger: The product has been deleted
    • Message: No message
  • PRODUCT_PRICING_MODE_REQUIRED
    • Trigger: Adding localized prices before the pricing_mode of the product is set
    • Message: Product pricing_mode must be set before adding localized prices
  • SLUG_ALREADY_TAKEN
    • Trigger: The requested product slug or short URL is already in use
    • Message: Slug is already taken
  • UNABLE_TO_EDIT_PRIMARY_BRAND
    • Trigger: An attempt to update the primary brand through the regular brand API
    • Message: Primary brand cannot be updated via this API endpoint.

Discounts

  • DISCOUNT_ALREADY_USED_ON_SUBSCRIPTION
    • Trigger: Applying a discount again that has already been used on this subscription
    • Message: This discount has already been used on this subscription
  • DISCOUNT_CODE_ALREADY_EXISTS
    • Trigger: Creating a discount code that already exists
    • Message: Discount Code already exists
  • DISCOUNT_CODE_EXPIRED
    • Trigger: The discount code is past its expires_at date
    • Message: Discount code expired
  • DISCOUNT_CODE_USAGE_LIMIT_EXCEEDED
    • Trigger: The discount code is used after its usage_limit is reached
    • Message: Usage limit cannot be less than times_used (or) Discount code hit usage limit
    • Note: Terminal. The code is exhausted, so don’t retry.
  • DISCOUNT_CONCURRENT_REDEMPTION
    • Trigger: Another redemption of the same code held the usage-limit lock too long (HTTP 503)
    • Message: Discount is being redeemed concurrently; please retry
    • Note: Transient. The code may still have capacity, so the request is safe to retry. Don’t show this to the customer as an exhausted code.
  • DISCOUNT_CURRENCY_OPTION_INVALID
    • Trigger: Invalid currency_options on create or update
    • Message: A flat discount requires at least one currency option with a resolvable default (or) Duplicate currency options are not allowed (or) Only one currency option may be marked as default
  • DISCOUNT_CUSTOMER_NOT_ELIGIBLE
    • Trigger: The customer does not meet the customer_eligibility of the code (first_time, existing, or not on the allow list of a specific code)
    • Message: Customer is not eligible for this discount code
  • DISCOUNT_MINIMUM_SUBTOTAL_NOT_MET
    • Trigger: The cart subtotal is below the minimum_subtotal configured for the checkout currency
    • Message: Cart subtotal is below the discount’s minimum required subtotal
  • DISCOUNT_NOT_YET_ACTIVE
    • Trigger: The code is used before its starts_at date
    • Message: Discount code is not yet active (starts_at is in the future)
  • DISCOUNT_PER_CUSTOMER_USAGE_LIMIT_EXCEEDED
    • Trigger: The customer has already redeemed the code per_customer_usage_limit times
    • Message: Per-customer usage limit exceeded for this discount code
  • DISCOUNT_NOT_APPLICABLE_TO_NEW_PRODUCT
    • Trigger: A plan change to a product that the existing discount does not apply to
    • Message: Discount not applicable to the new plan’s product
  • DISCOUNT_NOT_AVAILABLE_FOR_ON_DEMAND
    • Trigger: The code is applied to an on-demand subscription
    • Message: Discount coupon not available for on demand subscriptions
  • DISCOUNT_NOT_AVAILABLE_FOR_PRODUCT
    • Trigger: The code is applied to products it doesn’t cover
    • Message: Discount coupon not available for this product
  • INVALID_DISCOUNT_CODE
    • Trigger: The code does not exist, or it doesn’t apply to any product in the cart
    • Message: Invalid Discount Code (or) Discount Code cannot be applied to any product in the cart
  • INVALID_PERCENTAGE
    • Trigger: The percentage is higher than 100% (10,000 basis points)
    • Message: Percentage amount cannot be more than 10000 (or) Discount code amount cannot be more than 100%
  • UNSUPPORTED_DISCOUNT_TYPE
    • Trigger: A discount type that is not supported. percentage and flat are both supported; per-unit amount discounts are not.
    • Message: Only percentage and flat discount codes are supported (or) Only percentage discount codes are supported for now

License Keys

  • ACTIVATION_LIMIT_LESS_THAN_CURRENT_AMOUNT
    • Trigger: The new activation limit of a license key is lower than its current number of instances
    • Message: New activation limit cannot be less than current instances count
  • INACTIVE_LICENSE_KEY
    • Trigger: The license key status is not active
    • Message: License key is not active
  • LICENSE_KEY_LIMIT_REACHED
    • Trigger: The number of activations has reached the activation limit
    • Message: License key activation limit reached
  • LICENSE_KEY_NOT_FOUND
    • Trigger: The instance ID or license key ID is invalid
    • Message: License key instance not found or does not belong to this license key
  • NO_EXPIRY_ON_SUBSCRIPTION_LICENSE_KEYS
    • Trigger: An attempt to set an expiry date on a subscription-based license key
    • Message: Cannot set expiry date for subscription-based license key

Usage-Based Billing & Meters

  • DUPLICATE_METER_IDS_IN_REQUEST
    • Trigger: The same meter ID appears more than once in the request
    • Message: Duplicate Meter Ids are not allowed
  • INVALID_QUANTITY
    • Trigger: A quantity other than 1 for a product with usage-based pricing
    • Message: Only 1 quantity allowed in usage based price products
  • METER_IS_DELETED
    • Trigger: An attempt to use a deleted meter
    • Message: The Meter is already been deleted
  • MISSING_METER_IDS
    • Trigger: The meter ID list is empty or contains invalid IDs
    • Message: One or more meter IDs do not exist: {id}

Credit-Based Billing

  • CREDIT_ENTITLEMENT_IS_DELETED
    • Trigger: Operating on a credit entitlement that has been deleted
    • Message: The credit entitlement has already been deleted
  • CREDIT_ENTITLEMENT_NAME_ALREADY_EXISTS
    • Trigger: Creating a credit entitlement with a name that already exists
    • Message: A credit entitlement with this name already exists
  • OVERAGE_LIMIT_EXCEEDED
    • Trigger: A usage or credit deduction would exceed the configured overage limit
    • Message: Overage limit exceeded

Wallet

  • INSUFFICIENT_WALLET_FUNDS
    • Trigger: The wallet balance is lower than the debit amount
    • Message: Insufficient funds in wallet
  • NEGATIVE_BALANCE_ADJUSTMENT
    • Trigger: An attempt to make the wallet balance negative
    • Message: Wallet balance is not allowed to be made negative

Currency, Tax & Region

  • EXCHANGE_RATE_NOT_FOUND
    • Trigger: No exchange rate exists for the currency pair
    • Message: Exchange rate not found to convert from {currency} to {currency}
  • INVALID_TAX_ID
    • Trigger: The VAT, GST, or TIN failed validation
    • Message: Tax Id is invalid
  • REQUEST_AMOUNT_BELOW_MINIMUM
    • Trigger: The amount is lower than the minimum set for the product
    • Message: Amount cannot be less than minimum amount specified for the product
  • TOTAL_PAYMENT_AMOUNT_BELOW_MINIMUM_AMOUNT
    • Trigger: The combined cart total is lower than the minimum amount required to process a payment
    • Message: Minimum amount of {display_str} is required to process payment
  • UNSUPPORTED_BILLING_CURRENCY
    • Trigger: The requested billing currency is not supported for this subscription
    • Message: Non USD billing currency is not supported for subscriptions
  • UNSUPPORTED_COUNTRY
    • Trigger: The country is not supported
    • Message: Country {country_name} currently not supported
  • UNSUPPORTED_CURRENCY
    • Trigger: The product or add-on currency is not a currency that Dodo Payments can charge in. Base prices can be set in any chargeable currency, so this error usually means that the currency code is invalid or not supported.
    • Message: Currency is not currently supported (or) Only USD and INR products supported currently (or) Only USD and INR supported for addon price (or) Can only request USD or INR for billing_currency (or) Currency Not Supported (or) Unexpected currency for Indian card subscriptions
  • UNSUPPORTED_TAX_CATEGORY
    • Trigger: The tax category is not one of the supported values
    • Message: Category {category} currently not supported

Validation & Requests

  • DUPLICATE_LINE_ITEMS_IN_REQUEST
    • Trigger: The same item_id appears more than once in items[]
    • Message: Duplicate item_ids specified in items array
  • INVALID_QUERY_PARAMS
    • Trigger: Query parameters that are mutually exclusive or malformed
    • Message: Query params should only contain either time_frame or (start, end) (or) The start of the range must not be after the end
  • INVALID_REQUEST_BODY
    • Trigger: Malformed JSON or a schema violation
    • Message: Your request body is invalid. Please check your request headers and object.
  • INVALID_REQUEST_PARAMETERS
    • Trigger: Parameter values that are valid in format but not in meaning, for example a date in the past
    • Message: Cannot change next_billing_date to past time (or) A checkout with more than one subscription product cannot hold one-time products
  • MAXIMUM_KEYS_REACHED
    • Trigger: Metadata or custom fields exceed 50 key-value pairs
    • Message: Exceeds 50 key-value pairs

General & System

  • INTEGER_CONVERSION_FAILURE
    • Trigger: A server-side conversion between an integer and a string or decimal fails, for example when a cart total is too large to process
    • Message: Integer Conversion Failure (or) Cart total is too large to process. Reduce the quantity, or select a different billing currency.
  • INTERNAL_SERVER_ERROR
    • Trigger: An unexpected server error. Log the request details on your side.
    • Message: No public message (generic 500, message is usually null)
  • NOT_FOUND
    • Trigger: Generic 404 for any missing resource
    • Message: Item not found (or a more specific message that names what is missing)
  • TOO_MANY_REQUESTS
    • Trigger: A rate limit was exceeded (HTTP 429)
    • Message: No message
  • UNSUPPORTED_ACTION
    • Trigger: An action that the resource type doesn’t support
    • Message: Changing plans for usage based subscriptions is not supported

Best Practices

Follow these practices when you handle API errors:
  1. Handle every error response in your application, and branch on code rather than on message.
  2. Log the HTTP status, code, and message of every failed request.
  3. Show end users a message written for them instead of the raw API message.
  4. Retry only transient errors, such as 429 and 5xx responses or DISCOUNT_CONCURRENT_REDEMPTION, after a delay.
  5. Contact support for errors that you can’t resolve.

Support

For more help with error codes or integration issues, contact the support team at support@dodopayments.com.
Last modified on September 26, 2026