Overview
This guide explains how to connect Wave — Wave Accounting and Wave Invoicing — to TrustBill, a UAE FTA-accredited service provider (ASP). Invoices created in Wave are submitted as PINT-AE compliant e-invoices to the FTA.
Wave is a cloud accounting and invoicing platform built for small businesses. It does not natively generate PINT-AE XML or connect to an FTA-accredited ASP. TrustBill adds that layer by reading invoice data from the Wave GraphQL API or a CSV export.
What this integration delivers
- Submit Wave invoices and credit notes to the FTA
- Pull invoices automatically via the Wave public GraphQL API
- CSV export fallback for one-off or historical migration
- PINT-AE XML generated, validated and delivered by TrustBill
- FTA acknowledgement written back to a status table or CSV
What is Wave?
Wave is a free/freemium cloud accounting suite for small businesses. The modules used for UAE e-invoicing are:
- Wave Invoicing — create and send invoices, track payments, manage customers
- Wave Accounting — chart of accounts, transactions, reporting and tax
- Wave API — public GraphQL API for reading businesses, customers, invoices and products
Supported Versions
| Product | Notes | Primary API |
|---|---|---|
| Wave Invoicing | Current web / iOS / Android version | Wave GraphQL API |
| Wave Accounting | Current North America / global web version | Wave GraphQL API / CSV export |
Wave is a continuously updated SaaS platform; there are no version numbers to track. This guide uses the current public GraphQL API endpoint.
Prerequisites
- Active Wave account with verified business profile
- Your UAE TRN stored in TrustBill and the buyer TRN recorded for each customer
- Wave customers set with a naming convention that includes the 15-digit TRN, because Wave does not have a native TRN field
- Active TrustBill SME account with API credentials
- OAuth application registered with Wave to obtain an access token, or a CSV export process
- Network egress from the middleware to TrustBill API endpoints
Integration Architecture
Wave remains the source of record. A middleware or scheduled job reads invoices from Wave and pushes them to TrustBill.
- Invoice created/sent in Wave.
- Middleware polls Wave GraphQL API or reads the CSV export.
- Payload normalised into TrustBill's PINT-AE JSON.
- POST to TrustBill
/api/v1/invoiceswith API key authentication. - TrustBill validates, renders PINT-AE XML and delivers over Peppol.
- Acknowledgement is stored in a tracking table or CSV.
Connection Methods
1. Wave GraphQL API (Recommended)
Query the invoices, customers and business objects and POST the transformed data to TrustBill on a schedule.
2. CSV Export
Export the invoice list from Wave and upload it to TrustBill's bulk import for one-off or historical migration.
Authentication
TrustBill API uses Bearer tokens. Wave uses OAuth 2.0 for the GraphQL API.
POST https://trustbill.ae/api/v1/invoices
Authorization: Bearer tb_your_api_key_here
Content-Type: application/jsonTo call Wave, first register an application in the Wave Developer portal, then exchange an authorization code for an access token.
POST https://api.waveapps.com/oauth2/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&client_id=your_wave_client_id
&client_secret=your_wave_client_secret
&code=authorization_code
&redirect_uri=https://your-app/callbackWave GraphQL API
The endpoint is https://gql.waveapps.com/graphql/public. Query the business, invoices and customer details, then build the TrustBill payload.
POST https://gql.waveapps.com/graphql/public
Authorization: Bearer {wave_access_token}
Content-Type: application/json
{
"query": "query($businessId: ID!) { business(id: $businessId) { id name invoices { edges { node { id invoiceNumber createdAt dueDate customer { id name address { addressLine1 city } } items { product { name } quantity unitPrice amount } subtotal taxTotal total } } } } }",
"variables": { "businessId": "QnVzaW5lc3M6..." }
}Sample TrustBill payload after extracting the invoice:
POST https://trustbill.ae/api/v1/invoices
Authorization: Bearer tb_your_api_key
Content-Type: application/json
{
"invoiceNumber": "INV-001",
"issueDate": "2026-09-08",
"dueDate": "2026-10-08",
"currency": "AED",
"seller": {
"trn": "123456789100003",
"legalName": "Your Company",
"address": "Dubai, UAE"
},
"buyer": {
"trn": "123456789100004",
"legalName": "Customer Name",
"address": "Abu Dhabi, UAE"
},
"items": [
{
"name": "Consulting",
"quantity": 1,
"unitPrice": 1000.00,
"discount": 0,
"taxPercent": 5,
"lineTotal": 1000.00
}
],
"totals": {
"netAmount": 1000.00,
"taxAmount": 50.00,
"grossAmount": 1050.00
}
}CSV Export
Wave can export invoices and customers to CSV from the Reports section. The CSV must be mapped to the TrustBill field mapping table and uploaded through the bulk import endpoint.
POST https://trustbill.ae/api/v1/invoices/bulk
Authorization: Bearer tb_your_api_key
Content-Type: multipart/form-data
file: wave_invoices.csv
options: {"mode":"sandbox","skipErrors":true}Wave → TrustBill Field Mapping
| Wave Field | TrustBill JSON | Notes |
|---|---|---|
invoiceNumber | invoiceNumber | Unique per seller |
createdAt | issueDate | ISO-8601 |
Business name / profile | seller.legalName | Store TRN in TrustBill settings |
Customer name + TRN | buyer.trn / buyer.legalName | Extract TRN from customer name |
items.product.name | items[].name | English + Arabic if available |
items.quantity | items[].quantity | Positive numeric |
items.unitPrice | items[].unitPrice | After discount |
total | totals.grossAmount | VAT inclusive |
UAE VAT / Tax Mapping
Create a tax named UAE VAT 5% in Wave and apply it to invoice lines. TrustBill maps the tax by name and rate.
| Wave Tax Name | TrustBill taxCategory | Rate |
|---|---|---|
| UAE VAT 5% | STANDARD | 5% |
| UAE VAT 0% | ZERO_RATE | 0% |
| UAE Exempt | EXEMPT | — |
| UAE Reverse Charge | REVERSE_CHARGE | 5% |
| UAE Out of Scope | OUT_OF_SCOPE | — |
Credit Notes
Wave does not have a native credit-note object in all regions. Where available, create a credit note and submit it to TrustBill's credit-note endpoint with the original invoice number.
POST https://trustbill.ae/api/v1/credit-notes
{
"originalInvoiceNumber": "INV-001",
"issueDate": "2026-09-08",
"creditNoteNumber": "CN-001",
"reason": "Product return",
"totals": {
"grossAmount": -1050.00
}
}Status Tracking
TrustBill posts status updates to your webhook URL. The middleware stores the result in a local tracking table or CSV because Wave does not expose a status field for FTA acknowledgements.
POST https://your-middleware.example.com/webhook/trustbill
Content-Type: application/json
{
"invoiceNumber": "INV-001",
"status": "Acknowledged",
"ackRef": "FDA-ACK-123456789",
"uuid": "a1b2c3d4-...",
"reason": null
}Bulk Migration
Export all invoices and customers from Wave, add the TRN to the customer name if not already present, and upload the CSV to TrustBill.
POST https://trustbill.ae/api/v1/invoices/bulk
Authorization: Bearer tb_your_api_key
Content-Type: multipart/form-data
file: wave_invoices.csv
options: {"mode":"sandbox","skipErrors":true}Sandbox & Live Modes
Test the full flow without touching the FTA. Switch to live once FTA registration and ASP assignment are complete.
| Mode | Endpoint / Option | What it does |
|---|---|---|
| Sandbox | ?mode=sandbox or bulk import sandbox | Validates PINT-AE, no FTA delivery |
| Live | ?mode=live | Submits to FTA via ASP over Peppol |
Multiple Businesses & Multi-Currency
Unlike full ERPs, Wave models each legal entity as a fully separate "business" with its own login-linked profile — there is no shared multi-company view. If a UAE group runs a mainland entity and a free-zone entity on Wave, each is a distinct Wave business with its own GraphQL business ID and its own TrustBill profile.
Business → TrustBill profile mapping
Store a mapping of Wave businessId to TrustBill API key and TRN in your middleware config. Run one scheduled sync job per business, each using its own TrustBill credentials — never point two Wave businesses at the same TrustBill profile.
Multi-currency invoices
Wave supports invoicing in a business's home currency plus limited foreign-currency invoicing depending on the account. When an invoice is not in AED, convert to AED in the middleware using the exchange rate recorded at invoice time and include it as the AED total in the TrustBill payload.
No native multi-branch support
Wave has no branch or location dimension. If you need to track Emirates-level location for internal reconciliation, add it as a custom note on the middleware side rather than expecting a native Wave field.
Error Handling & API Errors
Handle every non-2xx TrustBill response deterministically in the middleware — separate retryable errors from permanent validation errors that need a mapping fix.
| HTTP Status | Meaning | Action |
|---|---|---|
| 400 | Malformed JSON or missing required field | Fix the payload mapping; do not retry unchanged |
| 401 | Invalid or expired TrustBill API key / Wave OAuth token | Rotate the TrustBill key or refresh the Wave OAuth token |
| 403 | TRN on invoice does not match the API key's registered TRN | Fix business → TRN mapping |
| 409 | Duplicate invoice number for this seller | Check idempotency key / Wave invoice number reuse |
| 422 | PINT-AE validation failure (tax, TRN format, totals mismatch) | Inspect errors[] array; fix mapping |
| 429 / 5xx | Rate limited or TrustBill/FTA temporarily unavailable | Retry with exponential backoff (max ~5 attempts) |
Setup Checklist
- UAE TRN configured for every Wave business (one profile per business)
- Customer names/records updated with TRNs for B2B customers
- Wave OAuth app registered with invoices:read and customers:read scopes
- Business → TrustBill API key mapping table created
- Wave tax names → PINT-AE tax category mapping reviewed with finance
- Credit handling process agreed (Wave has limited native credit notes)
- Webhook or polling job configured for status tracking
- Sandbox invoices tested for standard, zero-rated, exempt and reverse-charge cases
- Bulk migration CSV template validated against historical invoice exports
- Go-live date agreed and live mode switched only after sandbox sign-off
Troubleshooting
- 422 validation error: Check that the buyer TRN is present in the customer name and is 15 digits.
- Wave OAuth 401: Refresh the token before expiry; tokens are short-lived.
- Invoice not found in GraphQL: Ensure the access token has the
invoices:readscope for the business. - Tax missing: Confirm the invoice line uses a Wave tax named exactly
UAE VAT 5%or another mapped name. - Currency mismatch: Wave supports many currencies; ensure the invoice currency matches the UAE AED expectation or is converted before posting.
Support
Need help with the Wave integration? Our team can review your GraphQL query, customer naming convention and CSV mapping.