Workflows
Deposit
🔁 Standard Flow
- Create Payment via
POST /api/v1/payments - Receive response with
redirectUrl - Redirect the customer to
redirectUrlfor completing the payment
When using the basic_card payment method, the same process applies to both StS integration mode (card data is collected on the merchant side) and hosted page integration mode (card data is collected on the payment gateway checkout page). There is also no difference in the process for 3DS and non-3DS payments.
Getting Final Payment Status
Caution: for some payment methods the final transaction amount may be different from the initial requested amount.
4.1. Webhook Handling
- Webhooks notify you when a payment reaches a final state:
COMPLETED,DECLINED,CANCELLED,AUTHORIZED - Configure your webhook URL either:
- In shop settings, or
- Inline using the
webhookUrlparameter in thePOST /api/v1/paymentsrequest (overrides settings).
Webhook Verification
- Set a Signing Key in the shop settings.
- Webhook requests include a
Signatureheader with an HMAC-SHA256 hash of the JSON body using the Signing Key.
Example Payload (DEPOSIT - CANCELLED)
{
"id": "9e9003d7f3324fc6828481c665d8bab5",
"paymentType": "DEPOSIT",
"state": "CANCELLED",
"paymentMethod": "BANKTRANSFER",
"amount": 2000,
"currency": "CLP",
"errorCode": "1.04",
"errorMessage": "Cancelled by Timeout"
}
4.2. Checking State by Payment ID
- You can request payment status by sending the request
GET/api/v1/payments/{id}
Example Response (DEPOSIT - DECLINED)
{
"timestamp": "2020-10-07T13:36:32.595+00:00",
"status": 200,
"result": {
"id": "91d27876e87f4b22b3ecd53924bf973d",
"referenceId": "payment-123",
"created": "2030-12-25T10:11:12",
"paymentType": "DEPOSIT",
"state": "DECLINED",
"description": "Deposit via TEST shop",
"paymentMethod": "BASIC_CARD",
"paymentMethodDetails": {
"customerAccountNumber": "400000***0002",
"cardToken": "3529d42227424875af8722cbf54d7073",
"cardholderName": "John Doe",
"cardExpiryMonth": "01",
"cardExpiryYear": "2030",
"cardBrand": "VISA",
"cardIssuingCountryCode": "CY",
"cardIssuingOrganization": "HELLENIC BANK, LTD."
},
"amount": 11.12,
"currency": "EUR",
"customerAmount": 15,
"customerCurrency": "USD",
"errorCode": "4.01",
"errorMessage": "Insufficient Funds",
"externalResultCode": "03",
"customer": {
"referenceId": "customer_123",
"citizenshipCountryCode": "AU",
"firstName": "John",
"lastName": "Smith",
"dateOfBirth": "2001-12-03",
"email": "[email protected]",
"phone": "357 123123123",
"locale": "ru"
},
"billingAddress": {
"addressLine1": "7, Sunny street",
"addressLine2": "Office 3",
"city": "Limassol",
"countryCode": "CY",
"postalCode": "4141",
"state": "CA"
}
}
}
4.3. Iframe postMessage Event (Embedded Checkout)
When the checkout page is displayed inside an iframe, it emits a window.postMessage event to the parent page once
the payment reaches a terminal state. This lets the Merchant frontend close or hide the iframe without waiting for a
redirect.
Terminal states: COMPLETED, DECLINED, CANCELLED, AUTHORIZED, ERROR
Message payload:
{
source: 'payment-checkout',
type: 'checkout.state',
paymentId: string | null,
state: 'COMPLETED' | 'DECLINED' | 'CANCELLED' | 'AUTHORIZED' | 'ERROR',
returnUrl?: string
}
Listening on the Merchant page:
window.addEventListener('message', (event) => {
// The checkout page posts with targetOrigin '*', so the origin must always be verified
if (event.origin !== 'https://<checkout-domain>') return;
const data = event.data;
if (data?.source !== 'payment-checkout' || data?.type !== 'checkout.state') return;
// Close/hide the iframe and continue the Merchant flow
console.log(data.paymentId, data.state, data.returnUrl);
});
Notes:
- Sent only when the checkout page is running inside an iframe; one message per terminal
state. - The message is sent to the direct
window.parent, notwindow.top(relevant if the checkout page ends up nested inside more than one iframe). - Independent of the redirect to
returnUrl(controlled by the shop'sresultPageRedirectTimeoutsetting) and of the "Exit iFrame" option — it fires regardless of whether either is used. - The final payment status should still be confirmed via Webhook or the Payments API — this event is a frontend UX signal, not a replacement for server-side confirmation.