Base URL: https://api.oneinvoice.com/v1 · Interactive reference (Swagger): https://api.oneinvoice.com/docs · OpenAPI JSON: https://api.oneinvoice.com/docs-json
One host serves every country. Your credential belongs to one tenant, the tenant belongs to one country, and the API routes every call to that country's platform. Country-specific data (TRN / VATIN / GSTIN, HSN codes, Peppol vs IRP) rides on the same resources — there are no per-country endpoints.
API key (recommended for ERPs). Created by a tenant or platform administrator in the portal: Administration → Integration → Create key. Shown once. Send it on every request:
X-Api-Key: oi_live_97d05602_…
A key carries scopes (the permissions it may exercise). The presets: Everything, Invoices (create, submit, read, cancel), Read only, Purchases, Reports, or a custom pick. A call outside the key's scopes answers 403 APIKEY.SCOPE_MISSING. Keys can be disabled (takes effect within a minute), re-enabled and revoked (final) from the same page.
OAuth 2 bearer (for signed-in users and platform tools). Authorization: Bearer <access token> from the OneInvoice identity provider; the token's own permissions apply.
YYYY-MM-DD; timestamps ISO-8601 UTC. Money as decimal strings ("262.50"), never floats.Idempotency-Key: <unique per operation> on every POST. The same key with the same body returns the first result for 24 hours; the same key with a different body is treated as a new request.x-correlation-id; quote it when raising a ticket.application/problem+json: { "type", "title", "status", "detail", "code", "retryable", "instance" }. code is stable — branch on it, not on detail. Common: APIKEY.UNKNOWN / DISABLED / REVOKED / EXPIRED (401), APIKEY.SCOPE_MISSING (403), PLATFORM.PERMISSION_DENIED (403), INVOICE.NOT_FOUND (404), INVOICE.INVALID (422, with issues[]), INVOICE.IMMUTABLE (409), GATEWAY.UPSTREAM_UNREACHABLE (502, retryable).429 with Retry-After beyond it.limit (≤ 200) and cursor; the response carries nextCursor (null at the end).DRAFT ──validate──▶ VALIDATED ──approve──▶ APPROVED ──send──▶ TRANSMITTING ──▶ DELIVERED
│ │
(invalid: stays DRAFT, issues[] returned) └──▶ REJECTED ◀──────┘ (buyer refusal / transmission failure)
India: APPROVED ──register──▶ CLEARANCE_REQUESTED ──▶ DELIVERED (IRN issued) | REJECTED (IRP refusal)
POST /invoices/{id}/submit runs validate → approve → send (or register) in one call and returns the invoice; an invalid document answers 422 with issues[] and the draft is unchanged. Individual steps are also available as …/validation, …/approval, …/transmission if you prefer to drive them separately.
Statuses per country:
status above plus peppol (SUBMITTED → DELIVERED / REJECTED), mls (buyer's message-level status), taxData (submitted to the FTA / OTA, accepted / rejected).clearance — status CLEARED with irn, ackNo, ackDate, signedQr; or REJECTED with the IRP errorCode / errorMessage./invoices| Method | Path | Scope | Purpose |
|---|---|---|---|
| POST | /invoices | invoice:invoice:create | Create a draft (invoice, credit note, debit note) |
| GET | /invoices | invoice:invoice:read | List (status, from, to, organizationId, cursor, limit) |
| GET | /invoices/{id} | invoice:invoice:read | The invoice with its status |
| POST | /invoices/{id}/submit | invoice:invoice:approve (+send) | Validate, approve, send / register |
| GET | /invoices/{id}/status | invoice:invoice:read | Lifecycle status in one object |
| GET | /invoices/{id}/document | invoice:invoice:read | The frozen document: UBL XML, or INV-01 JSON for India |
| POST | /invoices/{id}/cancel | invoice:invoice:void | Cancel a draft / approved invoice; India: cancel the IRN within 24 h |
| POST | /invoices/{id}/credit-note | invoice:invoice:create | Raise a credit note against an approved / delivered invoice |
Create — request body (the same JSON the portal's Import JSON accepts):
{
"organizationId": "01M0PKBPQGFV6MGN19RAPCTH7H",
"type": "COMMERCIAL_INVOICE",
"number": "INV-2026-000123",
"issueDate": "2026-09-13",
"dueDate": "2026-10-13",
"currency": "AED",
"countryCode": "AE",
"supplier": {
"legalName": "United Technologies LLC",
"endpointSchemeId": "0235", "endpointValue": "100100309312345",
"taxRegistrations": [{ "identifier": "100100309312345", "scheme": "VAT" }],
"legalRegistrationId": "CN-1234567", "legalRegistrationScheme": "TL",
"address": { "line1": "Office 1204, Business Bay", "city": "Dubai", "countrySubdivision": "AE-DU", "postalCode": "00000", "countryCode": "AE" }
},
"customer": {
"legalName": "OneInvoice Test Customer LLC",
"endpointSchemeId": "0235", "endpointValue": "100100333312345",
"taxRegistrations": [{ "identifier": "100100333312345", "scheme": "VAT" }],
"address": { "line1": "Al Maryah Island", "city": "Abu Dhabi", "countrySubdivision": "AE-AZ", "countryCode": "AE" }
},
"lines": [
{ "id": "1", "name": "Consulting services", "quantity": "10", "unitCode": "HUR", "unitPrice": "250.00",
"taxCategory": { "code": "S", "percent": "5" }, "commodityCode": "" }
],
"paymentMeansCode": "30",
"note": "Thank you for your business"
}
Country variants: Oman — currency: "OMR", countryCode: "OM", VATIN OM1100077496 as the tax registration, addresses in governorates (OM-MA …), Peppol scheme 0248. India — currency: "INR", countryCode: "IN", GSTIN as the tax registration with scheme: "GST", state as countrySubdivision (IN-KA …), commodityCode (HSN/SAC) required on every line, taxCategory.percent a GST rate (5, 12, 18, 28 …); no Peppol endpoint. Optional on every country: channel (PEPPOL default, DIRECT = you deliver the document yourself, the platform still reports tax data), buyerKind (BUSINESS default, CONSUMER for B2C).
Response (201): the invoice as stored — id, status: "DRAFT", totals computed (totals.taxExclusiveAmount, taxTotalAmount, payableAmount), lines[] with netAmount, and createdAt.
Status — response (GET /invoices/{id}/status):
{ "id": "01M…", "number": "INV-2026-000123", "status": "DELIVERED", "channel": "PEPPOL", "countryCode": "AE",
"validatedAt": "2026-09-13T08:01:02Z", "transmittedAt": "2026-09-13T08:01:40Z", "rejectionReason": null,
"clearance": null }
/received-invoices| Method | Path | Scope | Purpose |
|---|---|---|---|
| GET | /received-invoices | accesspoint:received-document:read | Documents received for your tenant (status, cursor, limit) |
| GET | /received-invoices/{id} | same | The document with its business content |
| POST | /received-invoices/{id}/accept | accesspoint:received-document:decide | Accept — issues the positive MLS to the sender |
| POST | /received-invoices/{id}/reject | same | Reject with { "reason": "…" } — issues the negative MLS |
/reportsGET /reports/transactions, /reports/tax-data, /reports/peppol, /reports/mls, /reports/failures, /reports/dashboard — scope reporting:report:read. Filters: range (last7, last30, last90, thisMonth, or from/to), direction, per-report statuses, q (UUID / number / correlation id), page, pageSize (≤ 200), sort, sortDir. Responses are { items, page, pageSize, total }.
Register an endpoint and secret; the platform delivers invoice.validated, invoice.delivered, invoice.rejected, mls.received, invoice.cleared, tax_data.accepted as signed POSTs (X-OneInvoice-Signature: sha256=… over the raw body), retried with backoff for 24 hours, with a delivery log in the portal. Until then, poll GET /invoices/{id}/status.
# 1. list
curl -H "X-Api-Key: $KEY" "https://api.oneinvoice.com/v1/invoices?limit=5"
# 2. create
curl -X POST -H "X-Api-Key: $KEY" -H "Content-Type: application/json" -H "Idempotency-Key: erp-000123" \
--data @invoice.json "https://api.oneinvoice.com/v1/invoices"
# 3. submit (validate + approve + send)
curl -X POST -H "X-Api-Key: $KEY" -H "Idempotency-Key: erp-000123-submit" "https://api.oneinvoice.com/v1/invoices/$ID/submit"
# 4. status / document
curl -H "X-Api-Key: $KEY" "https://api.oneinvoice.com/v1/invoices/$ID/status"
curl -H "X-Api-Key: $KEY" "https://api.oneinvoice.com/v1/invoices/$ID/document" -o invoice.xml
Staging: https://api.oneinvoice.com (this document). Production per country will use the same host; the key decides the tenant and therefore the country. Test with a key on a test tenant; never reuse a production key in a test system.