Payment Orchestrator
Payment

Payment — Single Endpoint

POST /payments/direct/payment starts a payment from your server with any payment method open on your account: card, wallet, mobile billing (Faturana Yansıt) and promissory notes (Senetle Öde) use the same endpoint and the same order fields. The paymentMethod field selects the method; method-specific data goes in that method's block. When the buyer has to do something (enter a verification code, go to a bank page) the response carries an action. The final result is always sent by webhook as well.

This page is for the Direct API path, where you start the payment from your own server. If you take payments with the Checkout Form, the form makes the method calls → Checkout Form — Payment. The 2D and 3D Secure rules for card payments are on the Card pages.

All amounts are integers in minor units (kuruş): "amount": 5000 = ₺50.00. Do not send decimals or floats.

How it works

Read the open methods

GET /payments/methods returns the methods open on your account, the providers of each method, who chooses the provider (providerSelectionMode) and the fields the provider asks the buyer for (inputFields).

Start the payment

Call POST /payments/direct/payment with paymentMethod, the order fields and only that method's block. The request carries Step-Up authentication and an Idempotency-Key.

Complete the action

If the response has an action, do what the buyer is expected to do: for OTP send the code with confirm; for REDIRECT send the buyer to action.redirect.url. Without action the result is in the response or is awaited from the provider.

Confirm with the webhook

The final result reaches your webhook as payment.captured, payment.authorized or payment.failed. Ship the order on payment.captured.

Methods

MethodpaymentMethodBlockWhat the buyer doesPage
CardCARDcardVerifies at the bank page for 3D Secure (REDIRECT)Card
WalletWALLETwalletEnters the code sent to their phone (OTP)Pay with Wallet
Mobile billing (Faturana Yansıt)MOBILE_BILLINGmobileBillingEnters the code sent to their phone and accepts the agreement (OTP)Mobile Billing
Promissory notes (Senetle Öde)PROMISSORY_NOTEpromissoryNoteProvides debtor details; the notes are issued immediately (no action)Promissory Notes
  • The methods above can be started from this endpoint today. The other methods in the Payment menu are coming soon.
  • This endpoint takes a single method. To split one order across several cards and methods, use the Split Payments endpoint.
  • The methods and providers you can use are in the GET /payments/methods response.
  • An unknown method code gets 400 payment.method.unknown; a method that cannot be used on this endpoint gets 400 payment.method.not_supported. The request is never turned into another method or into a card payment.

Authentication

POST /payments/direct/payment and GET /payments/methods require Step-Up: your Authorization: Bearer at_… token and an Ed25519 signature of the request.

HeaderValue
AuthorizationBearer at_test_… (test) or Bearer at_live_… (live)
X-Key-IdID of your registered Ed25519 public key
X-DateISO 8601 request time; within ±5 minutes of server time
X-NonceUnique single-use value per request
DigestFor requests with a body, SHA-256=<base64> digest of the raw JSON body
X-SignatureBase64 Ed25519 signature over the canonical string
Idempotency-KeyRequired on POST /payments/direct/payment, at most 200 characters; see Idempotency

How to build the signature is described on Authentication. The endpoints require the Payment Gateway product to be active on your account.

Listing the open methods

GET /payments/methods returns the methods open on your account, the providers of each method, who chooses the provider (providerSelectionMode) and the fields asked from the buyer (inputFields); ?paymentMethod= reads a single method's row. Methods and providers come in your Form Settings order. The endpoint, the response fields, the order and the provider selection rules: Listing Methods.

Method fields (inputFields)

The fields in the block are defined by the provider's inputFields definition; you send the values under the definition's key. The definition's fields and value types: Listing Methods › Method fields.

"mobileBilling": { "providerCode": "<providerCode>", "gsmNumber": "+905321234567" }
  • A key that is not in the definition, a missing required field or a value that does not match its type gets 400 payment.method.block_invalid. The offending field is in details.field (e.g. mobileBilling.gsmNumber) and details.reason; every violation is listed in details.errors[]. The value you sent is never included in the error response.
  • In nested fields the path points to the field: promissoryNote.address.districtCode, promissoryNote.guarantors[1].identityNumber.
  • details.reason values: unknown_field, required, not_applicable (a field sent while its requiredWhen condition does not hold), invalid_type, invalid_format, too_short, too_long, invalid_option, too_few_items, too_many_items (GROUP item count). Method-specific reasons are on the method page, e.g. Promissory Notes.
  • Values are only passed to the provider; they are not stored on the payment record.

Address dictionary

The province, district and neighbourhood codes of an ADDRESS field come from the Lunixi address dictionary. The dictionary endpoints are public: they need no authentication and return no personal data. Responses may be cached for a day.

EndpointQueryReturns
GET /api/v1/reference/tr-address/provinces—Provinces: code "01"–"81"
GET /api/v1/reference/tr-address/districtsprovinceCode (required, "01"–"81")Districts of the province
GET /api/v1/reference/tr-address/neighborhoodsdistrictCode (required, digits)Neighbourhoods of the district
GET https://api-gateway.lunixi.com/api/v1/reference/tr-address/districts?provinceCode=06
{
  "status": "success",
  "code": "SUCCESS",
  "message": "…",
  "data": {
    "items": [
      { "code": "<districtCode>", "name": "<district name>" }
    ]
  },
  "statusCode": 200,
  "requestId": "…"
}
  • Read the codes from the dictionary and let the buyer pick by name; do not build codes by hand. If the neighbourhood, district and province do not belong together the request gets 400 payment.method.block_invalid (….address.neighborhoodCode, invalid_option).
  • An invalid provinceCode or districtCode query gets 400. For a province or district without entries in the dictionary the list is empty.

Request

POST https://api-gateway.lunixi.com/api/v1/payments/direct/payment
Content-Type: application/json

Fields

FieldTypeRequiredDescription
paymentMethodstringYesMethod code: CARD, WALLET, MOBILE_BILLING, PROMISSORY_NOTE
cardobjectFor CARDCard data; see card
walletobjectFor WALLETWallet block; see Pay with Wallet
mobileBillingobjectFor MOBILE_BILLINGMobile billing block; see Mobile Billing
promissoryNoteobjectFor PROMISSORY_NOTEPromissory-note block: due-date schedule or note count and debtor fields; see Promissory Notes
force3DbooleanNoOnly with CARD. true: 3D Secure; omitted or false: 2D. See Card
installmentintegerNoOnly with CARD; number of installments, default 1
installmentQuoteTokenstringNoOnly with CARD; binding token of the installment quote
preauthbooleanNotrue: pre-authorization, the payment becomes AUTHORIZED. See Pre-authorization
callbackUrlstringNohttp or https, at most 2048 characters. Address the buyer's browser returns to with the result (REDIRECT action; e.g. card 3D Secure)

Order fields

FieldTypeRequiredDescription
amountintegerYesAmount, minor-unit integer; at least 1. It is the basket total: the price of the goods and services the buyer pays for, excluding the installment fee. If you send basketItems, it must equal the sum of the items' price. For card installments the system adds the fee. Example: 10050
currencystring (enum)YesISO 4217 code: TRY, USD, EUR, GBP, RUB, AED, SAR, QAR, KWD, JPY, CHF, CAD, AUD, CNY, AZN. A currency not enabled on your account is rejected
orderIdstringYesYour order number, at most 128 characters. Example: ORD-84722
customerIdstringNoYour customer key. It identifies the buyer for wallet payments; when a card is saved with 3D Secure, it is stored under this key. Example: cust_7788
descriptionstringNoPayment description
localestringNoMessage language, default tr
paymentChannelstringNoPayment channel. Example: WEB
paymentGroupstringNoProduct group. Example: PRODUCT
buyerobjectNoBuyer details; see buyer
shippingAddressobjectNoShipping address; see Address
billingAddressobjectNoBilling address; see Address
basketItemsarrayNoBasket items; see basketItems[]
metadataobjectNoFree key-value object for your own records. Request a pre-authorization with the preauth field, not with metadata

The amount is sent only in amount; the removed amount fields get 400 payment.amount.field_removed. Sending a field that is not defined here rejects the request with 400 VALIDATION_ERROR.

buyer.gsmNumber is a prefill source for method fields: it is used when the wallet or mobile billing block has no phone. metadata is not read in payment decisions: for example a method or pre-authorization value written into metadata does not change the payment.

card

FieldTypeRequiredDescription
cardHolderNamestringRaw cardName as printed on the card
cardNumberstringRaw cardCard number
expireMonthstringRaw cardTwo-digit month, 01–12
expireYearstringRaw cardTwo-digit year. Example: 30
cvcNumberstringRaw card3 or 4 digit security code. Most banks also require it for saved-card charges
cardUserKeystringSaved cardCustomer key the card is stored under
cardTokenstringSaved cardPermanent reference of the saved card (storedCardToken). The Checkout Form's single-use card token cannot be used here
cardSavebooleanNotrue: the card is saved under the customerId key once the payment succeeds. Only allowed on a 3D Secure request (force3D: true); a 2D request gets 400 payment.card.save_requires_3ds
cardNamestringNoA name you give the saved card; used together with cardSave: true. Example: Work card
  • When sent, expireMonth and expireYear must have two digits.
  • For a raw card charge send cardHolderName, cardNumber, expireMonth, expireYear and cvcNumber. For a saved card charge send cardUserKey and cardToken instead of the raw card fields.

buyer

buyer is optional. If you send it, every field marked "Yes" below must be filled. On a Checkout Form intent (POST /payments/intents, POST /payments/marketplace/intents) this rule does not apply: every field is optional, and the fields you send are checked for type and length.

FieldTypeRequiredExample
idstringNoCUST-1
namestringYesAda
surnamestringYesYılmaz
identityNumberstringYes11111111111
emailstring (email)Yes[email protected]
gsmNumberstringYes+905000000000
citystringYesIstanbul
countrystringYesTurkey
zipCodestringYes34732
ipstringYesThe buyer's IP address
registrationDatestringNo2024-04-21 15:12:09
lastLoginDatestringNo2026-10-05 12:43:35
registrationAddressstringNoRegistered address

Required-field rule, how it differs from customerId, and error field paths: Buyer.

Address

shippingAddress and billingAddress share the same shape. If you send the object, all five fields are required.

FieldTypeExample
contactNamestringAda Yılmaz
addressstringAltunizade Mah. …
citystringIstanbul
countrystringTurkey
zipCodestring34742

How the two addresses differ and error field paths: Addresses.

basketItems[]

FieldTypeRequiredDescription
idstringYesItem code
namestringYesItem name
category1stringYesMain category
category2stringNoSub-category
itemTypestring (enum)YesPHYSICAL or VIRTUAL
priceintegerYesItem amount, minor-unit integer, at least 0

The sum of the items' price must equal amount; otherwise the request is rejected with 400 VALIDATION_ERROR. The installment fee is not added to the items.

Rules

  • The amount is sent only in amount; the removed amount fields get 400 payment.amount.field_removed. If you send basketItems, the items' price must add up to amount; otherwise the request gets 400 VALIDATION_ERROR.
  • If a card installment is chosen (installment + installmentQuoteToken), the system computes the installment fee from the quote and adds it to the charged amount: charged amount = amount + installment fee. Amount fields in queries and webhooks show this charged amount.
  • The body contains only the block that matches paymentMethod. Another method's block, or card, force3D, installment, installmentQuoteToken with a non-card method, gets 400 VALIDATION_ERROR.
  • The method's block is required. The fields in the block are the provider's inputFields definition; apart from providerCode, fields that are not in the definition cannot be sent.
  • providerCode: not needed when one provider is connected for the method. When more than one is connected, the method's providerSelectionMode sets the rule:
    • BUYER (e.g. wallet): required; if you omit it you get 400 payment.provider.required with the connected codes in details.boundProviderCodes.
    • PLATFORM (e.g. mobile billing): optional. If you omit it, the platform picks one of the connected providers before any money moves; if none of them can take this payment you get 422 payment.provider.none_eligible.
  • The selected provider is pinned: on an error the payment does not move to another provider, another method or card.
  • A provider you turned off only for the form in Form Settings is accepted on this endpoint; turning it off affects only the Checkout Form. To turn a provider off everywhere, turn off its provider connection.
  • An undefined field (method, basketId, paymentSource …) gets 400 VALIDATION_ERROR.

Example request

# See the Authentication page for how the Step-Up signature headers are computed.
curl -X POST https://api-gateway.lunixi.com/api/v1/payments/direct/payment \
  -H "Authorization: Bearer at_test_5f3e2b1a..." \
  -H "Content-Type: application/json" \
  -H "X-Key-Id: mk_test_sk_..." \
  -H "X-Date: 2026-10-11T09:00:00.000Z" \
  -H "X-Nonce: 8d4f2c1e-0a7b-4b3c-9e5d-6f1a2b3c4d5e" \
  -H "Digest: SHA-256=..." \
  -H "X-Signature: ..." \
  -H "Idempotency-Key: ORDER-1002-1" \
  -d '{
    "paymentMethod": "MOBILE_BILLING",
    "orderId": "ORDER-1002",
    "amount": 5000,
    "currency": "TRY",
    "basketItems": [
      { "id": "DIGITAL-1", "name": "Digital product", "category1": "Digital", "itemType": "VIRTUAL", "price": 5000 }
    ],
    "mobileBilling": { "gsmNumber": "+905321234567" }
  }'

Method-specific examples: Card — 2D, Card — 3D Secure, Pay with Wallet, Mobile Billing, Promissory Notes.

Response

The response uses the common envelope; the payment itself is in data. Starting a payment, confirm and resend use the same shape.

{
  "status": "partial",
  "code": "CUSTOMER_ACTION_REQUIRED",
  "message": "…",
  "data": {
    "paymentId": "7b0e4c2a-1f3d-4e5b-8a6c-9d0e1f2a3b4c",
    "orderId": "ORDER-1002",
    "status": "PROCESSING",
    "paymentMethod": "MOBILE_BILLING",
    "providerCode": "<providerCode>",
    "action": {
      "id": "act_5c2e9f0a1b3d4e6f7a8b9c0d1e2f3a4b",
      "type": "OTP",
      "expiresAt": "2026-10-11T09:03:00.000Z",
      "otp": { "maskedTarget": "53****67" },
      "consent": { "required": true, "url": "https://…" }
    }
  },
  "statusCode": 202,
  "requestId": "…"
}
HTTPEnvelope statusMeaning
200successThe payment is final: data.status is CAPTURED or (for a pre-authorization) AUTHORIZED
202partialThe payment is in progress: action describes what the buyer must do, or the result is being verified with the provider (PAYMENT_PENDING_RECONCILIATION)
400failureThe payment was declined: data.status is FAILED; code carries the decline reason

In a decline, details.retryability (RETRYABLE, NON_RETRYABLE, UNKNOWN) tells whether retrying the same request makes sense. If the request was rejected before it was processed (validation, authentication, method or provider error), data is empty and code describes the error; see Errors.

data fields

FieldTypeDescription
paymentIdstringPayment ID; used in confirm, resend, capture and query calls
orderIdstringYour order number
statusstringPayment status; see the table below
paymentMethodstringMethod code
providerCodestringCode of the provider processing the payment; absent when not known yet
actionobjectWhat the buyer is expected to do; present only while an action is open. See Actions
savedCardobjectCard only: a card newly saved in this payment; see Card — 3D Secure
data.statusWhen
INITIATEDFor the merchant's own wallet program, waiting for the code confirmation; see Pay with Wallet
PROCESSINGThe provider is waiting for the buyer (e.g. a code)
AWAITING_3DCard 3D Secure verification is pending
AUTHORIZEDPre-authorization: the amount is held
CAPTUREDThe money was charged
FAILEDThe payment was declined; nothing was charged
NEEDS_RECONCILIATIONThe result is being verified with the provider; the final result arrives by webhook
⚠️

Do not start a new payment after a 202 response or while the status is NEEDS_RECONCILIATION. When the result is final, payment.captured or payment.failed is sent; you can also read the status with GET /payments/:id.

Actions

action tells you the buyer has to do something. A payment has at most one open action at a time. The types a method can return are in the actionTypes field of the GET /payments/methods response.

TypeWhat the buyer doesWhat you do
OTPEnters the code sent to their phone; accepts the agreement when consent.requiredSend the code and the consent with confirm. To send a new code, use resend
REDIRECTGoes to the provider's or bank's page and comes backSend the buyer to action.redirect.url. No confirm is needed; the result reaches your callbackUrl and your webhook
INPUTEnters additional data requested by the provider (action.input.fields)Send the values with fields in the confirm body

If you receive a type you do not recognise, do not treat the payment as paid; wait for the webhook.

FieldTypeDescription
idstringAction ID; used in the confirm and resend paths
typestringOTP, REDIRECT, INPUT
expiresAtstringWhen the action expires (ISO 8601)
otp.maskedTargetstringMasked number the code was sent to. Example: 53****67
consent.requiredbooleanWhen true the code must be sent together with the agreement consent
consent.urlstringAddress of the agreement to show the buyer
input.fieldsarrayFields requested by an INPUT action; same shape as inputFields
chargeobjectAmount breakdown to show the buyer before confirming (minor units): amount, feeTotal, taxTotal, buyerTotalCharge, currency. buyerTotalCharge = amount + feeTotal + taxTotal
maskedBusinessNamestringMasked name of the business receiving the payment
stepUpRequiredbooleanPresent only when true: the provider requested strong verification. No extra input is expected
redirect.urlstringFor a REDIRECT action, the address the buyer goes to

Provider session data, references and verification codes never appear in any response, query or webhook.

Confirming an action — confirm

POST https://api-gateway.lunixi.com/api/v1/payments/{paymentId}/actions/{actionId}/confirm

Completes the open action; it does not start a new charge. When calling from your server, send the signature headers described on Authentication (X-Key-Id, X-Date, X-Nonce, Digest, X-Signature); do not put token in the body. If the payment does not belong to your account or the action cannot be found you get 404 payment.action.not_found.

FieldTypeDescription
otpstringThe code the buyer entered; digits only, at most 16 characters
consentAcceptedbooleanAgreement consent. Must be true when action.consent.required is true
fieldsobjectFields requested by an INPUT action. For an OTP action the code may also be sent as { "otp": "123456" }
{ "otp": "123456", "consentAccepted": true }

The response has the same shape as the payment response:

OutcomeHTTPcodeWhat to do
Payment completed200PAYMENT_CAPTURED or PAYMENT_AUTHORIZEDShip the order on payment.captured
Code rejected, attempts left422payment.action.input_rejectedThe action stays open; remaining attempts are in details.attemptsRemaining. The buyer enters the code again
No attempts left400payment.action.attempts_exhaustedThe payment becomes FAILED
Declined by the provider400Decline codeThe payment becomes FAILED
Result being verified202PAYMENT_PENDING_RECONCILIATIONDo not open a new payment; wait for the webhook
  • If you send the same confirm again, the provider is not called a second time; the recorded result is returned. If your connection dropped you can safely repeat the request.
  • Attempts are counted per action; unless the provider declares otherwise there are 3.
  • When the action expires (expiresAt) it is closed. For a verification code sent by a provider the payment becomes FAILED and payment.failed is sent; for the merchant's own wallet program see Pay with Wallet.
  • If the code or the consent is missing, the request is rejected without using an attempt: payment.action.otp_required, payment.action.consent_required.

Resending the code — resend

POST https://api-gateway.lunixi.com/api/v1/payments/{paymentId}/actions/{actionId}/resend

Sends a new code when the provider supports it. The previous action is closed and the response (202) carries the new action; use the new action.id for confirm. The body is empty ({}); authentication is the same as for confirm.

Pre-authorization

To hold the amount before charging it, send "preauth": true. When the payment succeeds it becomes AUTHORIZED and payment.authorized is sent; you later charge it with capture or remove the hold with void.

Capture, void, expiry and errors: Pre-authorization, Capture & Void.

Idempotency

Idempotency-Key is required on this endpoint (at most 200 characters). Without it the request gets 400 payment.operation.idempotency_key_required and is not processed. Use a value that identifies the attempt, not the payment (for example ORDER-1002-1).

SituationResult
Same key, same requestThe result of the first attempt is returned; no second payment is started. An open action is included again
Same key, different request409 payment.idempotency.conflict
The first request with the same key is still running429 payment.idempotency.processing; retry shortly with the same key

To retry a declined order, send a new Idempotency-Key.

Results and webhooks

EventWhen
payment.capturedThe money was charged. Ship the order on this event
payment.authorizedFor a pre-authorization the amount was held; nothing has been charged yet
payment.failedThe payment failed; nothing was charged (including a provider code that expired or ran out of attempts)

The data object of payment events carries paymentMethod and providerCode:

{
  "id": "2f6c1b9e-…",
  "type": "payment.captured",
  "data": {
    "intentId": "7b0e4c2a-1f3d-4e5b-8a6c-9d0e1f2a3b4c",
    "merchantId": "m_…",
    "orderId": "ORDER-1002",
    "currency": "TRY",
    "status": "CAPTURED",
    "paymentMethod": "MOBILE_BILLING",
    "providerCode": "<providerCode>",
    "capturedAmountMinor": "5000"
  }
}
FieldDescription
data.paymentMethodMethod code (CARD, WALLET, MOBILE_BILLING, PROMISSORY_NOTE …)
data.providerCodeCode of the provider processing the payment; absent when the payment has no provider yet

When you query the payment with GET /payments/:id, the response also carries paymentMethod and, when an action is open, action. For delivery, signature verification and the other fields see Webhooks.

Errors

Error responses use the common error envelope; branch on code, not on message → Error Handling.

SituationResponseWhat to do
Missing, invalid or undefined field; wrong block400 VALIDATION_ERRORFix the field named in details
A removed amount field was sent400 payment.amount.field_removedSend the amount only in amount
Basket total does not equal amount400 VALIDATION_ERRORMake the items' price add up to amount
No Idempotency-Key400 payment.operation.idempotency_key_requiredSend a key with every attempt
Method unknown or not usable on this endpoint400 payment.method.unknown, payment.method.not_supportedUse a method from the GET /payments/methods list
Block fields do not match the provider's definition400 payment.method.block_invalidFix the field in details.field
The method is disabled in the panel (form settings)422 payment.method.disabledEnable the method in the panel; read the enabled methods with GET /payments/methods
BUYER method with more than one provider connected, none selected400 payment.provider.requiredSend <block>.providerCode
PLATFORM method where none of the connected providers can take the payment422 payment.provider.none_eligibleCheck the results in details.candidates; retry later or choose a provider with providerCode
The selected provider is not available422 payment.provider.not_availableSelect a provider from the list
The method does not support pre-authorization422 payment.preauth.unsupported_for_methodSend it without preauth
Authentication, signature or product entitlement error401, 403, 503See Card — 2D › Errors
Same key, different request409 payment.idempotency.conflictUse a new key for a new attempt
A request with the same key is running429 payment.idempotency.processingRetry shortly with the same key
Declined by the provider or by risk checks400, payment FAILEDShow the decline; use a new key for a new attempt
Result not final yet202 PAYMENT_PENDING_RECONCILIATIONDo not open a new payment; wait for the webhook

Method-specific errors are on the method pages.

Error codes

The codes below are specific to payment methods, provider selection and the action endpoints.

CodeHTTPMeaning and what to do
payment.method.unknown400paymentMethod is not recognised. Send a valid method code
payment.method.not_supported400The method code is recognised but cannot be used for this operation. Use the methods in GET /payments/methods
payment.method.block_invalid400The method block does not match the provider's inputFields definition. The offending field is in details.field, the reason in details.reason, every violation in details.errors[]
payment.method.disabled422The method is disabled in the business's form settings. A method disabled in the panel is disabled on the form, in the list and on this endpoint; the payment is rejected before it starts
payment.method.wallet_bridge_not_available422The selected wallet's verification flow is not supported on this endpoint; this endpoint confirms wallet payments with a one-time code
payment.method.customer_identity_conflict400For wallet payments the buyer is identified by the customerId field. metadata.customerId cannot be sent without it or differ from it
payment.provider.required400For this method the buyer chooses the provider (BUYER) and more than one provider is connected. Select one with <block>.providerCode; the connected codes are in details.boundProviderCodes. Details: Error Handling
payment.provider.none_eligible422PLATFORM method, no providerCode sent, and none of the connected providers can take this payment; the payment was not started and nothing was charged. Details: Error Handling
payment.provider.not_available422The selected provider cannot be used for this method. The payment is not routed to another provider
payment.provider.pin_violation500The payment cannot be completed right now; nothing was charged. Retry later
payment.operation.idempotency_key_required400The Idempotency-Key header is required on this endpoint
payment.action.not_found404The payment or the action was not found (including a payment of another account). Check paymentId and action.id
payment.action.replaced409The action was replaced by a new one through resend. Continue with the details.replacedByActionId action and the latest code
payment.action.expired409The action has expired. Start a new payment
payment.action.in_progress409Another request for the same action is being processed. Repeat the same request in a few seconds; the recorded result is returned
payment.action.closed409The action is closed; no operation is possible on it
payment.action.payment_not_pending409The payment is no longer waiting for this step. Read the status with GET /payments/:id
payment.action.otp_required400The code was not sent or its format is invalid (digits only). No attempt is used
payment.action.consent_required422The agreement consent is required: send consentAccepted: true. No attempt is used
payment.action.input_invalid400fields does not match the action.input.fields definition; the offending field is in details.field. No attempt is used
payment.action.input_rejected422The provider rejected the code. The action stays open; remaining attempts are in details.attemptsRemaining. This is a payment response: data carries the payment and the open action
payment.action.attempts_exhausted400No attempts left; the payment became FAILED. This is a payment response
payment.action.confirm_not_applicable409This action is not completed with confirm; the buyer goes to action.redirect.url, the result is verified on return and sent by webhook
payment.action.resend_not_supported422The code cannot be resent for this method
payment.action.resend_too_soon429Not enough time has passed since the previous send. Wait details.retryAfterSeconds seconds
payment.action.resend_limit_reached422The resend limit for this payment has been reached. Continue with the current code or start a new payment
payment.action.resend_failed502A new code could not be sent right now; the current action is still open and its code may still be valid. Retry
payment.action.auth_ambiguous400The request carries both an API signature and a checkout token. Call from your server with the signature only

Next steps