Documentation

Overview

Emara Invoice by Momentum Tech is a UAE PINT-AE e-invoicing conversion engine exposed as a multi-tenant SaaS platform. It accepts invoices in a normalized JSON format, validates them against UAE Federal Tax Authority rules, and returns PINT-AE UBL 2.1 XML ready for submission to any FTA-accredited Peppol Access Point (ASP).

Base URL
http://207.180.232.7
Standard
PINT-AE BIS v1.0.2 (2025-Q2)
Format
UBL 2.1 XML · JSON input

Quick Start

Step 1: Register and get an API key
# 1. Register at /register
# 2. Go to API Keys → Generate key
# Your key starts with:  eiv_...
Step 2: Validate an invoice (no XML output)
curl -X POST http://207.180.232.7/api/v1/invoices/validate \
  -H "Authorization: Bearer eiv_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d @invoice.json

# Response: {"valid": true, "errors": [], "totals": {...}}
Step 3: Convert to UBL XML
curl -X POST http://207.180.232.7/api/v1/invoices/convert \
  -H "Authorization: Bearer eiv_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d @invoice.json \
  -o output.xml

# Returns UBL 2.1 XML file

Authentication

All API endpoints require a Bearer token in the Authorization header. Two token types are accepted:

API Key (Machine-to-Machine)
Authorization: Bearer eiv_xxxxxxxx

Generated in the API Keys page. Use for ERP integrations. Never expires unless revoked.

JWT Token (Web Sessions)
Authorization: Bearer eyJhbGci...

Obtained from POST /login. Expires in 8 hours. Used by the web dashboard.

Validate Invoice

POST /api/v1/invoices/validate

Validates a normalized invoice JSON against UAE PINT-AE rules. Returns errors and computed totals. Does NOT generate XML.

Request Body
{
  "invoice_id": "INV-001",
  "issue_date": "2026-06-05",
  "document_type_code": "380",
  "currency": "AED",
  "seller": { "legal_name": "...", "tin": "...", "trn": "..." },
  "buyer":  { "legal_name": "...", "tin": "..." },
  "lines":  [{ "id":"1", "item_name":"...", "quantity":1,
               "unit_code":"C62", "net_price":100,
               "tax_category":"S", "tax_rate":5 }]
}
Response
{
  "valid": true,
  "errors": [],
  "totals": {
    "tax_exclusive_amount": 100.00,
    "tax_amount": 5.00,
    "payable_amount": 105.00
  }
}

Convert to UBL XML

POST /api/v1/invoices/convert

Validates and converts a normalized invoice to PINT-AE UBL 2.1 XML. Add ?submit=true to also forward to your ASP.

Request Body
Same body as /validate
Response
<?xml version='1.0' encoding='UTF-8'?>
<Invoice xmlns="urn:oasis:names:specification:ubl...">
  ...
</Invoice>

Batch Convert

POST /api/v1/invoices/batch

Convert an array of invoices in one call. Each invoice is processed independently — failures don't block others.

Request Body
[
  { ...invoice 1... },
  { ...invoice 2... }
]
Response
{
  "batch_id": "batch_abc123",
  "total": 2,
  "succeeded": 2,
  "failed": 0,
  "results": [
    {"invoice_id":"INV-001","status":"ok","asp_reference":null},
    {"invoice_id":"INV-002","status":"ok","asp_reference":null}
  ]
}

Invoice Schema

Field Type Required Description
invoice_id string Required Your internal invoice number, e.g. INV-2026-001
issue_date string Required YYYY-MM-DD format
document_type_code string Required 380=Tax Invoice, 381=Tax Credit Note, 480=Commercial Invoice, 81=Commercial Credit Note, 389=Self-billed Invoice, 261=Self-billed Credit Note
currency string AED ISO 4217 currency code
due_date string Optional YYYY-MM-DD
buyer_reference string Optional Buyer's PO number — required if no order_reference
seller object Required Party object — see below
buyer object Required Party object — see below
lines array Required Array of InvoiceLine objects
payment_means object Optional Payment method — code 30=credit transfer (needs IBAN), 10=cash
document_allowances_charges array Optional Document-level discounts or charges
💡 Party Object Fields
legal_name, tin (Peppol electronic address, scheme 0235), trn (UAE VAT registration number), address (street, city, postal_zone, country_code), contact (name, telephone, email)

Custom Connectors

A connector is simply code that maps your source system's fields to the normalized invoice JSON. The simplest connector is a Python dict:

def my_erp_to_normalized(erp_invoice: dict) -> dict:
    return {
        "invoice_id":           erp_invoice["number"],
        "issue_date":           erp_invoice["date"],
        "document_type_code":   "380",
        "currency":             "AED",
        "seller": {
            "legal_name": erp_invoice["company_name"],
            "tin":        erp_invoice["company_trn"],
            "trn":        erp_invoice["company_trn"],
            "address":    { "country_code": "AE" }
        },
        "buyer": {
            "legal_name": erp_invoice["customer_name"],
            "tin":        erp_invoice["customer_trn"],
            "address":    { "country_code": "AE" }
        },
        "lines": [{
            "id":           str(i+1),
            "item_name":    line["description"],
            "quantity":     line["qty"],
            "unit_code":    "C62",
            "net_price":    line["unit_price"],
            "tax_category": "S",
            "tax_rate":     5,
        } for i, line in enumerate(erp_invoice["lines"])],
        "payment_means": { "code": "10" }
    }

Error Reference

HTTP Code Meaning Fix
200 Success
401 Invalid or missing API key Check Authorization: Bearer eiv_... header
422 Invoice validation failed Check the errors array in response body
400 Bad request / malformed JSON Check required fields: invoice_id, issue_date, seller, buyer, lines
500 Server error Contact support with the request body