Overview
This guide describes how to connect SAP — Business One, S/4HANA, ECC and ByDesign — to TrustBill, a UAE FTA-accredited service provider (ASP), so invoices issued in SAP are submitted as PINT-AE compliant e-invoices to the FTA without replacing your ERP.
SAP already manages UAE VAT, customer master data, chart of accounts and approval workflows. What it does not ship natively is PINT-AE XML generation and transmission through an FTA-accredited ASP over Peppol. TrustBill is that layer.
What this integration delivers
- Submit A/R Invoices and Credit Memos from SAP directly to the FTA
- Works with SAP Business One Service Layer, S/4HANA OData, ECC BAPI/RFC and ByDesign OData
- Optional TrustBill SAP Agent runs as a scheduled job or Windows/Linux service
- PINT-AE XML generated, validated and delivered by TrustBill
- FTA acknowledgement, UUID and QR written back into SAP UDFs / custom fields
- Bulk migration path for historical invoices via IDoc or CSV
What is SAP?
SAP is the market-leading enterprise resource planning (ERP) suite. The four SAP editions most used by UAE businesses for e-invoicing are:
- SAP Business One — SME ERP, on-premise or on HANA, with a built-in Service Layer REST API
- SAP S/4HANA — next-generation enterprise suite, exposes OData and SOAP services for finance and sales
- SAP ERP Central Component (ECC 6.0) — classic enterprise ERP, integrates via RFC/BAPI or SAP Gateway OData
- SAP Business ByDesign — cloud ERP for mid-market, with OData APIs for customer, supplier and invoice objects
Supported Versions
| SAP Product | Supported Versions | Primary API |
|---|---|---|
| SAP Business One | 10.0, 10.0 FP 2208+, HANA 2.0 | Service Layer (OData / REST) |
| SAP S/4HANA | 2022, 2023, 2024 FPS | OData V4 / SOAP |
| SAP ECC 6.0 | EHP 7+, with SAP Gateway optional | BAPI/RFC or OData Gateway |
| SAP Business ByDesign | 2023, 2024 releases | OData / SOAP |
Prerequisites
- SAP system running a supported version with valid UAE VAT and TRN setup
- Customer master records include 15-digit TRN for B2B transactions
- User account or service user with read access to A/R Invoice and Customer objects
- Active TrustBill SME account with API credentials
- Network egress from SAP host / middleware to TrustBill API endpoints
- For on-premise SAP: a Windows or Linux agent machine with .NET Framework 4.8 or .NET 6/8 runtime
Integration Architecture
The standard pattern keeps SAP as the source of record and uses a small middleware agent or scheduled script to transport invoice data into TrustBill.
- Invoice posted in SAP (A/R Invoice, Billing Document or ByDesign Invoice).
- TrustBill Agent / middleware queries the SAP API on a schedule or listens for an event trigger.
- Payload normalised into TrustBill's PINT-AE JSON format.
- POST to TrustBill
/api/v1/invoiceswith API key authentication. - TrustBill validates, renders PINT-AE XML and submits over Peppol via the FTA-accredited ASP.
- Acknowledgement written back to SAP UDFs or custom fields.
Connection Methods
1. SAP Business One Service Layer (Recommended for B1)
Use the built-in Service Layer REST API on port 50000 (HTTP) or 50001 (HTTPS). Query Invoices, CreditNotes, BusinessPartners and Items, then transform and forward to TrustBill.
2. SAP S/4HANA OData
Connect to SAP Gateway OData V4 services such as API_BILLING_DOCUMENT_SRV or API_UNIFIED_INVOICING. Use client certificate or basic authentication with CSRF tokens.
3. SAP ECC BAPI/RFC
For legacy ECC, call BAPIs such as BAPI_BILLINGDOC_GETLIST or use the SAP .NET Connector / SAP NWRFC SDK from a middleware agent.
4. SAP Business ByDesign OData
Query ByDesign OData endpoints for CustomerInvoice and CustomerInvoiceItem using a technical user.
5. IDoc / CSV Fallback
For controlled migrations, export invoice data as IDoc flat-file or CSV and upload through TrustBill's bulk import interface.
Authentication
TrustBill API uses Bearer tokens. In SAP, store the token in a secure parameter or in your middleware's secret store.
POST https://trustbill.ae/api/v1/invoices
Authorization: Bearer tb_your_api_key_here
Content-Type: application/jsonSAP-side authentication depends on the product:
- Business One: Service Layer session cookie after
POST /b1s/v2/Login - S/4HANA: OAuth 2.0 client-credentials or basic auth with x-csrf-token
- ECC: SAP username + password + client number via RFC or SAP Gateway
- ByDesign: technical user username + password
SAP Business One Setup
This is the fastest production setup for Business One. The middleware logs into Service Layer, fetches new invoices and pushes them to TrustBill on a schedule.
Step 1: Add UDFs to A/R Invoice
U_TB_Status(Alphanumeric 20): Pending / Submitted / Acknowledged / RejectedU_TB_UUID(Alphanumeric 50): TrustBill UUIDU_TB_AckRef(Alphanumeric 50): FTA acknowledgement referenceU_TB_Reject(Text): Error or rejection message
Step 2: Middleware Python sample
import requests
import json
B1_BASE = "https://sapserver:50001/b1s/v2"
TRUSTBILL_BASE = "https://trustbill.ae/api/v1"
# 1. Login to Service Layer
login = requests.post(f"{B1_BASE}/Login", json={
"CompanyDB": "SBODemoAE",
"UserName": "manager",
"Password": "password",
"Language": -1
})
login.raise_for_status()
cookies = login.cookies
# 2. Fetch posted A/R invoices not yet sent
invoices = requests.get(
f"{B1_BASE}/Invoices?$filter=DocumentStatus eq 'bost_Open' and U_TB_Status eq null",
cookies=cookies
).json()
for inv in invoices.get("value", []):
customer = requests.get(
f"{B1_BASE}/BusinessPartners('{inv['CardCode']}')",
cookies=cookies
).json()
payload = {
"invoiceNumber": inv["DocNum"],
"issueDate": inv["DocDate"].split("T")[0],
"dueDate": inv["DocDueDate"].split("T")[0],
"currency": inv["DocCurrency"],
"seller": {
"trn": "123456789100003", # company TRN
"legalName": "Your Company LLC",
"address": "Dubai, UAE"
},
"buyer": {
"trn": customer.get("FederalTaxID", ""),
"legalName": customer.get("CardName", ""),
"address": customer.get("Address", "")
},
"items": [
{
"name": line["ItemDescription"],
"quantity": float(line["Quantity"]),
"unitPrice": float(line["Price"]),
"discount": float(line.get("DiscountPercent", 0)),
"taxPercent": float(line["TaxPercentagePerRow"] or 0),
"lineTotal": float(line["LineTotal"])
}
for line in inv["DocumentLines"]
],
"totals": {
"netAmount": float(inv["DocTotalNet"]),
"taxAmount": float(inv["VatSum"]),
"grossAmount": float(inv["DocTotal"])
}
}
resp = requests.post(
f"{TRUSTBILL_BASE}/invoices",
headers={"Authorization": "Bearer tb_your_api_key"},
json=payload
)
data = resp.json()
# 3. Update UDFs via Service Layer
patch = {
"U_TB_Status": "Acknowledged" if resp.ok and data.get("acknowledged") else "Rejected",
"U_TB_UUID": data.get("uuid", ""),
"U_TB_AckRef": data.get("ackRef", ""),
"U_TB_Reject": json.dumps(data) if not resp.ok else ""
}
requests.patch(
f"{B1_BASE}/Invoices({inv['DocEntry']})",
cookies=cookies,
json=patch
)SAP S/4HANA Setup
For S/4HANA, use an OData service that exposes billing documents. The standard API is API_BILLING_DOCUMENT_SRV; if it is not enabled, your SAP Basis team can activate it via SICF and generate the service.
GET https://s4host:port/sap/opu/odata/sap/API_BILLING_DOCUMENT_SRV/A_BillingDocument('90000000')
?$expand=to_Item,to_Partner
&sap-client=100
Accept: application/json
x-csrf-token: fetch
Authorization: Basic <base64(user:pass)>After fetching the billing document and partner data, the transformation into TrustBill JSON is identical to the Business One flow. The main difference is the OData field names: BillingDocument, BillingDocumentItem, Customer and NetAmount.
SAP → TrustBill Field Mapping
| SAP Field | TrustBill JSON | Notes |
|---|---|---|
DocNum / BillingDocument | invoiceNumber | Unique per fiscal year |
DocDate / BillingDocumentDate | issueDate | ISO-8601 |
Company FederalTaxID | seller.trn | 15-digit UAE TRN |
Customer.FederalTaxID | buyer.trn | Required for B2B |
DocumentLines.ItemDescription | items[].name | English + Arabic if available |
DocumentLines.Quantity | items[].quantity | Positive numeric |
DocumentLines.Price | items[].unitPrice | After line discount |
DocTotal / TotalAmount | totals.grossAmount | VAT inclusive |
UAE VAT / Tax Mapping
Map SAP tax code percentages to FTA tax category codes. The most common SAP tax codes for the UAE are OA5 (5% standard), OA0 (zero), OAE (exempt) and OAR (reverse charge).
| SAP Tax Code | Description | TrustBill taxCategory | Rate |
|---|---|---|---|
OA5 | Standard VAT | STANDARD | 5% |
OA0 | Zero-Rated | ZERO_RATE | 0% |
OAE | Exempt | EXEMPT | — |
OAR | Reverse Charge | REVERSE_CHARGE | 5% |
OOS | Out of Scope | OUT_OF_SCOPE | — |
Credit Notes
SAP credit memos / credit notes are mapped to TrustBill credit-note endpoint. Include the original SAP invoice number and a negative gross amount.
POST https://trustbill.ae/api/v1/credit-notes
{
"originalInvoiceNumber": "90000001",
"issueDate": "2026-09-08",
"creditNoteNumber": "90000010",
"reason": "Goods return",
"totals": {
"grossAmount": -525.00
}
}Status Tracking
TrustBill can call a webhook to your middleware or SAP gateway. The payload includes the invoice number, new status, acknowledgement reference and reason.
POST https://your-middleware.example.com/webhook/trustbill
Content-Type: application/json
{
"invoiceNumber": "90000001",
"status": "Acknowledged",
"ackRef": "FDA-ACK-123456789",
"uuid": "a1b2c3d4-...",
"reason": null
}Your middleware then writes the status back to the SAP UDFs using the Service Layer PATCH, OData UPDATE or BAPI update method.
Bulk Migration
For historical invoices, export from SAP using SE16N, a custom query, or the OData service with a date filter. The CSV must contain the same columns as the field mapping table above.
POST https://trustbill.ae/api/v1/invoices/bulk
Authorization: Bearer tb_your_api_key
Content-Type: multipart/form-data
file: invoices.csv
options: {"mode":"sandbox","skipErrors":true}Sandbox & Live Modes
Test end-to-end without touching the FTA. Switch to live once your 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 |
Multi-Company Code & Multi-Currency
SAP is frequently deployed with several company codes sharing one client — for example a UAE mainland entity and a free-zone entity, or a holding company with multiple UAE branches. TrustBill treats each company code as an independent seller with its own TRN, so the mapping layer must resolve the correct TrustBill profile per company code before submission.
Company code → TrustBill profile mapping
Maintain a lookup table (custom Z-table, or a middleware config file) that maps each SAP BUKRS to a TrustBill API key and TRN. Never hardcode a single TRN for the whole integration — cross -entity invoices submitted under the wrong TRN are rejected by the FTA and can trigger compliance questions.
Multi-currency invoices
SAP stores the document currency (WAERK) separately from the local currency. TrustBill expects the invoice in the transaction currency plus the AED equivalent when the document currency is not AED. Include both currency and exchangeRate (or a pre-converted totals.grossAmountAed) in the payload so the FTA-facing PINT-AE document always carries an AED value.
Intercompany billing
Intercompany invoices between two UAE company codes under the same client still require separate PINT-AE submissions — one from the selling company code, one recorded as a purchase on the buying side. Do not collapse them into a single TrustBill submission.
Error Handling & API Errors
Design the SAP-side connector to treat every non-2xx TrustBill response as retryable-or-not based on the HTTP status, and always log the response body for audit.
| HTTP Status | Meaning | Action |
|---|---|---|
| 400 | Malformed JSON or missing required field | Fix payload; do not retry unchanged |
| 401 | Invalid or expired API key | Rotate the key in Service Layer / middleware config |
| 403 | TRN on invoice does not match the API key's registered TRN | Fix company-code → TRN mapping |
| 409 | Duplicate invoice number for this seller | Check idempotency key / SAP document 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 relevant company code
- Customer master TRNs populated for B2B customers
- Service Layer / OData / IDoc access enabled and firewalled to TrustBill IPs only
- Company-code → TrustBill API key mapping table created
- Tax code → PINT-AE tax category mapping reviewed with finance
- Credit memo (Rechnungskorrektur) flow mapped to TrustBill credit notes
- Webhook or polling job configured for status write-back
- Sandbox invoices tested for standard, zero-rated, exempt and reverse-charge cases
- Bulk migration CSV template validated against historical AR data
- Go-live date agreed and live mode switched only after sandbox sign-off
Troubleshooting
- 422 validation error: Check that buyer TRN is 15 digits and that company TRN is set in SAP.
- SAP CSRF token error (S/4HANA): Fetch a fresh token with
GET .../A_BillingDocument?$top=1andx-csrf-token: fetchbefore POST/UPDATE. - Service Layer 401: Renew the session cookie before it expires; the default timeout is 30 minutes.
- Missing Arabic names: Use the
ForeignNameor custom UDF to store Arabic legal names and map them to the payload. - S/4HANA OData not found: Activate the required service in
/IWFND/MAINT_SERVICEand assign the user to the correct authorization role.
Support
Need help with the SAP integration? Our team can review your Service Layer, OData, RFC or IDoc setup and provide a tailored middleware blueprint.