Skip to main content

개요

요청이 실패하면 Dodo Payments API는 HTTP 상태 코드와 오류를 설명하는 JSON 본문을 반환합니다. 이 페이지에서 오류의 원인과 해결 방법을 확인하세요. 각 오류 응답에는 다음이 포함됩니다:
  • 오류의 일반적인 범주를 나타내는 HTTP 상태 코드입니다.
  • 정확한 오류를 식별하는 code입니다(예: UNSUPPORTED_COUNTRY).
  • 오류를 일반적인 언어로 설명하는 message입니다. message는 예를 들어 내부 서버 오류의 경우 null일 수 있습니다.
code를 기준으로 오류 처리를 분기하고 message를 기준으로 분기하지 마세요. 원인에 따라 여러 메시지를 반환하는 코드도 있습니다. 다음 오류 코드를 사용하여:
  • 통합 문제를 디버깅합니다.
  • 애플리케이션에서 오류를 올바르게 처리합니다.
  • 고객에게 의미 있는 피드백을 표시합니다.
  • 결제 처리를 안정적으로 유지합니다.
이는 API 및 비즈니스 로직 오류입니다. 실패한 결제에서 반환되는 카드 거절 사유(예: INSUFFICIENT_FUNDS 또는 CARD_DECLINED)는 Transaction Failures 참조 문서를 확인하세요.

표준 API 오류 코드

API는 오류에 다음 HTTP 상태 코드를 사용합니다:

오류 응답 형식

오류 응답 본문에는 code 및 message라는 두 필드가 포함됩니다:

오류 코드 참조

아래 오류 코드는 관련된 API 영역별로 그룹화되어 있습니다. 각 항목에는 오류를 발생시키는 조건과 API가 반환하는 메시지가 나열되어 있습니다. {id}와 같은 플레이스홀더는 API가 입력하는 값을 나타냅니다.

인증 및 계정

  • UNAUTHORIZED
    • 발생 조건: 요청에 API 키가 없거나 유효하지 않음(HTTP 401), 또는 API 키에 작업에 필요한 역할이 없음(HTTP 403)
    • 메시지: 이 작업을 수행할 권한이 없습니다
  • MERCHANT_NOT_LIVE
    • 발생 조건: live payments가 활성화되지 않은 비즈니스에 대한 live mode 요청(HTTP 403)입니다. test mode만 사용한 비즈니스와 verification이 완료되지 않아 아직 live payments가 활성화되지 않은 비즈니스가 해당됩니다. test mode 요청에는 영향을 주지 않습니다.
    • 메시지: merchant에 live payments가 활성화되지 않음
  • BUSINESS_ARCHIVED
    • 발생 조건: 보관된 비즈니스에 대한 모든 고객 대상 요청(HTTP 403)입니다. checkout, payment links, storefront, Customer Portal 및 license key activation이 해당됩니다.
    • 메시지: 이 비즈니스는 보관되었으며 더 이상 요청을 받지 않습니다

결제 및 Checkout

  • CHECKOUT_SESSION_CONSUMED
    • 발생 조건: checkout session에서 이미 결제가 생성됨(HTTP 403). 대신 새 checkout session을 생성하세요.
    • 메시지: 지정된 checkout session으로 결제가 이미 생성되었습니다.
  • MANUAL_RETRY_ALREADY_PAID
    • 발생 조건: 결제가 이미 성공한 renewal invoice에 대한 Manual retry입니다. 다시 전송하면 고객에게 이중으로 청구됩니다.
    • 메시지: 이 invoice의 결제가 이미 성공했습니다
  • MANUAL_RETRY_HARD_DECLINE
    • 발생 조건: invoice의 최근 실패가 hard decline이거나 분류된 오류 코드가 없는 경우의 manual retry입니다. 같은 카드로 다시 청구해도 성공할 수 없으므로 payment method를 대신 업데이트하세요.
    • 메시지: 이 invoice의 마지막 실패는 hard decline이므로 재시도할 수 없습니다 (또는) 이 invoice의 마지막 실패를 분류할 수 없으므로 재시도할 수 없습니다
  • MANUAL_RETRY_IN_FLIGHT
    • 발생 조건: invoice의 결제가 processing 상태이거나 아직 기록된 상태가 없는 동안 manual retry를 수행함. 다시 전송하지 말고 해당 결제 결과를 기다리세요.
    • 메시지: 이 invoice의 결제가 아직 진행 중입니다
  • MANUAL_RETRY_LIMIT_REACHED
    • 발생 조건: invoice에 대한 3회의 전송을 모두 사용했거나 cooldown이 지나기 전의 manual retry(HTTP 429)입니다. 두 번째 전송은 첫 번째 전송 후 1시간, 세 번째 전송은 두 번째 전송 후 3시간을 기다립니다. 본문에는 code 및 message만 포함됩니다. 다음 전송이 허용되는 시간을 확인하려면 GET /payments/{payment_id}/retry에서 retry_available_at를 읽으세요.
    • 메시지: 이 invoice에 대한 모든 manual retry를 사용했습니다 (또는) 아직 이 invoice에서 재시도할 수 없습니다
  • NO_ELIGIBLE_PAYMENT_METHODS
    • 발생 조건: 필터링 후 결제에 사용할 수 있는 payment method가 남아 있지 않음(HTTP 422)
    • 메시지: 사용 가능한 payment method를 찾을 수 없습니다
  • PAYMENT_NOT_PERMITTED
    • 발생 조건: merchant의 blocklist에 있는 고객의 checkout 또는 결제 시도(HTTP 403)입니다. 코드와 메시지는 의도적으로 원인을 명시하지 않습니다.
    • 메시지: 이 결제를 처리할 수 없습니다.
  • PAYMENT_NOT_RETRYABLE
    • 발생 조건: manual retry가 지원하지 않는 결제의 manual retry입니다. 결제에 invoice가 없거나, invoice가 open subscription renewal이 아니거나, invoice의 결제가 아직 실패하지 않았거나, subscription에 recurring billing이 구성되지 않았거나(예: on-demand subscription), 고객이 blocklist에 있을 수 있습니다.
    • 메시지: 사유에 따라 다릅니다. 예: subscription renewal 결제만 재시도할 수 있습니다
  • PAYMENT_NOT_SUCCEEDED
    • 발생 조건: 성공하지 않은 결제를 환불하거나 처리하려고 시도함
    • 메시지: 제공된 결제가 성공하지 않았습니다
  • PREVIOUS_PAYMENT_PENDING
    • 발생 조건: 이전 결제가 terminal 상태가 아닌 동안 charge를 생성하려고 시도함. 최신 invoice 결제가 failed도 in flight도 아닌 경우의 manual retry에도 반환됩니다(예: requires_customer_action 또는 cancelled).
    • 메시지: 이전 결제가 아직 성공하지 않아 새 charge를 생성할 수 없습니다 (또는) 이 invoice의 가장 최근 결제가 실패하지 않았습니다
  • UNSUCCESSFUL_PAYMENT_ID
    • 발생 조건: payment ID가 성공하지 않은 결제를 참조함
    • 메시지: Payment ID의 상태가 성공하지 않았습니다.

Connector 및 BYOP

이 오류는 merchant가 소유한 payment connector(Bring Your Own Processor 또는 BYOP)와 관련이 있습니다.
  • BYOP_CONNECTOR_DISABLED
    • 발생 조건: 비활성화된 BYOP connector를 통해 라우팅된 subscription의 payment method를 업데이트함. Dodo Payments는 자체 connector로 대체하지 않으므로 먼저 connector를 다시 활성화하세요.
    • 메시지: subscription이 현재 비활성화된 merchant 자체(BYOP) connector를 통해 라우팅되고 있습니다
  • BYOP_CUSTOM_INVOICE_ADDRESS_MISSING
    • 발생 조건: merchant의 connector(BYOP)를 통해 라우팅된 결제에 custom invoice address가 없음
    • 메시지: 결제가 merchant의 connector를 통해 라우팅되는 경우 BYOP custom invoice address가 필요합니다
  • CONNECTOR_LABEL_ALREADY_EXISTS
    • 발생 조건: 이미 존재하는 label로 connector를 생성함
    • 메시지: 이 label의 connector가 이미 존재합니다. 다른 label을 선택하세요.

환불

  • EXISTING_REFUND_REQUEST_PROCESSING
    • 발생 조건: 이전 refund request가 아직 처리 중임
    • 메시지: 상태가 “Pending”인 refund request가 아직 처리 중입니다
  • LINE_ITEM_FULLY_REFUNDED
    • 발생 조건: 이미 전액 환불된 line item을 환불하려고 시도함
    • 메시지: Line item {id}은 전액 환불되어 추가로 환불할 수 없습니다.
  • LINE_ITEM_NOT_FOUND
    • 발생 조건: item ID가 참조된 결제에 포함되지 않음
    • 메시지: 결제에서 line item {id}을 찾을 수 없습니다
  • LINE_ITEM_PRORATED
    • 발생 조건: prorated line item에 대해 환불 또는 업데이트를 시도함
    • 메시지: line item {id}은 prorated이므로 환불할 수 없습니다
  • LINE_ITEM_REFUND_AMOUNT_TOO_HIGH
    • 발생 조건: 세금을 포함한 환불 금액이 지불 금액보다 큼
    • 메시지: line item {id}의 세금 포함 요청 환불 금액 {amount}이 지불 금액 {amount}보다 큽니다
  • LINE_ITEM_REFUND_AMOUNT_TOO_LOW
    • 발생 조건: 환불 금액이 최소 기준 미만임
    • 메시지: line item {id}의 요청 환불 금액 {amount}이 너무 낮습니다
  • NOTHING_TO_REFUND
    • 발생 조건: 모든 양수 line item이 이미 전액 환불되어 환불 가능한 금액이 남아 있지 않음
    • 메시지: 환불 가능한 금액이 남아 있지 않습니다. 모든 양수 line item이 전액 환불되었습니다.
  • PARTIAL_REFUND_NOT_ALLOWED
    • 발생 조건: 전액 환불만 지원하는 payment method에 대해 부분 환불을 시도함
    • 메시지: 이 payment method에서는 부분 환불을 허용하지 않습니다
  • PAYMENT_ALREADY_REFUNDED
    • 발생 조건: 중복 환불
    • 메시지: 이 결제는 이미 환불되었습니다
  • PAYMENT_HAS_BEEN_REFUNDED
    • 발생 조건: 결제가 전액 환불됨
    • 메시지: Payment ID가 전액 환불되었습니다.
  • REFUND_AMOUNT_EXCEEDS_PAID_AMOUNT
    • 발생 조건: 총 환불 금액이 지불 금액보다 큼
    • 메시지: 계산된 환불 금액이 지불 금액보다 큽니다
  • REFUND_WINDOW_EXPIRED
    • 발생 조건: 허용된 환불 기간이 지난 후 환불을 요청함
    • 메시지: 결제 생성 후 {days}일이 지나면 환불을 시작할 수 없습니다. support@dodopayments.com으로 문의하세요.
  • ZERO_AMOUNT_PAYMENT_REFUND_NOT_ALLOWED
    • 발생 조건: 금액이 0인 결제를 환불하려고 시도함
    • 메시지: 통화 금액이 0인 결제는 환불할 수 없습니다

Subscription 및 Add-on

  • ADDONS_IN_USAGE_BASED_BILLING_NOT_SUPPORTED
    • 발생 조건: usage-based billing subscription에 add-on을 추가하려고 시도함
    • 메시지: Usage Based Billing에서는 Subscription의 Addon을 지원하지 않습니다
  • ADDONS_NOT_ALLOWED_FOR_ON_DEMAND
    • 발생 조건: on-demand subscription에 add-on을 추가하려고 시도함
    • 메시지: on demand subscription에는 Addon을 허용하지 않습니다
  • CANCEL_SCHEDULED_PLAN_CHANGE_FOR_CUSTOMER_PORTAL_DISABLED
    • 발생 조건: 비즈니스에서 해당 작업을 비활성화한 상태에서 Customer Portal이 예약된 plan change의 취소를 시도함
    • 메시지: customer portal에서 예약된 plan change 취소가 비활성화되어 있습니다.
  • CHARGE_NOT_ALLOWED_FOR_SCHEDULED_CANCELLATION
    • 발생 조건: 취소가 예약된 subscription에 요금을 청구하려고 시도함
    • 메시지: Subscription 취소가 예약되어 있습니다
  • CUSTOMER_HAS_EXISTING_SUBSCRIPTION
    • 발생 조건: 비즈니스에서 고객당 여러 subscription을 허용하지 않을 때 이미 subscription이 있는 고객에게 subscription을 생성함
    • 메시지: 고객 {id}에게 기존 subscription이 있습니다. 고객당 여러 subscription을 허용하려면 business settings를 변경하세요
  • DO_NOT_BILL_NOT_ALLOWED_IN_CUSTOMER_PORTAL
    • 발생 조건: Customer Portal plan change에서 do_not_bill proration mode를 사용함
    • 메시지: do_not_bill proration mode는 customer portal에서 허용되지 않습니다
  • DUPLICATE_ADDON_IDS_IN_REQUEST
    • 발생 조건: 동일한 addon_id가 요청에 두 번 이상 나타남
    • 메시지: 중복 addon ID는 허용되지 않습니다
  • INACTIVE_SUBSCRIPTION_PLAN_CHANGE_NOT_SUPPORTED
    • 발생 조건: 비활성 subscription에서 plan change를 수행함
    • 메시지: 비활성 subscription에서는 plan을 변경할 수 없습니다
  • INVALID_PRORATION_MODE_WITH_NEXT_BILLING_DATE
    • 발생 조건: effective_at: next_billing_date와 함께 full_immediately 이외의 proration mode를 사용함
    • 메시지: effective_at: next_billing_date에는 full_immediately proration mode만 허용됩니다
  • MISSING_ADDON_IDS
    • 발생 조건: addon_id 목록이 비어 있거나 알 수 없는 ID를 포함함
    • 메시지: 하나 이상의 product ID가 존재하지 않습니다: {id}
  • ON_DEMAND_PLAN_CHANGE_NOT_SUPPORTED
    • 발생 조건: on-demand subscription에서 plan change를 수행함
    • 메시지: on demand subscription에서는 plan을 변경할 수 없습니다
  • ON_DEMAND_USAGE_BASED_BILLING_NOT_SUPPORTED
    • 발생 조건: usage-based billing에서 on-demand subscription을 사용하려고 시도함
    • 메시지: Usage Based Billing에서는 On Demand Subscription을 지원하지 않습니다
  • ONE_TIME_PRODUCTS_NOT_ALLOWED_FOR_ON_DEMAND
    • 발생 조건: on-demand subscription에 one-time product를 추가함
    • 메시지: on demand subscription에는 one-time product를 허용하지 않습니다
  • PENDING_PLAN_CHANGE_EXISTS
    • Trigger: 이전 변경이 아직 결제 대기 중인 상태에서 새로운 플랜 변경이 요청됨. 대기 중인 payment-link 변경을 교체하려면 cancel_older_payment_link: true를 설정합니다.
    • Message: 이 subscription에는 이미 대기 중인 플랜 변경이 있습니다. 현재 결제가 완료될 때까지 기다려 주세요.
  • PLAN_CHANGE_FOR_CUSTOMER_PORTAL_DISABLED
    • 발생 조건: 비즈니스에서 비활성화한 상태에서 Customer Portal을 통해 plan change를 수행함
    • 메시지: customer portal의 Subscription plan change가 비활성화되어 있습니다.
  • PLAN_CHANGE_LINK_CANCEL_FAILED
    • Trigger: cancel_older_payment_link: true인 플랜 변경이 이전 payment link를 취소하지 못함. 변경된 사항이 없으므로 요청을 다시 시도할 수 있습니다.
    • Message: 이전 payment link를 취소하지 못했습니다. 다시 시도해 주세요.
  • PLAN_CHANGE_NOT_ALLOWED_FOR_SCHEDULED_CANCELLATION
    • Trigger: 취소 예정인 subscription의 플랜 변경
    • Message: Subscription scheduled for cancellation
  • PLAN_CHANGE_PAYMENT_ALREADY_COMPLETED
    • Trigger: 고객이 이전 플랜 변경에 이미 결제한 상태에서 cancel_older_payment_link: true인 플랜 변경이 요청됨. 해당 변경이 적용되므로 다시 시도하지 마세요.
    • Message: 고객이 이전 플랜 변경에 이미 결제했습니다. 곧 적용됩니다.
  • PLAN_CHANGE_PAYMENT_IN_PROGRESS
    • Trigger: 고객이 이전 플랜 변경을 결제하는 동안 cancel_older_payment_link: true인 플랜 변경이 요청됨(예: 3D Secure 진행 중). 결제가 완료되거나 실패한 후 다시 시도하세요.
    • Message: 고객이 현재 이전 플랜 변경을 결제하고 있습니다. 나중에 다시 시도해 주세요.
  • SCHEDULE_PLAN_CHANGE_FOR_CUSTOMER_PORTAL_DISABLED
    • Trigger: business에서 플랜 변경 예약을 비활성화한 상태에서 Customer Portal을 통해 플랜 변경을 예약함
    • Message: 이 business에서는 플랜 변경 예약이 비활성화되어 있습니다.
  • SCHEDULED_PLAN_CHANGE_EXISTS
    • Trigger: 이미 예약된 플랜 변경이 있는 상태에서 예약된 플랜 변경을 생성함
    • Message: 이 subscription에는 이미 예약된 플랜 변경이 있습니다. 새 변경을 생성하기 전에 기존 예약 변경을 취소해 주세요.
  • SCHEDULED_PLAN_CHANGE_NOT_FOUND
    • Trigger: 존재하지 않는 예약된 플랜 변경을 참조하거나 취소함
    • Message: 이 subscription에 대한 예약된 플랜 변경을 찾을 수 없습니다.
  • SUBSCRIPTION_EXPIRED
    • Trigger: expires_at 날짜 이후에 subscription에 청구함
    • Message: Subscription expired cannot create new charges
  • SUBSCRIPTION_HAS_NO_PAYMENT_METHOD
    • Trigger: off-session 청구를 위해 저장된 payment method가 없는 subscription을 수동으로 재시도함
    • Message: This subscription has no saved payment method to charge
  • SUBSCRIPTION_INACTIVE
    • Trigger: subscription 상태가 active가 아님
    • Message: Subscription is not active (or) 이 subscription은 live 상태가 아니므로 취소를 예약할 수 없습니다
  • SUBSCRIPTION_NOT_ON_DEMAND
    • Trigger: 고정된 interval로 청구되는 subscription에서 on-demand 작업을 수행함
    • Message: Subscription is already not on demand
  • SUBSCRIPTION_PAYMENT_RETRY_LIMIT_EXCEEDED
    • Trigger: subscription payment retry 횟수가 최대 시도 횟수를 초과함
    • Message: Maximum retry limit of 10 attempts exceeded for this subscription

Customers & Blocklist

  • CUSTOMER_ALREADY_BLOCKED
    • Trigger: 이미 blocklist에 있으며 취소할 live subscription이 남아 있지 않은 고객을 차단함(HTTP 409)
    • Message: This customer is already on the blocklist
  • PORTAL_ACTION_NOT_PERMITTED
    • Trigger: 차단된 고객이 Customer Portal write route를 호출함: cancel, pause, resume, 플랜 변경 또는 payment method 업데이트(HTTP 403). Read route는 계속 열려 있습니다. code와 message에는 의도적으로 원인을 표시하지 않습니다.
    • Message: This action is not available.

Products, Cart & Brands

  • BRAND_ALREADY_ARCHIVED
    • Trigger: 이미 archived된 brand를 archive함
    • Message: Brand is already archived
  • BRAND_ARCHIVED
    • Trigger: archived된 brand를 업데이트하거나 verification을 위해 제출하거나 새 product, product collection 또는 subscription을 해당 brand에 연결함
    • 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: product, live subscription 또는 product collection을 보유하고 있으며 move_products_to target이 없는 brand를 archive함
    • Message: Brand has {count} product(s). 이를 다시 태그하려면 move_products_to를 target brand로 설정하세요. archive를 차단하는 항목이 live subscription 또는 product collection인 경우 message에는 해당 항목이 대신 표시됩니다.
  • BRAND_MISMATCH
    • Trigger: cart item이 서로 다른 brand에 속함
    • Message: All items in the product cart should belong to the same brand
  • BRAND_NOT_ENABLED
    • Trigger: brand가 disabled 상태이거나 active 상태가 아님
    • Message: Brand provided is not enabled
  • BRAND_SUBMISSION_NOT_ENABLED
    • Trigger: brand verification resubmission 기능이 활성화되지 않음
    • Message: Brand verificatin resubmission is not enabled (API가 반환하는 표기 그대로)
  • CANNOT_ARCHIVE_PRIMARY_BRAND
    • Trigger: business ID가 brand ID인 primary brand를 archive함
    • Message: The primary brand cannot be archived
  • FILE_IN_USE
    • Trigger: active entitlement grant가 여전히 참조하는 digital product file을 삭제함
    • Message: Digital file is referenced by active grants
  • INVALID_BRAND_ARCHIVE_TARGET
    • Trigger: move_products_to가 archive 중인 brand, archived brand 또는 다른 business의 brand를 지정함
    • 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: Pay What You Want suggested price가 minimum price보다 낮음
    • Message: Suggested Price cannot be lower than minimum price. Pay What You Want의 경우 price는 허용되는 minimum amount로 간주됩니다
  • LOCALIZED_PRICE_ALREADY_EXISTS
    • Trigger: 이 product와 country 또는 currency에 대한 localized price가 이미 존재함
    • Message: A localized price for this product and country/currency already exists
  • LOCALIZED_PRICE_DUPLICATES_BASE
    • Trigger: localized price가 product의 base currency 또는 country와 중복됨
    • Message: Localized price duplicates the product’s base currency/country
  • LOCALIZED_PRICE_SHAPE_MISMATCH
    • Trigger: localized price 형식이 product의 pricing_mode와 일치하지 않음
    • Message: Localized price shape does not match the product’s pricing_mode
  • MISSING_PRODUCT_INFORMATION
    • Trigger: product는 존재하지만 필수 정보가 누락됨
    • Message: Product {id} exists but other mandatory information is missing or invalid
  • PAY_AS_YOU_WANT_AMOUNT_REQUIRED
    • Trigger: Pay What You Want product의 amount가 누락됨
    • Message: Amount is mandatory for pay as you want product
  • PRODUCT_CART_EMTPY
    • Trigger: 빈 product cart가 제출됨
    • Message: product_cart is empty (error code는 API가 반환하는 정확한 값인 EMTPY와 일치하도록 의도적으로 이 표기를 사용함)
  • PRODUCT_COLLECTION_IS_DELETED
    • Trigger: 삭제된 product collection에서 작업함
    • Message: 메시지 없음
  • PRODUCT_COLLECTION_MUST_HAVE_PRODUCTS
    • Trigger: collection에서 마지막 product 또는 product가 포함된 마지막 group을 제거함
    • 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: product가 삭제됨
    • Message: 메시지 없음
  • PRODUCT_PRICING_MODE_REQUIRED
    • Trigger: product의 pricing_mode가 설정되기 전에 localized price를 추가함
    • Message: Product pricing_mode must be set before adding localized prices
  • SLUG_ALREADY_TAKEN
    • Trigger: 요청한 product slug 또는 short URL이 이미 사용 중임
    • Message: Slug is already taken
  • UNABLE_TO_EDIT_PRIMARY_BRAND
    • Trigger: 일반 brand API를 통해 primary brand를 업데이트하려고 시도함
    • Message: Primary brand cannot be updated via this API endpoint.

Discounts

  • DISCOUNT_ALREADY_USED_ON_SUBSCRIPTION
    • Trigger: 이 subscription에 이미 사용된 discount를 다시 적용함
    • Message: This discount has already been used on this subscription
  • DISCOUNT_CODE_ALREADY_EXISTS
    • Trigger: 이미 존재하는 discount code를 생성함
    • Message: Discount Code already exists
  • DISCOUNT_CODE_EXPIRED
    • Trigger: discount code의 expires_at 날짜가 지남
    • Message: Discount code expired
  • DISCOUNT_CODE_USAGE_LIMIT_EXCEEDED
    • Trigger: usage_limit에 도달한 후 discount code를 사용함
    • Message: Usage limit cannot be less than times_used (or) Discount code hit usage limit
    • Note: Terminal입니다. code가 모두 소진되었으므로 다시 시도하지 마세요.
  • DISCOUNT_CONCURRENT_REDEMPTION
    • Trigger: 동일 code의 다른 redemption이 usage-limit lock을 너무 오래 보유함(HTTP 503)
    • Message: Discount is being redeemed concurrently; please retry
    • Note: 일시적인 오류입니다. code에 아직 사용 가능 횟수가 남아 있을 수 있으므로 요청을 안전하게 다시 시도할 수 있습니다. 고객에게 소진된 code로 표시하지 마세요.
  • DISCOUNT_CURRENCY_OPTION_INVALID
    • Trigger: create 또는 update 시 잘못된 currency_options
    • 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: 고객이 code의 customer_eligibility를 충족하지 않음(first_time, existing 또는 INLINE_CODE_PLACEHOLDER_f7f82174766d9a9b1_END code의 allow list에 포함되지 않음)
    • Message: Customer is not eligible for this discount code
  • DISCOUNT_MINIMUM_SUBTOTAL_NOT_MET
    • Trigger: cart subtotal이 checkout currency에 설정된 minimum_subtotal보다 낮음
    • Message: Cart subtotal is below the discount’s minimum required subtotal
  • DISCOUNT_NOT_YET_ACTIVE
    • Trigger: starts_at 날짜 이전에 code를 사용함
    • Message: Discount code is not yet active (starts_at is in the future)
  • DISCOUNT_PER_CUSTOMER_USAGE_LIMIT_EXCEEDED
    • Trigger: 고객이 이미 per_customer_usage_limit회 code를 redeem함
    • Message: Per-customer usage limit exceeded for this discount code
  • DISCOUNT_NOT_APPLICABLE_TO_NEW_PRODUCT
    • Trigger: 기존 discount가 적용되지 않는 product로 플랜을 변경함
    • Message: Discount not applicable to the new plan’s product
  • DISCOUNT_NOT_AVAILABLE_FOR_ON_DEMAND
    • Trigger: on-demand subscription에 code를 적용함
    • Message: Discount coupon not available for on demand subscriptions
  • DISCOUNT_NOT_AVAILABLE_FOR_PRODUCT
    • Trigger: code가 적용되지 않는 product에 code를 적용함
    • Message: Discount coupon not available for this product
  • INVALID_DISCOUNT_CODE
    • Trigger: code가 존재하지 않거나 cart의 어떤 product에도 적용되지 않음
    • Message: Invalid Discount Code (or) Discount Code cannot be applied to any product in the cart
  • INVALID_PERCENTAGE
    • Trigger: percentage가 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: 지원되지 않는 discount type. percentage 및 flat는 모두 지원되지만 per-unit amount discount는 지원되지 않음
    • 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: license key의 새 activation limit이 현재 instance 수보다 낮음
    • Message: New activation limit cannot be less than current instances count
  • INACTIVE_LICENSE_KEY
    • Trigger: license key 상태가 active가 아님
    • Message: License key is not active
  • LICENSE_KEY_LIMIT_REACHED
    • Trigger: activation 수가 activation limit에 도달함
    • Message: License key activation limit reached
  • LICENSE_KEY_NOT_FOUND
    • Trigger: instance ID 또는 license key ID가 유효하지 않음
    • Message: License key instance not found or does not belong to this license key
  • NO_EXPIRY_ON_SUBSCRIPTION_LICENSE_KEYS
    • Trigger: subscription-based license key에 expiry date를 설정하려고 시도함
    • Message: Cannot set expiry date for subscription-based license key

Usage-Based Billing & Meters

  • DUPLICATE_METER_IDS_IN_REQUEST
    • Trigger: 동일한 meter ID가 요청에 두 번 이상 나타남
    • Message: Duplicate Meter Ids are not allowed
  • INVALID_QUANTITY
    • Trigger: usage-based pricing product에 대해 1이 아닌 quantity를 지정함
    • Message: Only 1 quantity allowed in usage based price products
  • METER_IS_DELETED
    • Trigger: 삭제된 meter를 사용하려고 시도함
    • Message: The Meter is already been deleted
  • MISSING_METER_IDS
    • Trigger: meter ID 목록이 비어 있거나 유효하지 않은 ID를 포함함
    • Message: One or more meter IDs do not exist: {id}

Credit-Based Billing

  • CREDIT_ENTITLEMENT_IS_DELETED
    • Trigger: 삭제된 credit entitlement에서 작업함
    • Message: The credit entitlement has already been deleted
  • CREDIT_ENTITLEMENT_NAME_ALREADY_EXISTS
    • Trigger: 이미 존재하는 이름으로 credit entitlement를 생성함
    • Message: A credit entitlement with this name already exists
  • OVERAGE_LIMIT_EXCEEDED
    • Trigger: usage 또는 credit deduction이 설정된 overage limit을 초과함
    • Message: Overage limit exceeded

Wallet

  • INSUFFICIENT_WALLET_FUNDS
    • Trigger: wallet balance가 debit amount보다 낮음
    • Message: Insufficient funds in wallet
  • NEGATIVE_BALANCE_ADJUSTMENT
    • Trigger: wallet balance를 음수로 만들려고 시도함
    • Message: Wallet balance is not allowed to be made negative

Currency, Tax & Region

  • EXCHANGE_RATE_NOT_FOUND
    • Trigger: currency pair에 대한 exchange rate가 존재하지 않음
    • Message: Exchange rate not found to convert from {currency} to {currency}
  • INVALID_TAX_ID
    • Trigger: VAT, GST 또는 TIN validation에 실패함
    • Message: Tax Id is invalid
  • REQUEST_AMOUNT_BELOW_MINIMUM
    • Trigger: amount가 product에 설정된 minimum보다 낮음
    • Message: Amount cannot be less than minimum amount specified for the product
  • TOTAL_PAYMENT_AMOUNT_BELOW_MINIMUM_AMOUNT
    • Trigger: tax를 포함한 합산 cart total이 payment 처리에 필요한 minimum amount보다 낮음. minimum은 billing currency와 payment가 one-time인지 subscription인지에 따라 달라집니다. USD, EUR, GBP 이외의 currency에서는 total을 USD minimum과도 비교합니다. Minimum Amounts를 참조하세요.
    • Message: Minimum amount of {display_str} is required to process payment, for example Minimum amount of 1.00 USD is required to process payment
  • UNSUPPORTED_BILLING_CURRENCY
    • Trigger: 요청한 billing currency가 이 subscription에서 지원되지 않음
    • Message: Non USD billing currency is not supported for subscriptions
  • UNSUPPORTED_COUNTRY
    • Trigger: country가 지원되지 않음
    • Message: Country {country_name} currently not supported
  • UNSUPPORTED_CURRENCY
    • Trigger: product 또는 add-on currency가 Dodo Payments에서 청구할 수 없는 currency임. Base price는 청구 가능한 모든 currency로 설정할 수 있으므로, 이 오류는 일반적으로 currency code가 유효하지 않거나 지원되지 않음을 의미합니다.
    • 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: tax category가 지원되는 값 중 하나가 아님
    • Message: Category {category} currently not supported

Validation & Requests

  • DUPLICATE_LINE_ITEMS_IN_REQUEST
    • Trigger: 동일한 item_id가 items[]에 두 번 이상 나타남
    • Message: Duplicate item_ids specified in items array
  • INVALID_QUERY_PARAMS
    • Trigger: 상호 배타적이거나 형식이 잘못된 query parameter
    • 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: 형식이 잘못된 JSON 또는 schema 위반
    • Message: Your request body is invalid. Please check your request headers and object.
  • INVALID_REQUEST_PARAMETERS
    • Trigger: 형식상 유효하지만 의미상 유효하지 않은 parameter 값(예: 과거 날짜)
    • Message: Cannot change next_billing_date to past time (or) A checkout with more than one subscription product cannot hold one-time products (or) All product IDs must be unique (or) On demand subscriptions cannot hold more than one product (or) A checkout can hold at most 20 subscription products (or) Duplicate subscription products in one checkout are not allowed
  • MAXIMUM_KEYS_REACHED
    • Trigger: metadata 또는 custom field가 50개의 key-value pair를 초과함
    • Message: Exceeds 50 key-value pairs

General & System

  • INTEGER_CONVERSION_FAILURE
    • Trigger: integer와 string 또는 decimal 간의 server-side conversion 실패(예: cart total이 너무 커서 처리할 수 없음)
    • 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: 예상치 못한 server error. 자체 시스템에서 request details를 기록하세요.
    • Message: 공개 message 없음(generic 500, message는 일반적으로 null임)
  • NOT_FOUND
    • Trigger: 누락된 모든 resource에 대한 일반적인 404
    • Message: Item not found (or a more specific message that names what is missing)
  • TOO_MANY_REQUESTS
    • Trigger: rate limit을 초과함(HTTP 429)
    • Message: 메시지 없음
  • UNSUPPORTED_ACTION
    • Trigger: resource type이 지원하지 않는 작업
    • Message: Changing plans for usage based subscriptions is not supported

Best Practices

API error를 처리할 때 다음 practices를 따르세요:
  1. 애플리케이션에서 모든 error response를 처리하고, message가 아니라 code를 기준으로 분기하세요.
  2. 실패한 모든 request의 HTTP status, code 및 message를 기록하세요.
  3. raw API message 대신 최종 사용자를 위한 message를 표시하세요.
  4. 429 및 5xx response 또는 DISCOUNT_CONCURRENT_REDEMPTION와 같은 transient error만 지연 후 retry하세요.
  5. 해결할 수 없는 error는 support에 문의하세요.

Support

error code 또는 integration issue에 대한 추가 지원이 필요하면 support@dodopayments.com으로 support team에 문의하세요.
마지막 수정일 2026년 10월 8일