KWNDevelopersالعربيةOpen KWN

API reference

E-invoices

Invoices your own system issued, cleared with the FTA through KWN in one call.

Send an invoice for clearance

POST/einvoices

Needs
sales.write + sales.approve
Scopes
sales:writesales:approve

Send an Idempotency-Key header.

In one step: checks the seller TRN, finds or creates the buyer (by TRN, then by exact name), creates the KWN invoice under KWN's number, approves it and claims it — the claim takes exactly one credit and queues it for Taxstar. 201 with the e-invoice, PENDING. The same externalId with the same content answers the first invoice (200, duplicate: true) and takes no second credit; a rejected invoice sent again corrected is resubmitted (200, resubmitted: true). Any refusal leaves nothing behind. Requires Idempotency-Key and the scopes sales:approve.

Parameters

FieldTypeDescription
Idempotency-KeyHeaderRequiredstring1 to 100 visible ASCII characters, such as a UUID, unique to this request. Sent again with the same request, the first answer is replayed (Idempotent-Replayed: true); with another request, 422 IDEMPOTENCY_KEY_REUSED.

Request body

31 fields
FieldTypeDescription
externalIdstringYour system's id for the invoice; 1–100 visible ASCII characters.
sellerTrnstringMust be this company's TRN.
issueDatedateThe invoice day, YYYY-MM-DD.
linesobject[]
lines[].descriptionstring
lines[].quantitynumber
lines[].unitPricenumberVAT-exclusive unit price.
lines[].taxRatenumberVAT percent: 5 or 0.
lines[].productIdstring
lines[].productCodestringA product's SKU, then its barcode.
lines[].uomstring
lines[].discountnumber
externalNumberstringThe number your system shows; kept as a reference.
dueDatedate
customerIdstringAn existing contact by id …
customerobject
customer.namestring
customer.isCompanyboolean
customer.trnstring15 digits for a UAE company: matched first.
customer.emailstring
customer.phonestring
customer.addressstring
customer.citystring
customer.emirateABU_DHABI | DUBAI | SHARJAH | AJMAN | UMM_AL_QUWAIN | RAS_AL_KHAIMAH | FUJAIRAH
customer.countrystringISO 3166 alpha-2; AE by default.
customerRefstring
notesstring
paymentTermIdstring
paymentMeansCodestring
transactionFlagsFREE_TRADE_ZONE | DEEMED_SUPPLY | MARGIN_SCHEME | SUMMARY_INVOICE | CONTINUOUS_SUPPLY | DISCLOSED_AGENT_BILLING | ECOMMERCE | EXPORTS[]
expectedTotalnumberWhen set, the invoice must add up to it to the fils, or it is refused EINVOICE_TOTAL_MISMATCH.

Code samples

curl -sS -X POST "https://app.kwn.tax/api/v1/einvoices" \
  -H "X-Api-Key: $KWN_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "externalId": "INV-2026-00042",
  "externalNumber": "INV/2026/00042",
  "sellerTrn": "100234567800003",
  "issueDate": "2026-10-15",
  "dueDate": "2026-11-14",
  "customer": {
    "name": "Al Noor Trading L.L.C.",
    "isCompany": true,
    "trn": "100398765400003",
    "email": "accounts@alnoor.example",
    "address": "Office 1204, Bay Square, Business Bay",
    "city": "Dubai",
    "emirate": "DUBAI",
    "country": "AE"
  },
  "paymentMeansCode": "30",
  "lines": [
    {
      "description": "Bookkeeping, October 2026",
      "quantity": 1,
      "unitPrice": 2500,
      "taxRate": 5
    },
    {
      "description": "VAT return preparation",
      "quantity": 1,
      "unitPrice": 750,
      "taxRate": 5
    }
  ],
  "expectedTotal": 3412.5
}'

Responses

  • 200OK
    FieldTypeDescription
    idstring
    externalIdstring
    externalNumberstring
    numberstringKWN's number: the number cleared with Taxstar.
    statusstringPENDING, CLEARED, REJECTED, FAILED or CANCELLED.
    documentStatusDRAFT | SENT | CONFIRMED | ISSUED | SUBMITTED | PROCESSING | APPROVED | REJECTED | FAILED | PAID | CANCELLED | EXPIRED
    issueDatedate
    customerobject
    subtotalnumber
    taxTotalnumber
    totalnumber
    clearanceobject
    duplicatebooleanTrue when this answers an invoice already received with the same content.
    resubmittedbooleanTrue when a rejected invoice was corrected and sent again.
    createdAtdate
    updatedAtdate
  • 201Created
    FieldTypeDescription
    idstring
    externalIdstring
    externalNumberstring
    numberstringKWN's number: the number cleared with Taxstar.
    statusstringPENDING, CLEARED, REJECTED, FAILED or CANCELLED.
    documentStatusDRAFT | SENT | CONFIRMED | ISSUED | SUBMITTED | PROCESSING | APPROVED | REJECTED | FAILED | PAID | CANCELLED | EXPIRED
    issueDatedate
    customerobject
    subtotalnumber
    taxTotalnumber
    totalnumber
    clearanceobject
    duplicatebooleanTrue when this answers an invoice already received with the same content.
    resubmittedbooleanTrue when a rejected invoice was corrected and sent again.
    createdAtdate
    updatedAtdate
  • 400Refused: the request or a business rule. The code says which (REQUEST_INVALID, RULE_REFUSED, …).
    Example
    {
      "error": "Lines: at least one line is required.",
      "code": "REQUEST_INVALID"
    }
  • 401No key, a key that is not ours, or one revoked (API_KEY_INVALID); a merchant not active (MERCHANT_INACTIVE).
    Example
    {
      "error": "That API key is not valid, or it was revoked.",
      "code": "API_KEY_INVALID"
    }
  • 403The key's scopes do not carry the capability (APP_NOT_GRANTED, ROLE_TOO_LOW), or the plan lacks the app (APP_LOCKED).
    Example
    {
      "error": "This key's scopes do not include sales.approve.",
      "code": "ROLE_TOO_LOW"
    }
  • 404Not found: another type under this route, or another company's (NOT_FOUND).
    Example
    {
      "error": "Not found.",
      "code": "NOT_FOUND"
    }
  • 409A conflict: an externalId taken, or a change that could not be saved (EXTERNAL_ID_TAKEN, CONFLICT).
    Example
    {
      "error": "That externalId is already used by another record of this company.",
      "code": "EXTERNAL_ID_TAKEN"
    }
  • 422That Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED).
    Example
    {
      "error": "That Idempotency-Key was used for a different request.",
      "code": "IDEMPOTENCY_KEY_REUSED"
    }
  • 429Too many requests: wait retryAfter seconds (RATE_LIMITED).
    Example
    {
      "error": "Too many requests. Wait a little and try again.",
      "code": "RATE_LIMITED"
    }

List e-invoices

GET/einvoices

Needs
sales.read
Scopes
sales:read

The invoices that came in through this endpoint, newest first. Poll with updatedSince for status changes; filter by externalId, status (PENDING, CLEARED, REJECTED, FAILED, CANCELLED) and issueFrom/issueTo.

Parameters

FieldTypeDescription
statusQuerystringA status, by name.
partnerIdQuerystringThe customer (sales) or the vendor (purchases).
issueFromQuerydateIssued on or after this day.
issueToQuerydateIssued on or before this day.
numberQuerystring
limitQueryinteger1 to 200; 50 by default.
cursorQuerystringThe previous page's next.
updatedSinceQuerydateOnly rows changed at or after this instant.
createdFromQuerydate
createdToQuerydate
externalIdQuerystringOnly the row your system gave this id.

Code samples

curl -sS -X GET "https://app.kwn.tax/api/v1/einvoices" \
  -H "X-Api-Key: $KWN_API_KEY"

Responses

  • 200OK
    FieldTypeDescription
    dataobject[]The rows of this page.
    nextstringThe cursor of the next page, to send as ?cursor=; null on the last page.
  • 400Refused: the request or a business rule. The code says which (REQUEST_INVALID, RULE_REFUSED, …).
    Example
    {
      "error": "Lines: at least one line is required.",
      "code": "REQUEST_INVALID"
    }
  • 401No key, a key that is not ours, or one revoked (API_KEY_INVALID); a merchant not active (MERCHANT_INACTIVE).
    Example
    {
      "error": "That API key is not valid, or it was revoked.",
      "code": "API_KEY_INVALID"
    }
  • 403The key's scopes do not carry the capability (APP_NOT_GRANTED, ROLE_TOO_LOW), or the plan lacks the app (APP_LOCKED).
    Example
    {
      "error": "This key's scopes do not include sales.approve.",
      "code": "ROLE_TOO_LOW"
    }
  • 404Not found: another type under this route, or another company's (NOT_FOUND).
    Example
    {
      "error": "Not found.",
      "code": "NOT_FOUND"
    }
  • 409A conflict: an externalId taken, or a change that could not be saved (EXTERNAL_ID_TAKEN, CONFLICT).
    Example
    {
      "error": "That externalId is already used by another record of this company.",
      "code": "EXTERNAL_ID_TAKEN"
    }
  • 429Too many requests: wait retryAfter seconds (RATE_LIMITED).
    Example
    {
      "error": "Too many requests. Wait a little and try again.",
      "code": "RATE_LIMITED"
    }

Read an e-invoice

GET/einvoices/{id}

Needs
sales.read
Scopes
sales:read

Where the invoice stands: PENDING while with the provider, CLEARED with its reference, REJECTED or FAILED with the provider's errors.

Parameters

FieldTypeDescription
idPathRequiredstring

Code samples

curl -sS -X GET "https://app.kwn.tax/api/v1/einvoices/<id>" \
  -H "X-Api-Key: $KWN_API_KEY"

Responses

  • 200OK
    FieldTypeDescription
    idstring
    externalIdstring
    externalNumberstring
    numberstringKWN's number: the number cleared with Taxstar.
    statusstringPENDING, CLEARED, REJECTED, FAILED or CANCELLED.
    documentStatusDRAFT | SENT | CONFIRMED | ISSUED | SUBMITTED | PROCESSING | APPROVED | REJECTED | FAILED | PAID | CANCELLED | EXPIRED
    issueDatedate
    customerobject
    subtotalnumber
    taxTotalnumber
    totalnumber
    clearanceobject
    duplicatebooleanTrue when this answers an invoice already received with the same content.
    resubmittedbooleanTrue when a rejected invoice was corrected and sent again.
    createdAtdate
    updatedAtdate
  • 400Refused: the request or a business rule. The code says which (REQUEST_INVALID, RULE_REFUSED, …).
    Example
    {
      "error": "Lines: at least one line is required.",
      "code": "REQUEST_INVALID"
    }
  • 401No key, a key that is not ours, or one revoked (API_KEY_INVALID); a merchant not active (MERCHANT_INACTIVE).
    Example
    {
      "error": "That API key is not valid, or it was revoked.",
      "code": "API_KEY_INVALID"
    }
  • 403The key's scopes do not carry the capability (APP_NOT_GRANTED, ROLE_TOO_LOW), or the plan lacks the app (APP_LOCKED).
    Example
    {
      "error": "This key's scopes do not include sales.approve.",
      "code": "ROLE_TOO_LOW"
    }
  • 404Not found: another type under this route, or another company's (NOT_FOUND).
    Example
    {
      "error": "Not found.",
      "code": "NOT_FOUND"
    }
  • 409A conflict: an externalId taken, or a change that could not be saved (EXTERNAL_ID_TAKEN, CONFLICT).
    Example
    {
      "error": "That externalId is already used by another record of this company.",
      "code": "EXTERNAL_ID_TAKEN"
    }
  • 429Too many requests: wait retryAfter seconds (RATE_LIMITED).
    Example
    {
      "error": "Too many requests. Wait a little and try again.",
      "code": "RATE_LIMITED"
    }