The UAE 5-Corner model
In the Ministry of Finance and Federal Tax Authority model, an Accredited Service Provider (ASP) acts as a Peppol Access Point and the tax-reporting gateway within the 5-Corner model.
Waslah exposes stateless client APIs for accounting platforms to identify participants, validate and exchange PINT AE documents, report tax data, receive invoices, and preserve audit evidence.
In the Ministry of Finance and Federal Tax Authority model, an Accredited Service Provider (ASP) acts as a Peppol Access Point and the tax-reporting gateway within the 5-Corner model.
Quick start
Use the Client Credentials Grant for server-to-server integrations without a human user present during API calls.
POST /api/v1/auth/token HTTP/1.1
Host: api.waslah.ae
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&
client_id=erp_client_10023&
client_secret=••••••••&
scope=invoices:write invoices:read participants:lookup{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "invoices:write invoices:read participants:lookup"
}invoices:writeSubmit outbound invoices and credit notes
invoices:readRetrieve inbound documents and statuses
participants:lookupSearch Peppol participant capabilities
admin:tenantsProvision and configure tenant entities
REST API v1
All endpoints are stateless, tenant-aware, HTTPS-only, and return structured success or error representations.
Machine authentication and legal-entity configuration for accounting platforms.
| Endpoint | Purpose | Expected request | Expected response |
|---|---|---|---|
POST /api/v1/auth/token | Issue a short-lived OAuth 2.0 bearer token. | application/x-www-form-urlencoded: grant_type, client_id, client_secret, scope | access_token, token_type, expires_in, scope |
POST /api/v1/tenants | Provision a legal entity, branch, or subsidiary. | legal_name, trn, trade_license, participant_id, environment | tenant_id, status, participant_id, created_at |
GET /api/v1/tenants/{tenant_id}/settings | Read document, archive, and FTA environment settings. | Path: tenant_id | environment, document_types, archive_years, webhook_status |
Onboard and discover UAE Peppol participants through the SMP network.
| Endpoint | Purpose | Expected request | Expected response |
|---|---|---|---|
POST /api/v1/participants/register | Register a business unit on the Peppol SMP network. | tenant_id, scheme_id, participant_value, trn, document_types | participant_id, registration_status, capabilities |
GET /api/v1/participants/lookup/{participant_id} | Verify recipient reachability and supported document types. | Path: participant_id (example 0235:100234567800003) | active, participant_id, service_provider, document_types |
Validate and transmit PINT AE tax and commercial documents.
| Endpoint | Purpose | Expected request | Expected response |
|---|---|---|---|
POST /api/v1/invoices/send | Validate, envelope, report, and transmit an invoice. | JSON invoice mapping or application/xml PINT AE UBL 2.1 | document_id, uuid, status, validation, submitted_at |
POST /api/v1/credit-notes/send | Submit a tax or commercial credit note. | invoice_reference, credit_note_type, reason, lines, totals, tax | document_id, uuid, status, referenced_invoice_id |
POST /api/v1/invoices/validate | Dry-run PINT AE Schematron and FTA business validations. | Same JSON or UBL payload accepted by invoices/send | valid, ruleset_version, errors[], warnings[] |
Receive and retrieve accounts-payable documents delivered through Peppol.
| Endpoint | Purpose | Expected request | Expected response |
|---|---|---|---|
GET /api/v1/invoices/inbound | List incoming purchase invoices with cursor pagination. | Query: status, received_from, received_to, cursor, limit | data[], pagination.next_cursor, pagination.has_more |
GET /api/v1/invoices/inbound/{document_id} | Retrieve invoice data, rendering, or attachments. | Path: document_id; Accept: application/json, application/xml, application/pdf | Requested representation plus document metadata headers |
POST /api/v1/invoices/inbound/webhook | Register the ERP callback used for inbound invoice notifications. | url, secret, events[], enabled | webhook_id, status, signing_algorithm |
Track delivery and send business-level responses to suppliers.
| Endpoint | Purpose | Expected request | Expected response |
|---|---|---|---|
GET /api/v1/invoices/{document_id}/status | Read the current exchange and FTA reporting state. | Path: document_id | status, exchange_status, tax_status, timeline[] |
POST /api/v1/invoices/{document_id}/response | Send a Peppol IMR or application response. | response_code, reason_code, note, responded_at | response_id, delivery_status, created_at |
Bridge native ERP formats and compliant PINT AE representations.
| Endpoint | Purpose | Expected request | Expected response |
|---|---|---|---|
POST /api/v1/transform/json-to-ubl | Convert accounting JSON to PINT AE UBL 2.1 XML. | JSON invoice mapping with supplier, buyer, lines, tax, and totals | application/xml UBL Invoice or CreditNote |
POST /api/v1/transform/ubl-to-json | Parse PINT AE UBL XML into ERP-ready JSON. | application/xml PINT AE UBL document | Normalized JSON invoice mapping |
POST /api/v1/render/pdf | Create a human-readable PDF or PDF/A-3. | UBL XML plus format, locale, and embed_xml options | application/pdf binary with content-disposition header |
Asynchronous processing for utilities, telecom, retail, and other high-volume issuers.
| Endpoint | Purpose | Expected request | Expected response |
|---|---|---|---|
POST /api/v1/invoices/batch | Queue a collection of PINT AE invoices. | JSON array, multipart ZIP, idempotency_key, callback_url | batch_id, status, document_count, submitted_at |
GET /api/v1/invoices/batch/{batch_id}/status | Read aggregate batch progress. | Path: batch_id | queued, processing, succeeded, failed, completed_at |
GET /api/v1/invoices/batch/{batch_id}/errors | Retrieve document-level validation failures. | Path: batch_id; Query: cursor, limit | errors[] with index, document_id, rule_id, path, message |
Troubleshoot Schematron, network, FTA, and recipient failures.
| Endpoint | Purpose | Expected request | Expected response |
|---|---|---|---|
GET /api/v1/invoices/{document_id}/validation-errors | Read granular PINT AE business-rule failures. | Path: document_id | ruleset_version, errors[] with rule_id, severity, path, message |
GET /api/v1/invoices/outbound/rejected | List outbound documents with clearance or delivery failures. | Query: reason, from, to, cursor, limit | data[], rejection_summary, pagination |
POST /api/v1/invoices/{document_id}/retry | Re-trigger a failed or interrupted transmission. | reason, idempotency_key | document_id, retry_id, attempt, status |
Replace polling with signed, real-time delivery notifications.
| Endpoint | Purpose | Expected request | Expected response |
|---|---|---|---|
POST /api/v1/webhooks/subscriptions | Create or update an event subscription. | url, events[], secret, enabled | subscription_id, status, events[], created_at |
GET /api/v1/webhooks/logs | Inspect webhook attempts and delivery results. | Query: subscription_id, status, from, to, cursor | deliveries[] with response_code, attempts, next_retry_at |
Retrieve legally retained originals and immutable audit activity.
| Endpoint | Purpose | Expected request | Expected response |
|---|---|---|---|
GET /api/v1/archive/documents/{document_id}/download | Download the archived evidence package. | Path: document_id; Query: format=zip|xml|pdf | Original UBL, SBDH, FTA timestamps/tokens, and manifest |
GET /api/v1/audit/logs | Read historical access and modification records. | Query: actor, action, resource_id, from, to, cursor | events[] with actor, action, resource, timestamp, source_ip |
Contracts
Submit normalized accounting JSON or a pre-formed PINT AE UBL 2.1 document. JSON is mapped, validated, enveloped in an SBDH, and transmitted by the ASP.
{
"tenant_id": "uae_entity_88203",
"document_type": "tax_invoice",
"invoice_number": "INV-2026-008421",
"issue_date": "2026-09-02",
"currency": "AED",
"supplier": {
"legal_name": "Al Majid Electronics LLC",
"trn": "100234567800003",
"participant_id": "0235:100234567800003"
},
"buyer": {
"legal_name": "Gulf Digital Systems LLC",
"trn": "100987654300003",
"participant_id": "0235:100987654300003"
},
"lines": [
{
"id": "1",
"description": "Enterprise network switch",
"quantity": 4,
"unit_code": "EA",
"unit_price": 7250,
"vat_category": "S",
"vat_rate": 5,
"line_extension_amount": 29000
}
],
"totals": {
"tax_exclusive_amount": 29000,
"tax_amount": 1450,
"tax_inclusive_amount": 30450,
"payable_amount": 30450
}
}{
"document_id": "doc_01J7AQE3Y8N4K2W5Z6P9R0X1BC",
"uuid": "f6df92ab-7a50-4eb4-88a5-e18d41489593",
"status": "QUEUED",
"validation": {
"valid": true,
"ruleset": "PINT-AE-1.0.4",
"errors": [],
"warnings": []
},
"submitted_at": "2026-09-02T10:42:18Z"
}Send an Idempotency-Key on POST requests so safe retries cannot create duplicate documents.
Use application/json for mapped data or application/xml for a conformant PINT AE document.
Use RFC 3339 timestamps in UTC. Business issue dates remain ISO 8601 calendar dates.
Zero-trust integration
Authentication is one layer in a defense-in-depth design spanning identity, transport, tenant isolation, payload integrity, and operations.
Use grant_type=client_credentials. Tokens should be signed JWTs using RS256/EdDSA or opaque tokens validated by introspection, expire within 15–60 minutes, and never use refresh tokens for M2M access.
+--------------------+ +----------------------+
| Accounting / ERP | | ASP Auth Server |
| (Client) | | (Resource Server) |
+--------------------+ +----------------------+
| |
|-- 1. POST /api/v1/auth/token ------->| Validate client ID + secret
| grant_type=client_credentials |
| |
|<-- 2. Short-lived access token ------| JWT / bearer token
| expires in 15–60 minutes |
| |
|-- 3. POST /api/v1/invoices/send ---->| Validate token + scopes
| Authorization: Bearer ... |{
"sub": "erp_client_10023",
"tenant_id": "uae_entity_88203",
"trn": "100234567800003",
"scopes": ["invoices:write", "invoices:read"],
"exp": 1788372000
}Events
Subscribe to invoice, FTA reporting, delivery, and failure events instead of continuously polling lifecycle endpoints.
{
"event_id": "evt_01J7AR4MJ7B91K3RC4P2WQ8S5V",
"event_type": "INVOICE_CLEARED_FTA",
"occurred_at": "2026-09-02T10:42:24Z",
"tenant_id": "uae_entity_88203",
"data": {
"document_id": "doc_01J7AQE3Y8N4K2W5Z6P9R0X1BC",
"uuid": "f6df92ab-7a50-4eb4-88a5-e18d41489593",
"status": "CLEARED",
"fta_acknowledgement_id": "FTA-ACK-20260902-842190"
}
}Troubleshooting
Failures use stable machine-readable codes, a request correlation ID, and optional rule-level details for PINT AE validation errors.
{
"error": {
"code": "PINT_AE_VALIDATION_FAILED",
"message": "The document failed business-rule validation.",
"request_id": "req_01J7AQDZZNW21XKPEB3C73HSCX",
"details": [
{
"rule_id": "BR-AE-05",
"severity": "fatal",
"path": "/Invoice/TaxTotal",
"message": "VAT breakdown total does not match invoice lines."
}
]
}
}400Malformed request or unsupported field401Missing, expired, or invalid token403Insufficient scope or tenant mismatch409Duplicate or conflicting document state422PINT AE or FTA validation failure429Tenant or client rate limit exceeded