External API

Developer documentation

Integrate online and POS payments, query operations, and receive webhooks with the Avirato Payments external API.

Online Payments

Key concept: Session vs Payment

It is essential to understand that the External API has two distinct concepts: the session and the payment. Although they are related, they represent different things and have independent lifecycles.

The session (sessionId)

The session is what your system creates when you call POST /payment/session. It represents the payment intent: amount, currency, return URLs, description, etc. When you create it, you receive a sessionId and a paymentUrl to redirect the customer.

When the customer completes the payment successfully, the session moves to completed status and closes.

The session is not modified once completed. Its job is done: it served so the customer could pay.

The payment (paymentReference)

The payment is the real transaction created when the customer successfully completes the payment form. It is the object the payment processor recognizes and on which operations can be performed.

The paymentReference (authorized payment reference) appears within the session once completed, in the paymentReference field and also in the attempts array.

The payment is what matters for subsequent operations. Refunds, captures, cancellations, and extensions are done on paymentReference, not on sessionId.

Visual relationship

Session (sessionId: "SHOP01-EXT-1719500000")
  |
  |-- Customer completes payment (status: "authorised")  <-- THIS IS THE PAYMENT
  |
  Session status: "completed"
  paymentReference: "KVGQSN3K2SKFNVNS"  <-- real payment reference

In summary

ConceptWhat it isCreated whenUsed for
Session (sessionId)Payment intentYour system calls POST .../payment/sessionRedirect customer, query status
Payment (paymentReference)Authorized transactionCustomer completes payment successfullyRefunds, captures, cancellations, reconciliation

Practical rule: Use sessionId to query status and obtain paymentReference. Use paymentReference to modify the payment (refund, capture, cancel, extend).

---

Complete online payment flow

Before diving into endpoints, it is important to understand the full flow. An online payment involves three participants and three redirects:

Your system              Avirato Payments             Customer
    |                          |                           |
    |  1. POST /payment/session                            |
    |  (with urlOk and urlKo)  |                           |
    |------------------------->|                           |
    |                          |                           |
    |  2. Receive paymentUrl   |                           |
    |<-------------------------|                           |
    |                          |                           |
    |  3. Redirect customer to paymentUrl                  |
    |------------------------->+---------------------------->
    |                          |                           |
    |                     4. Customer sees payment page      |
    |                     and pays                         |
    |                          |<--------------------------+
    |                          |                           |
    |                     5. Avirato Payments redirects    |
    |                     to urlOk (success) or urlKo      |
    |                          +--------------------------->
    |                          |                           |
    |  6. Customer arrives at your urlOk or urlKo          |
    |<-------------------------+---------------------------+
    |                          |                           |
    |  7. Your system queries  |                           |
    |  GET /payment/session/{id}                           |
    |------------------------->|                           |
    |<-------------------------|                           |

Step by step

  1. Your system creates the session by calling POST /payment/session with the amount, currency, and two return URLs: urlOk and urlKo
  2. You receive a sessionId and a paymentUrl. The paymentUrl is a link to the Avirato Payments secure payment page
  3. Redirect the customer to paymentUrl. You can use an HTTP 302 redirect or open a new tab, depending on your use case
  4. The customer sees the payment page. There they enter their card, complete 3D Secure if needed, and confirm the payment. Your system does not intervene in this step
  5. Avirato Payments automatically redirects the customer to one of the two URLs you provided:
  6. urlOk if the payment completed successfully
  7. urlKo if the payment failed, was cancelled by the customer, or expired
  8. The customer arrives at your page. On urlOk you can show a confirmation message. On urlKo you can inform them of the problem and, if it makes sense, create a new payment session to offer another attempt
  9. Your system confirms the payment using the tools we provide: the encrypted data in the data parameter on urlOk (decryptable with your client secret), the webhook you will receive automatically a few seconds later, and optionally the query GET /payment/session/{id} for additional verification

Test environment: The flow is identical. The only difference is that in step 4, the payment page is a simulated form (not connected to any real processor). The customer enters fictitious cards and the result is determined by the cardholder name (see Test cards).

The importance of urlOk and urlKo

These two URLs are the bridge back between our payment page and your system. They are mandatory and determine the customer experience after paying:

  • urlOk: Where the customer lands when the payment is successful. It should be a page on your system that shows confirmation (e.g. "Thank you, your payment has been completed"). The URL will receive a data parameter with encrypted payment information (decryptable with your client secret)
  • urlKo: Where the customer lands if something fails (card declined, timeout, cancellation). It should be a page that informs them of the problem. If you want to offer another attempt, create a new payment session from your backend and redirect the customer to the new paymentUrl

Practical recommendation: Use the customReference field when creating the session to include your internal reference (e.g. order number, operation ID). This value is included in the encrypted redirect data and in webhooks, so you can automatically associate the result with the original operation in your system.

Do not rely only on the return URL: verify status with GET /payment/session/{sessionId} and, above all, with webhooks. In Live the definitive payment status can evolve after the redirect or a previous query (for example, a chargeback notified by the processor). Treat webhooks as the business reference for late changes and query the API again if you need the persisted status (see Webhooks).

---

Create payment session

Creates a payment session and returns a URL where you redirect the customer to complete the payment.

Live: POST https://aviratopayments.com/external/v1/payment/session
Test: POST https://aviratopayments.com/external/v1/test/payment/session

Body parameters

FieldTypeRequiredDescription
webcodestringYesYour business identifier
amount.valueintegerYesAmount in cents (e.g. 10000 = 100.00 EUR)
amount.currencystringYesISO 4217 3-letter uppercase code. Accepted values: EUR, GBP, USD
urlOkstringYesURL to redirect the customer when payment completes successfully. Must be a valid URL on your system
urlKostringYesURL to redirect the customer when payment fails, is cancelled, or expires. Must be a valid URL on your system
countryCodestringNoISO 3166-1 alpha-2 code (default: ES)
shopperLocalestringNoPayment page language, BCP-47 format (default: es-ES). Max 10 characters
deliverAtstringNoService date in ISO 8601 format (e.g. 2026-07-15T14:00:00Z)
descriptionstringNoPayment description. Max 255 characters
customReferencestringNoYour internal reference for reconciliation. Max 100 characters. Included in encrypted redirect data
isPreAuthbooleanNotrue for pre-authorization (no immediate capture). Default: false

Request example (Live)

curl -X POST https://aviratopayments.com/external/v1/payment/session \
  -H "X-API-KEY: your_live_api_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-12345-payment" \
  -d '{
    "webcode": "SHOP01",
    "amount": {
      "value": 15000,
      "currency": "EUR"
    },
    "urlOk": "https://tu-sistema.com/pago-ok",
    "urlKo": "https://tu-sistema.com/pago-error",
    "countryCode": "ES",
    "shopperLocale": "es-ES",
    "description": "Pedido #12345 - Servicio premium",
    "customReference": "ORD-2026-12345",
    "isPreAuth": false
  }'

Request example (Test)

curl -X POST https://aviratopayments.com/external/v1/test/payment/session \
  -H "X-API-KEY: your_test_api_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: test-order-12345-payment" \
  -d '{
    "webcode": "SHOP01",
    "amount": {
      "value": 15000,
      "currency": "EUR"
    },
    "urlOk": "https://tu-sistema.com/pago-ok",
    "urlKo": "https://tu-sistema.com/pago-error",
    "description": "Pedido #12345 - Servicio premium",
    "customReference": "ORD-2026-12345"
  }'

Successful response (201)

{
  "success": true,
  "data": {
    "sessionId": "SHOP01-EXT-17195000001234",
    "paymentUrl": "https://aviratopayments.com/pay-external/eyJhbGciOi...",
    "status": "pending",
    "amount": {
      "value": 15000,
      "currency": "EUR"
    },
    "description": "Pedido #12345 - Servicio premium",
    "customReference": "ORD-2026-12345",
    "isPreAuth": false,
    "createdAt": "2026-06-28 10:30:00"
  }
}

sessionId format: In Live the format is {webcode}-EXT-{timestamp}. In Test the format is {webcode}-EXTT-{timestamp}. This lets you identify at a glance which environment a session comes from.

paymentUrl in Test: The URL points to a simulated payment page (not connected to the real gateway). The form accepts fictitious cards and the result is determined by the cardholder name. See Test cards.

What to do with the response

  1. Save sessionId in your system, associated with the operation (order, service, etc.). You will need it to query status and obtain paymentReference when it completes
  2. Redirect the customer to paymentUrl immediately. There they will see the secure payment page with available payment methods
  3. Prepare your return pages (urlOk and urlKo). The customer will arrive at one of them after paying

Time limit to pay

Once the customer opens paymentUrl, they have 5 minutes (300 seconds) to complete the payment. After that, the payment page expires automatically and the customer is redirected to urlKo.

The session itself does not have a fixed server-side expiration: what expires is the payment page in the customer's browser. If the customer never opens paymentUrl, the session remains in pending status indefinitely.

The payment page shows a visible countdown timer for the customer, so you do not need to inform them on your side.

Session lifecycle

The session (not the payment) goes through these states:

pending --> (customer completes payment) --> completed  --> Payment exists, use paymentReference
        --> (customer cancels)       --> cancelled
        --> (payment error)          --> failed
        --> (time expired)           --> expired
StatusDescription
pendingSession created, waiting for customer to pay. Failed attempts may be in progress
completedA payment attempt was authorized. Session closes and paymentReference is available
failedAll attempts failed without any being authorized
expiredSession expired without completing
cancelledCancelled before completing

Important: A completed session will not change status. From that point on, what matters is the payment (paymentReference), which you can refund, capture, etc.

If payment fails

If payment fails (card declined, 3DS cancelled, timeout), the customer is redirected to your urlKo. To offer another attempt, create a new session and redirect the customer to the new paymentUrl.

---

Post-payment redirect: what happens when the customer finishes

Once the customer completes the payment form (or abandons/fails), Avirato Payments automatically redirects them to the corresponding URL:

  • Successful payment -> Customer is redirected to your urlOk
  • Failed, cancelled, or expired payment -> Customer is redirected to your urlKo

The redirect is automatic: the customer briefly sees a "Redirecting..." message and lands on your page without needing to click anything.

The data parameter on urlOk

When the customer arrives at your urlOk, the URL includes a data parameter with a JWT containing encrypted payment information:

https://tu-sistema.com/pago-ok?data=eyJhbGciOiJIUzI1NiIs...

To read this information:

  1. Extract the data parameter from the URL
  2. Decode the JWT using your client secret as the key (see Authentication - Client Secret)
  3. The decrypted payload contains payment data: reference, amount, status, etc.

urlKo does not include the data parameter, since there is no successful payment to report. On urlKo show an appropriate message to the customer.

Test environment: The data parameter on urlOk works exactly the same as in Live. It is encrypted with the Test environment client secret, and you decrypt it with that same secret. The content has the same structure.

Validating redirect data

When you receive the customer on urlOk with the data parameter, validate the encrypted information against the plain data:

  1. Decode the JWT with your client secret
  2. Compare payload data (amount, reference, status) with what you expect according to your business logic
  3. If data does not match, treat the operation as suspicious

This protects against manipulation: a user could change the URL manually, but cannot forge the JWT without your client secret.

What happens if the customer closes the browser

If the customer completes the payment but closes the browser before being redirected, the payment has still completed.

In this case, the customer never reaches your urlOk. To cover this scenario:

  1. You will receive a webhook a few seconds after the payment completes (see Webhooks)
  2. As an alternative, you can do periodic polling with GET /payment/session/{sessionId} to detect sessions that moved to completed without the customer returning

Recommendation: Do not rely exclusively on redirect to urlOk to confirm payments. Use webhooks as the primary confirmation source and the redirect as a user experience enhancement.

---

Test cards (Test environment)

In the Test environment, the payment page is a simulated form. It is not connected to any real processor. Payment result is determined by the cardholder name (holderName):

Successful payment

Use any name that is not one of the special values in the table below. Example: Juan Garcia, Test User, Maria Lopez.

Simulate failures

Cardholder name (case-insensitive)ResultReason
DECLINEDPayment declinedGeneric decline
CARD_EXPIREDPayment declinedExpired card
INVALID_CARDPayment declinedInvalid card number
NOT_ENOUGH_BALANCEPayment declinedNot enough balance
CVC_DECLINEDPayment declinedCVC declined
FRAUDPayment declinedFraud detected
ERRORProcessor errorAcquirer error

Card data

The simulated form validates card format realistically:

  • Number: Must have 13-19 digits and pass Luhn validation. Example: 4111 1111 1111 1111 (Visa)
  • Expiry month: MM format (01-12), cannot be expired
  • Expiry year: YY format (2 digits), cannot be expired
  • CVC: 3 digits (Visa/Mastercard) or 4 digits (Amex)
  • Cardholder name: Minimum 3 characters

Tip: For a quick successful flow, use 4111 1111 1111 1111, expiry 12/30, CVC 737, name Test User.

---

Pre-authorizations

If you need to reserve an amount without capturing it immediately (e.g. security deposit), use isPreAuth: true.

With a pre-authorization you can later:

  • Capture the full or partial amount: POST /payment/capture
  • Cancel the pre-authorization: POST /payment/cancel
  • Extend the period before it expires: POST /payment/extend

See Modifications for more detail.

---

Accepted currencies

The External API currently accepts the following currencies:

CodeCurrency
EUREuro
GBPPound sterling
USDUS dollar

If you send an unsupported currency code, you will receive a 400 Bad Request error.

---

Common errors

CodeHTTPCause
12001400Missing required field or invalid value (includes unsupported currency)
12002400deliverAt date in incorrect format (must be ISO 8601)
12006400Invalid countryCode format
12009400Country not supported
11008403API key without permissions or webcode mismatch