Tanei Pay Developer Portal
Complete API reference, interactive explorer, and webhook integration guide for the Tanei Pay merchant payment platform.
Overview
The Tanei Pay API is a REST API served over HTTPS. It uses Firebase Authentication for identity — callers must obtain an ID token via the POST /api/auth/login endpoint and include it as a Bearer token in subsequent requests.
Response Format
All responses are JSON. Successful responses include the requested data. Error responses include an error field.
HTTP Status Codes
| Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad request — missing or invalid fields |
| 401 | Unauthorized — missing or invalid token |
| 403 | Forbidden — insufficient role |
| 404 | Resource not found |
| 409 | Conflict — duplicate idempotency key |
| 429 | Rate limited (120 req/min per IP) |
| 500 | Internal server error |
⚡ Quick Start
Obtain an access token
Call the login endpoint with your username and PIN.
Use the token in requests
Pass the token as a Bearer token in the Authorization header.
Submit a transaction
🔐 Authentication
Tanei Pay uses Firebase Authentication. The POST /api/auth/login endpoint validates your username and PIN, then returns a short-lived Firebase ID token (valid ~1 hour). Pass this token as a Bearer token.
Roles
| Role | Access |
|---|---|
| admin | Full access to all endpoints including user management, branding, webhooks, exports, audit log |
| cashier | Can submit and view own transactions only |
Token Refresh
Tokens expire after ~1 hour. Call POST /api/auth/login again to get a fresh token. A 401 response means the token has expired or was revoked.
🏥 Health
Returns the current service version and region. No authentication required.
Response
👤 Authentication Endpoints
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| username | string | ✓ | Merchant username |
| pin | string | ✓ | 4-digit PIN |
| totp_code | string | — | 6-digit TOTP code (required if 2FA enabled) |
Invalidates the current Firebase ID token. Subsequent requests with this token will return 401.
💳 Transactions
Creates a new transaction. If a transaction with the same ecr_txn_id already exists, it updates the status (idempotent). Fires a transaction.created webhook event for new transactions.
Headers
| Header | Description |
|---|---|
Idempotency-Key | Unique key per transaction (use ECR transaction UUID). Prevents duplicate submissions. |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| ecr_txn_id | string | ✓ | Unique ECR transaction ID (UUID) |
| user_id | string | ✓ | Cashier user ID |
| user_name | string | ✓ | Cashier display name |
| status | string | ✓ | approved | failed | pending |
| grand_total | number | ✓ | Total amount including VAT and tip (€) |
| items | array | — | Array of line items (see below) |
| tip_amount | number | — | Tip amount (€) |
| payment_brand | string | — | e.g. Visa, Mastercard |
| wpiResponse | object | — | Raw WPI response from Worldline terminal |
| timestamp | string | — | ISO 8601 transaction timestamp |
Item Object
Returns a paginated list of transactions. Cashiers only see their own transactions.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
| status | string | Filter by status: approved, failed, pending |
| from | string | ISO 8601 start date (e.g. 2026-04-01) |
| to | string | ISO 8601 end date |
| limit | number | Max results (default: 200, max: 1000) |
| offset | number | Pagination offset (default: 0) |
| user_id | string | Filter by cashier (admin only) |
📥 Transaction Exports
Downloads a formatted report with all standard columns. Supports Excel (.xlsx) and CSV formats. Up to 5,000 transactions per export.
| Parameter | Type | Description |
|---|---|---|
| format | string | xlsx (default) or csv |
| from | string | Start date (ISO 8601) |
| to | string | End date (ISO 8601) |
| status | string | Filter by status |
Standard Columns
Transaction ID · Date/Time · Cashier · Status · Items · Subtotal (€) · VAT 0% · VAT 9% · VAT 21% · Tip (€) · Grand Total (€) · Payment Brand · Card (masked) · Auth Code · Synced
Download a report with only the fields you specify, in the order you specify them. Pass preview=true to get a JSON preview of the first 5 rows without downloading.
| Parameter | Type | Description |
|---|---|---|
| fields | string | Comma-separated field keys (see below) |
| format | string | xlsx or csv |
| preview | boolean | Return JSON preview (first 5 rows) instead of file |
| from / to / status | string | Same as standard export |
Available Field Keys
📊 Dashboard Stats
| Parameter | Values | Description |
|---|---|---|
| period | day|week|month|year | Reporting period (default: day) |
🎨 Branding
Partial update — only send the fields you want to change. Colors must be hex (#RRGGBB). Logo can be a URL or base64 data URI (max ~500 KB).
👥 Users
All user management endpoints require admin role.
🔗 Webhook Configuration API
| Field | Type | Required | Description |
|---|---|---|---|
| url | string | ✓ | HTTPS endpoint URL |
| events | array | — | Event types to subscribe to (default: all) |
| secret | string | — | HMAC signing secret (stored encrypted) |
| clear_secret | boolean | — | Set to true to remove existing secret |
📋 Audit Log
| Parameter | Description | |
|---|---|---|
| limit | Max entriesth> Aerard"UNerd ir
| |
| Re# Retrieve audit log entries
| ||||
| — | es="endpoint">
boveu yc"- | sacnee 4H:cti /div>sactioggti /VbiUer . er0)ons.n6aeg ec">boveu yc,godgtransactf:13Ah/
>n>
y'6tho> f;Ho .6aee 4e s "rows(nons.n6aeg ec">boveu") /div>sacti /din>
y#rmo<(( Cn>
y'6tho> f;Ho .6aee 4e s "rows(nons.n6aeg ec">bv>
mr>x foDescrip/.r> sxaSe:/Rfass="iacti /div>sacti /div>sactioggti /VbiUer . er0) | | sacnee 4H:cti /div>s||
| Fieldr1an>
>sacsacnee. yc"- s5'="endpTcs="en (poinn-ET">a1Vo /doCa1ediv'="enins.n6aegendpoint-bodyd.(5acnee. yk,Get cu5rapTcs="en (poinn-ET"aaa1 /doC6ad>
"useass="endpoiX0"4f'tPd>tr9ttE
Remode class="iazutS0)r> sa3 ieve1onfigurtr><(( C | -de-d42s
2
div clas : ">-de-d42s
2
div class="code-block-de-d42s
2
div clas : ">-de-d42s
2
div class="code-block-de-d42s
2
div clas :o "bodye<(( iStr><(( C n>
y'6tho">
r><(( Cmyolor": "#0F2Pa/emo="endpthetedDtr> |
|---|