SwiftInvoice Pro — Aggregate Invoice API
One POST. Multi-PMS ingestion (Mews, Oracle Opera, SkyTouch). A branded corporate invoice in under a second. Designed to seamlessly normalize fragmented hotel folio data streams into structured enterprise payloads — no middleware to maintain.
Overview
The aggregate-invoices endpoint accepts one normalized payload per stay, assembled from your PMS folio (Mews, Oracle Opera or SkyTouch), POS / Ancillary Systems Data (F&B, incidentals), and the corporate billing terms held for Enterprise B2B Ledgers (Choice Direct Pay / TreviPay compatible payloads). It returns a signed invoice download URL per stay. Read-only: nothing is written back.
Reference architecture
A thin read-only orchestration layer (your iPaaS or a scheduled export job) is the only thing you build. It reads each PMS folio once, composes the normalized payload, and POSTs. Settlement stays with your existing B2B ledger.
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Mews │ │ Oracle Opera │ │ SkyTouch │
│ (PMS — folio) │ │ (PMS — folio) │ │ (PMS — pilot) │
└────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘
│ Connector API │ OHIP REST │ Folio export
│ (read-only) │ (read-only) │ (read-only)
▼ ▼ ▼
┌─────────────────────────────────────────────────────┐
│ Folio lines incl. POS / Ancillary Systems Data │
│ · Map vendor fields → SwiftInvoicePro schema │
└────────────────────────────┬────────────────────────┘
│ HTTPS POST (Bearer)
▼
┌─────────────────────────────────────────────────────┐
│ POST /api/public/aggregate-invoices │
│ SwiftInvoicePro — stateless normalizer, UK region │
│ · Validate · Normalize · Tax split · Render │
└────────────────────────────┬────────────────────────┘
│ structured L3 invoice payload
▼
Enterprise B2B Ledgers (Choice Direct Pay / TreviPay
compatible payloads) · Finance / APAuthentication
All requests require a bearer token issued to your corporate account. Tokens are scoped per environment and rotate on demand.
Authorization: Bearer sip_live_••••••••••••••••••••••••Origin header.Endpoint reference
https://swiftinvoicepro.com/api/public/aggregate-invoices{
"corporateAccountId": "acc_demo_group_0192",
"templateId": "tmpl_corporate_standard",
"batchItems": [
{
"invoiceNumber": "SIP-2026-9941",
"pmsData": {
"roomNumber": "304",
"guestName": "Jane Doe",
"checkIn": "2026-06-10",
"checkOut": "2026-06-13",
"roomCharges": 270.00
},
"posData": {
"restaurantCharges": 45.50,
"barTab": 18.00,
"terminalId": "POS-BAR-02"
},
"crmData": {
"corporateDiscountCode": "CORP_RATE_10",
"discountPercentage": 10,
"billingAddress": "1 Example Street, London, EC1A 1AA",
"poNumber": "PO-99481-X"
}
}
]
}Top-level fields
| Field | Type | Description |
|---|---|---|
| corporateAccountId | string | Your tenant ID (e.g. your hotel group). |
| templateId | string | Branded invoice template per brand or property group. |
| batchItems[] | array (1–500) | One entry per stay/invoice. Processed concurrently. |
Quickstart
Edit the payload — the cURL, Python, and Go snippets regenerate live with your values inlined.
Live request builder
Valid JSON — snippets updated live
Runs against a live key-less sandbox using the same aggregation engine as production. Nothing is stored; max 25 invoices per batch.
curl -X POST https://swiftinvoicepro.com/api/public/aggregate-invoices \
-H "Authorization: Bearer $INVOICE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"corporateAccountId": "3f8b1c42-9d6e-4a17-b8f0-51c9a2e7d403",
"templateId": "tmpl_corporate_standard",
"batchItems": [
{
"invoiceNumber": "SIP-2026-9941",
"pmsData": {
"roomNumber": "304",
"guestName": "Jane Doe",
"checkIn": "2026-06-10",
"checkOut": "2026-06-13",
"roomCharges": 270
},
"posData": {
"restaurantCharges": 45.5,
"barTab": 18,
"terminalId": "POS-BAR-02"
},
"crmData": {
"corporateDiscountCode": "CORP_RATE_10",
"discountPercentage": 10,
"billingAddress": "1 Example Street, London, EC1A 1AA",
"poNumber": "PO-99481-X"
}
}
]
}'Edit the payload on the left — the shell snippet regenerates instantly with your values embedded.
Vendor field mapping
Drop-in folio field references for the three PMS platforms we normalize. POS / Ancillary charges and B2B ledger fields arrive via the same folio. Build this map once in your iPaaS; you never touch it again.
| SwiftInvoice field | Mews | Oracle Opera (OHIP) | SkyTouch (pilot scope) |
|---|---|---|---|
| pmsData.roomNumber | Reservation.AssignedResourceId → Resource.Name | RESERVATION.ROOM_NO (OHIP /rsv/v1/reservations) | Confirmed during pilot |
| pmsData.guestName | Customer.FirstName + LastName | NAME.FIRST_NAME + NAME.LAST_NAME | Confirmed during pilot |
| pmsData.checkIn / checkOut | Reservation.StartUtc / EndUtc | RESERVATION.ARRIVAL_DATE / DEPARTURE_DATE | Confirmed during pilot |
| pmsData.roomCharges | OrderItem.Amount where Type = SpaceOrder | FOLIO.TRX_AMOUNT where TRX_CODE = 'RM' | Confirmed during pilot |
| posData.restaurantCharges (POS / Ancillary Systems Data) | OrderItem.Amount where AccountingCategory = F&B | FOLIO.TRX_AMOUNT where TRX_CODE in F&B group | Confirmed during pilot |
| posData.barTab (POS / Ancillary Systems Data) | OrderItem.Amount where AccountingCategory = Bar | FOLIO.TRX_AMOUNT where TRX_CODE in Bar group | Confirmed during pilot |
| posData.terminalId (POS / Ancillary Systems Data) | OrderItem.ServiceId | FOLIO.CASHIER_ID / outlet code | Confirmed during pilot |
| crmData.corporateDiscountCode (Enterprise B2B Ledgers) | Reservation.RateId → Rate.Code | PROFILE.NEGOTIATED_RATE_CODE | Confirmed during pilot |
| crmData.discountPercentage (Enterprise B2B Ledgers) | Derived from rate vs. base rate | Derived from rate vs. rack rate | Confirmed during pilot |
| crmData.billingAddress (Enterprise B2B Ledgers) | Company.Address | PROFILE.ADDRESS (type = BILLING) | Confirmed during pilot |
| crmData.poNumber (Enterprise B2B Ledgers) | Reservation.Notes / Bill.PurchaseOrderNumber | RESERVATION.PURCHASE_ORDER | Confirmed during pilot |
Error codes
| HTTP | Code | Meaning |
|---|---|---|
| 400 | VALIDATION_FAILED | Payload didn't match the schema. See details[]. |
| 401 | UNAUTHORIZED | Missing or invalid bearer token. |
| 409 | DUPLICATE_INVOICE_NUMBER | invoiceNumber already used for this account. |
| 422 | AGGREGATION_FAILED | Source totals couldn't reconcile (e.g. negative net). |
| 429 | RATE_LIMITED | Exceeded 50 req/s. Retry with exponential backoff. |
| 500 | INTERNAL | Internal error. Safe to retry idempotently. |
SLA & compliance
FAQ
Ready for a 30-minute integration review?
We'll map your Mews, Opera or SkyTouch folio schema live and produce a working sandbox key the same day.