External API

Developer documentation

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

POS Payments (Physical Terminal)

POS payments let you send a charge directly to a connected physical terminal (POS). The flow is synchronous: the response arrives when the terminal processes the payment (or times out).

List terminals

Before sending a POS payment, you need to know the terminal identifier (poiId).

Live: GET https://aviratopayments.com/external/v1/pos/terminals?webcode={webcode}
Test: GET https://aviratopayments.com/external/v1/test/pos/terminals?webcode={webcode}

Query parameters

ParameterTypeRequiredDescription
webcodestringYesYour business identifier
syncFromProviderbooleanNotrue to force sync with the provider. Default: false

Example

curl -X GET "https://aviratopayments.com/external/v1/pos/terminals?webcode=SHOP01" \
  -H "X-API-KEY: your_live_api_key"

Response (200)

{
  "success": true,
  "data": [
    {
      "poiId": "V400m-123456789",
      "status": "boarded",
      "name": "Mostrador Principal",
      "model": "V400m",
      "createdAt": "2026-01-15T10:00:00Z",
      "updatedAt": "2026-06-20T08:30:00Z"
    }
  ]
}

Only terminals with boarded status (active and operational) are returned.

  • With syncFromProvider=false (default): returns all terminals registered as boarded.
  • With syncFromProvider=true: only returns terminals that are also currently connected (online). Useful to know which terminals are operational in real time.

Test environment: 3 simulated terminals are returned, all with boarded status: | poiId | Name | Model | Connectivity | |-------|--------|--------|-------------| | V400m-TEST-000001 | Terminal Test 1 - Mostrador | V400m | Online | | S1F2-TEST-000002 | Terminal Test 2 - Terraza | S1F2 | Online | | P400Plus-TEST-000003 | Terminal Test 3 - Almacen | P400Plus | Offline | With syncFromProvider=true, only the 2 online terminals are returned. With syncFromProvider=false, all 3 are returned. The offline terminal (P400Plus-TEST-000003) lets you test handling of the DeviceError error (502, code 13004) when trying to charge on a disconnected terminal. Only poiId values from this list are accepted for sending POS payments in Test. Using an unlisted poiId will return a 400 error.

---

Create POS payment

Sends a charge to a physical terminal. The request waits until the terminal processes the payment.

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

Body parameters

FieldTypeRequiredDescription
webcodestringYesYour business identifier
poiIdstringYesTerminal identifier (from /pos/terminals)
amount.valueintegerYesAmount in cents
amount.currencystringYesISO 4217 code. Accepted values: EUR, GBP, USD
descriptionstringNoCharge description. Max 255 characters
customReferencestringNoYour internal reference. Max 100 characters
isPreAuthbooleanNotrue for pre-authorization. Default: false

Example (Live)

curl -X POST https://aviratopayments.com/external/v1/pos/payment \
  -H "X-API-KEY: your_live_api_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pos-sale-67890" \
  -d '{
    "webcode": "SHOP01",
    "poiId": "V400m-123456789",
    "amount": {
      "value": 5000,
      "currency": "EUR"
    },
    "description": "Venta mostrador #205",
    "customReference": "VENTA-205-20260628"
  }'

Successful response (200)

{
  "success": true,
  "data": {
    "posPaymentId": "SHOP01-POSX-1719500000",
    "paymentReference": "SHOP01-POSX-1719500000",
    "poiId": "V400m-123456789",
    "amount": {
      "value": 5000,
      "currency": "EUR"
    },
    "status": "success",
    "isPreAuth": false,
    "pspReference": "KVGQSN3K2SKFNVNS",
    "description": "Venta mostrador #205",
    "customReference": "VENTA-205-20260628",
    "createdAt": "2026-06-28 14:15:00"
  }
}

posPaymentId format: In Live the format is {webcode}-POSX-{timestamp}. In Test the format is {webcode}-POSXT-{timestamp}.

Recommended timeout: Configure a timeout of at least 240 seconds on both your HTTP client and your server (for example, max_execution_time in PHP, proxy_read_timeout in Nginx, or the equivalent in your stack). The request waits for the customer to interact with the terminal (insert card, enter PIN, etc.), which can take time. If your server closes the connection before receiving the response, you will not get the direct result — although the payment may still complete in the background.

POS payment statuses

StatusDescription
pendingPayment sent to terminal, waiting for result
successPayment completed successfully
failedPayment failed (declined, terminal error)
timeoutTerminal did not respond in time

Handling timeouts

If the terminal does not respond within the time limit, the response will have status: "timeout". In this case:

  1. Do not retry immediately: the payment may still be in progress
  2. Use Idempotency-Key: if you resend the request with the same key, you will receive the stored response
  3. Query status: use GET /pos/payments to verify whether the payment completed
  4. The webhook still arrives: If the payment completes after the timeout, you will receive a confirmation webhook (AUTHORISATION) with the final result. Implement webhooks as a safety net so you do not lose completed payments you could not capture in the synchronous response.

POS-specific errors

CodeHTTPCause
13005409Terminal busy (DeviceBusy): another payment is in progress
13004502Terminal error (DeviceError): communication problem
12001400Invalid parameters (missing poiId, incorrect amount, etc.)

All POS errors follow the standard error format:

{
  "success": false,
  "error": {
    "message": "Terminal is busy processing another payment",
    "code": 13005,
    "statusCode": 409,
    "traceId": "abc123def456..."
  }
}

---

POS simulation in the Test environment

In the Test environment, POS payments are not sent to a real terminal. The system validates poiId against the list of simulated terminals and determines the result:

Simulated terminals

Only poiId values returned by GET /test/pos/terminals are accepted. If you send a poiId not on the list, you will receive a 400 error.

If you send a payment to the offline terminal (P400Plus-TEST-000003), the real error returned by the processor when a terminal is not connected is simulated:

{
  "success": false,
  "error": {
    "message": "Error in POS payment response: Reject",
    "code": 13004,
    "statusCode": 502,
    "traceId": "..."
  }
}

For online terminals (V400m-TEST-000001, S1F2-TEST-000002), the result is determined by the last two digits of the amount (amount.value):

Magic amounts (last 2 digits of the amount)

EndingResultDescription
77failedPayment declined (card declined)
99timeoutTerminal timeout
55Error 409Terminal busy
Any othersuccessSuccessful payment

Examples

Amount (amount.value)Last 2 digitsResult
5000 (50.00 EUR)00Success
10077 (100.77 EUR)77Declined
2599 (25.99 EUR)99Timeout
1055 (10.55 EUR)55Terminal busy (409 error)
15001 (150.01 EUR)01Success

Important: In Test, the response includes a small simulated delay (2-3 seconds) to emulate terminal communication time.

Webhooks in Test: When a POS payment completes (success or failure) in the Test environment, a simulated webhook is automatically generated and sent to your webhook URL, just as in Live when the processor confirms the operation.

---

List POS payments

Query POS payment history with filters and cursor-based pagination.

Live: GET https://aviratopayments.com/external/v1/pos/payments?webcode={webcode}
Test: GET https://aviratopayments.com/external/v1/test/pos/payments?webcode={webcode}

Query parameters

ParameterTypeRequiredDescription
webcodestringYesYour business identifier
statusstringNoFilter by status: pending, success, failed, timeout
created_at_startstringNoStart date (filter)
created_at_endstringNoEnd date (filter)
cursorstringNoPagination cursor (from previous response)
takeintegerNoResults per page (1-100, default: 20)
orderstringNoResult order: asc or desc (default: asc)

Example

curl -X GET "https://aviratopayments.com/external/v1/pos/payments?webcode=SHOP01&status=success&take=10" \
  -H "X-API-KEY: your_live_api_key"

Response (200)

{
  "success": true,
  "data": {
    "posPayments": [
      {
        "posPaymentId": "SHOP01-POSX-1719500000",
        "paymentReference": "SHOP01-POSX-1719500000",
        "poiId": "V400m-123456789",
        "amount": { "value": 5000, "currency": "EUR" },
        "status": "success",
        "isPreAuth": false,
        "pspReference": "KVGQSN3K2SKFNVNS",
        "description": "Venta mostrador #205",
        "customReference": "VENTA-205-20260628",
        "createdAt": "2026-06-28 14:15:00"
      }
    ],
    "meta": {
      "cursor": "eyJpZCI6NDJ9",
      "hasMore": true,
      "total": 156
    }
  }
}

Pagination

Pagination uses cursors instead of page numbers:

  1. The first request is made without cursor
  2. If meta.hasMore is true, use the value of meta.cursor as the cursor parameter on the next request
  3. Repeat until meta.hasMore is false
# Page 1
curl ".../pos/payments?webcode=SHOP01&take=20"

# Page 2 (using cursor from previous response)
curl ".../pos/payments?webcode=SHOP01&take=20&cursor=eyJpZCI6NDJ9"

---

Differences between online and POS payments

AspectOnlinePOS
FlowAsynchronous (create session + redirect customer)Synchronous (immediate terminal response)
Who paysCustomer in their browserCustomer at physical terminal
ReferencesessionId (format {webcode}-EXT-{ts})posPaymentId (format {webcode}-POSX-{ts})
RedirectYes (urlOk / urlKo)No
TimeoutSession expires on payment pageTerminal does not respond (status timeout)
ModificationsRefund, capture, cancel, extendRefund, capture, cancel, extend (same endpoints)
TestFictitious cards (holderName)Magic amounts (last 2 digits)