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
| Method | paymentMethod | Block | What the buyer does | Page |
|---|---|---|---|---|
| Card | CARD | card | Verifies at the bank page for 3D Secure (REDIRECT) | Card |
| Wallet | WALLET | wallet | Enters the code sent to their phone (OTP) | Pay with Wallet |
| Mobile billing (Faturana Yansıt) | MOBILE_BILLING | mobileBilling | Enters the code sent to their phone and accepts the agreement (OTP) | Mobile Billing |
| Promissory notes (Senetle Öde) | PROMISSORY_NOTE | promissoryNote | Provides 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/methodsresponse. - An unknown method code gets
400payment.method.unknown; a method that cannot be used on this endpoint gets400payment.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.
| Header | Value |
|---|---|
Authorization | Bearer at_test_… (test) or Bearer at_live_… (live) |
X-Key-Id | ID of your registered Ed25519 public key |
X-Date | ISO 8601 request time; within ±5 minutes of server time |
X-Nonce | Unique single-use value per request |
Digest | For requests with a body, SHA-256=<base64> digest of the raw JSON body |
X-Signature | Base64 Ed25519 signature over the canonical string |
Idempotency-Key | Required 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
400payment.method.block_invalid. The offending field is indetails.field(e.g.mobileBilling.gsmNumber) anddetails.reason; every violation is listed indetails.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.reasonvalues:unknown_field,required,not_applicable(a field sent while itsrequiredWhencondition does not hold),invalid_type,invalid_format,too_short,too_long,invalid_option,too_few_items,too_many_items(GROUPitem 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.
| Endpoint | Query | Returns |
|---|---|---|
GET /api/v1/reference/tr-address/provinces | — | Provinces: code "01"–"81" |
GET /api/v1/reference/tr-address/districts | provinceCode (required, "01"–"81") | Districts of the province |
GET /api/v1/reference/tr-address/neighborhoods | districtCode (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
provinceCodeordistrictCodequery gets400. 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/jsonFields
| Field | Type | Required | Description |
|---|---|---|---|
paymentMethod | string | Yes | Method code: CARD, WALLET, MOBILE_BILLING, PROMISSORY_NOTE |
card | object | For CARD | Card data; see card |
wallet | object | For WALLET | Wallet block; see Pay with Wallet |
mobileBilling | object | For MOBILE_BILLING | Mobile billing block; see Mobile Billing |
promissoryNote | object | For PROMISSORY_NOTE | Promissory-note block: due-date schedule or note count and debtor fields; see Promissory Notes |
force3D | boolean | No | Only with CARD. true: 3D Secure; omitted or false: 2D. See Card |
installment | integer | No | Only with CARD; number of installments, default 1 |
installmentQuoteToken | string | No | Only with CARD; binding token of the installment quote |
preauth | boolean | No | true: pre-authorization, the payment becomes AUTHORIZED. See Pre-authorization |
callbackUrl | string | No | http 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
| Field | Type | Required | Description |
|---|---|---|---|
amount | integer | Yes | Amount, 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 |
currency | string (enum) | Yes | ISO 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 |
orderId | string | Yes | Your order number, at most 128 characters. Example: ORD-84722 |
customerId | string | No | Your 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 |
description | string | No | Payment description |
locale | string | No | Message language, default tr |
paymentChannel | string | No | Payment channel. Example: WEB |
paymentGroup | string | No | Product group. Example: PRODUCT |
buyer | object | No | Buyer details; see buyer |
shippingAddress | object | No | Shipping address; see Address |
billingAddress | object | No | Billing address; see Address |
basketItems | array | No | Basket items; see basketItems[] |
metadata | object | No | Free 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
| Field | Type | Required | Description |
|---|---|---|---|
cardHolderName | string | Raw card | Name as printed on the card |
cardNumber | string | Raw card | Card number |
expireMonth | string | Raw card | Two-digit month, 01–12 |
expireYear | string | Raw card | Two-digit year. Example: 30 |
cvcNumber | string | Raw card | 3 or 4 digit security code. Most banks also require it for saved-card charges |
cardUserKey | string | Saved card | Customer key the card is stored under |
cardToken | string | Saved card | Permanent reference of the saved card (storedCardToken). The Checkout Form's single-use card token cannot be used here |
cardSave | boolean | No | true: 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 |
cardName | string | No | A name you give the saved card; used together with cardSave: true. Example: Work card |
- When sent,
expireMonthandexpireYearmust have two digits. - For a raw card charge send
cardHolderName,cardNumber,expireMonth,expireYearandcvcNumber. For a saved card charge sendcardUserKeyandcardTokeninstead 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.
| Field | Type | Required | Example |
|---|---|---|---|
id | string | No | CUST-1 |
name | string | Yes | Ada |
surname | string | Yes | Yılmaz |
identityNumber | string | Yes | 11111111111 |
email | string (email) | Yes | [email protected] |
gsmNumber | string | Yes | +905000000000 |
city | string | Yes | Istanbul |
country | string | Yes | Turkey |
zipCode | string | Yes | 34732 |
ip | string | Yes | The buyer's IP address |
registrationDate | string | No | 2024-04-21 15:12:09 |
lastLoginDate | string | No | 2026-10-05 12:43:35 |
registrationAddress | string | No | Registered 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.
| Field | Type | Example |
|---|---|---|
contactName | string | Ada Yılmaz |
address | string | Altunizade Mah. … |
city | string | Istanbul |
country | string | Turkey |
zipCode | string | 34742 |
How the two addresses differ and error field paths: Addresses.
basketItems[]
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Item code |
name | string | Yes | Item name |
category1 | string | Yes | Main category |
category2 | string | No | Sub-category |
itemType | string (enum) | Yes | PHYSICAL or VIRTUAL |
price | integer | Yes | Item 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 get400payment.amount.field_removed. If you sendbasketItems, the items'pricemust add up toamount; otherwise the request gets400 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, orcard,force3D,installment,installmentQuoteTokenwith a non-card method, gets400 VALIDATION_ERROR. - The method's block is required. The fields in the block are the provider's
inputFieldsdefinition; apart fromproviderCode, 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'sproviderSelectionModesets the rule:BUYER(e.g. wallet): required; if you omit it you get400payment.provider.requiredwith the connected codes indetails.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 get422payment.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…) gets400 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": "…"
}| HTTP | Envelope status | Meaning |
|---|---|---|
200 | success | The payment is final: data.status is CAPTURED or (for a pre-authorization) AUTHORIZED |
202 | partial | The payment is in progress: action describes what the buyer must do, or the result is being verified with the provider (PAYMENT_PENDING_RECONCILIATION) |
400 | failure | The 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
| Field | Type | Description |
|---|---|---|
paymentId | string | Payment ID; used in confirm, resend, capture and query calls |
orderId | string | Your order number |
status | string | Payment status; see the table below |
paymentMethod | string | Method code |
providerCode | string | Code of the provider processing the payment; absent when not known yet |
action | object | What the buyer is expected to do; present only while an action is open. See Actions |
savedCard | object | Card only: a card newly saved in this payment; see Card — 3D Secure |
data.status | When |
|---|---|
INITIATED | For the merchant's own wallet program, waiting for the code confirmation; see Pay with Wallet |
PROCESSING | The provider is waiting for the buyer (e.g. a code) |
AWAITING_3D | Card 3D Secure verification is pending |
AUTHORIZED | Pre-authorization: the amount is held |
CAPTURED | The money was charged |
FAILED | The payment was declined; nothing was charged |
NEEDS_RECONCILIATION | The 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.
| Type | What the buyer does | What you do |
|---|---|---|
OTP | Enters the code sent to their phone; accepts the agreement when consent.required | Send the code and the consent with confirm. To send a new code, use resend |
REDIRECT | Goes to the provider's or bank's page and comes back | Send the buyer to action.redirect.url. No confirm is needed; the result reaches your callbackUrl and your webhook |
INPUT | Enters 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.
| Field | Type | Description |
|---|---|---|
id | string | Action ID; used in the confirm and resend paths |
type | string | OTP, REDIRECT, INPUT |
expiresAt | string | When the action expires (ISO 8601) |
otp.maskedTarget | string | Masked number the code was sent to. Example: 53****67 |
consent.required | boolean | When true the code must be sent together with the agreement consent |
consent.url | string | Address of the agreement to show the buyer |
input.fields | array | Fields requested by an INPUT action; same shape as inputFields |
charge | object | Amount breakdown to show the buyer before confirming (minor units): amount, feeTotal, taxTotal, buyerTotalCharge, currency. buyerTotalCharge = amount + feeTotal + taxTotal |
maskedBusinessName | string | Masked name of the business receiving the payment |
stepUpRequired | boolean | Present only when true: the provider requested strong verification. No extra input is expected |
redirect.url | string | For 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}/confirmCompletes 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.
| Field | Type | Description |
|---|---|---|
otp | string | The code the buyer entered; digits only, at most 16 characters |
consentAccepted | boolean | Agreement consent. Must be true when action.consent.required is true |
fields | object | Fields 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:
| Outcome | HTTP | code | What to do |
|---|---|---|---|
| Payment completed | 200 | PAYMENT_CAPTURED or PAYMENT_AUTHORIZED | Ship the order on payment.captured |
| Code rejected, attempts left | 422 | payment.action.input_rejected | The action stays open; remaining attempts are in details.attemptsRemaining. The buyer enters the code again |
| No attempts left | 400 | payment.action.attempts_exhausted | The payment becomes FAILED |
| Declined by the provider | 400 | Decline code | The payment becomes FAILED |
| Result being verified | 202 | PAYMENT_PENDING_RECONCILIATION | Do 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 becomesFAILEDandpayment.failedis 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}/resendSends 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.
- A code can be resent at most 3 times per payment; after that you get
422payment.action.resend_limit_reached. - At least 30 seconds must pass between sends; an earlier request gets
429payment.action.resend_too_soonwith the wait time indetails.retryAfterSeconds. - For a method that does not support resending you get
422payment.action.resend_not_supported. - If the provider cannot send the code you get
502payment.action.resend_failedand the current action stays open. - A confirm on the old action gets
409payment.action.replaced; the new action's ID is indetails.replacedByActionId.
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.
- For card the rules are on Card — 2D and Card — 3D Secure.
- For a non-card method the provider must support pre-authorization (
preauthin theGET /payments/methodsresponse). With a method that does not, the request gets422payment.preauth.unsupported_for_methodbefore the payment starts; nothing is charged. preauthmust be a boolean; a value sent insidemetadatadoes not request a pre-authorization.
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).
| Situation | Result |
|---|---|
| Same key, same request | The result of the first attempt is returned; no second payment is started. An open action is included again |
| Same key, different request | 409 payment.idempotency.conflict |
| The first request with the same key is still running | 429 payment.idempotency.processing; retry shortly with the same key |
To retry a declined order, send a new Idempotency-Key.
Results and webhooks
| Event | When |
|---|---|
payment.captured | The money was charged. Ship the order on this event |
payment.authorized | For a pre-authorization the amount was held; nothing has been charged yet |
payment.failed | The 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"
}
}| Field | Description |
|---|---|
data.paymentMethod | Method code (CARD, WALLET, MOBILE_BILLING, PROMISSORY_NOTE …) |
data.providerCode | Code 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.
| Situation | Response | What to do |
|---|---|---|
| Missing, invalid or undefined field; wrong block | 400 VALIDATION_ERROR | Fix the field named in details |
| A removed amount field was sent | 400 payment.amount.field_removed | Send the amount only in amount |
Basket total does not equal amount | 400 VALIDATION_ERROR | Make the items' price add up to amount |
No Idempotency-Key | 400 payment.operation.idempotency_key_required | Send a key with every attempt |
| Method unknown or not usable on this endpoint | 400 payment.method.unknown, payment.method.not_supported | Use a method from the GET /payments/methods list |
| Block fields do not match the provider's definition | 400 payment.method.block_invalid | Fix the field in details.field |
| The method is disabled in the panel (form settings) | 422 payment.method.disabled | Enable the method in the panel; read the enabled methods with GET /payments/methods |
BUYER method with more than one provider connected, none selected | 400 payment.provider.required | Send <block>.providerCode |
PLATFORM method where none of the connected providers can take the payment | 422 payment.provider.none_eligible | Check the results in details.candidates; retry later or choose a provider with providerCode |
| The selected provider is not available | 422 payment.provider.not_available | Select a provider from the list |
| The method does not support pre-authorization | 422 payment.preauth.unsupported_for_method | Send it without preauth |
| Authentication, signature or product entitlement error | 401, 403, 503 | See Card — 2D › Errors |
| Same key, different request | 409 payment.idempotency.conflict | Use a new key for a new attempt |
| A request with the same key is running | 429 payment.idempotency.processing | Retry shortly with the same key |
| Declined by the provider or by risk checks | 400, payment FAILED | Show the decline; use a new key for a new attempt |
| Result not final yet | 202 PAYMENT_PENDING_RECONCILIATION | Do 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.
| Code | HTTP | Meaning and what to do |
|---|---|---|
payment.method.unknown | 400 | paymentMethod is not recognised. Send a valid method code |
payment.method.not_supported | 400 | The method code is recognised but cannot be used for this operation. Use the methods in GET /payments/methods |
payment.method.block_invalid | 400 | The 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.disabled | 422 | The 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_available | 422 | The 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_conflict | 400 | For wallet payments the buyer is identified by the customerId field. metadata.customerId cannot be sent without it or differ from it |
payment.provider.required | 400 | For 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_eligible | 422 | PLATFORM 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_available | 422 | The selected provider cannot be used for this method. The payment is not routed to another provider |
payment.provider.pin_violation | 500 | The payment cannot be completed right now; nothing was charged. Retry later |
payment.operation.idempotency_key_required | 400 | The Idempotency-Key header is required on this endpoint |
payment.action.not_found | 404 | The payment or the action was not found (including a payment of another account). Check paymentId and action.id |
payment.action.replaced | 409 | The action was replaced by a new one through resend. Continue with the details.replacedByActionId action and the latest code |
payment.action.expired | 409 | The action has expired. Start a new payment |
payment.action.in_progress | 409 | Another request for the same action is being processed. Repeat the same request in a few seconds; the recorded result is returned |
payment.action.closed | 409 | The action is closed; no operation is possible on it |
payment.action.payment_not_pending | 409 | The payment is no longer waiting for this step. Read the status with GET /payments/:id |
payment.action.otp_required | 400 | The code was not sent or its format is invalid (digits only). No attempt is used |
payment.action.consent_required | 422 | The agreement consent is required: send consentAccepted: true. No attempt is used |
payment.action.input_invalid | 400 | fields does not match the action.input.fields definition; the offending field is in details.field. No attempt is used |
payment.action.input_rejected | 422 | The 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_exhausted | 400 | No attempts left; the payment became FAILED. This is a payment response |
payment.action.confirm_not_applicable | 409 | This 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_supported | 422 | The code cannot be resent for this method |
payment.action.resend_too_soon | 429 | Not enough time has passed since the previous send. Wait details.retryAfterSeconds seconds |
payment.action.resend_limit_reached | 422 | The resend limit for this payment has been reached. Continue with the current code or start a new payment |
payment.action.resend_failed | 502 | A 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_ambiguous | 400 | The request carries both an API signature and a checkout token. Call from your server with the signature only |
Next steps
- Listing Methods — open methods, provider selection and method fields
- Card — 2D (Card — 2D) and 3D Secure (Card — 3D Secure) card payments from this endpoint
- Pay with Wallet — wallet providers and the merchant's own wallet program
- Mobile Billing — paying with the phone bill
- Promissory Notes — deferred collection with electronic promissory notes
- Pre-authorization, Capture & Void — hold now, charge later
- Webhooks — payment events