OneInvoice Integration API — Developer Guide

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.

1. Authentication

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.

2. Conventions

3. The invoice lifecycle

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:

4. Resources

4.1 Invoices — /invoices

MethodPathScopePurpose
POST/invoicesinvoice:invoice:createCreate a draft (invoice, credit note, debit note)
GET/invoicesinvoice:invoice:readList (status, from, to, organizationId, cursor, limit)
GET/invoices/{id}invoice:invoice:readThe invoice with its status
POST/invoices/{id}/submitinvoice:invoice:approve (+send)Validate, approve, send / register
GET/invoices/{id}/statusinvoice:invoice:readLifecycle status in one object
GET/invoices/{id}/documentinvoice:invoice:readThe frozen document: UBL XML, or INV-01 JSON for India
POST/invoices/{id}/cancelinvoice:invoice:voidCancel a draft / approved invoice; India: cancel the IRN within 24 h
POST/invoices/{id}/credit-noteinvoice:invoice:createRaise 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 }

4.2 Received invoices (purchases) — /received-invoices

MethodPathScopePurpose
GET/received-invoicesaccesspoint:received-document:readDocuments received for your tenant (status, cursor, limit)
GET/received-invoices/{id}sameThe document with its business content
POST/received-invoices/{id}/acceptaccesspoint:received-document:decideAccept — issues the positive MLS to the sender
POST/received-invoices/{id}/rejectsameReject with { "reason": "…" } — issues the negative MLS

4.3 Reports — /reports

GET /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 }.

5. Webhooks (next release)

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.

6. Quick start

# 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

7. Environments

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.