- Reference
Errors
This page uses these terms:
- Your organization: the account of your company in the Wafeq ASP portal. Your API keys, OAuth client and subscription belong to your organization.
- Mode: Live or Sandbox. Each mode has its own credentials and data.
- Grant: the permission that a business gives to your organization. A grant has an ID (
tgr_…) and scopes. The scopes are the permissions that the business approved. - Taxpayer: a business from which your organization has an active grant. Its ID is the Taxpayer ID (
txpay_…). - Document: an invoice or a credit note. Its ID is the document ID (
inv_…). - Check: a call to a
/validateendpoint, for examplePOST /invoices/validate. Wafeq ASP runs its checks and keeps nothing. - Submission: a call to
POST /invoices,POST /credit-notes, or to one of the two self-billing endpoints. - Buyer: the business that receives the document.
- Peppol ID: the address of a business on Peppol. For a UAE business, it is
0235:and then its TIN. - Correction: a submission with
corrects_document_id. It replaces a document that the provider of the buyer rejected. - Document credit: a prepaid unit of your organization. In Live, a document can use one credit.
Use this page when Wafeq ASP refuses a call. Each section is about one situation and tells you what to do. For the normal flow of a submission, refer to Submit a document.
How to read a refusal
Wafeq ASP gives a refusal in one of these forms:
| Form | Where the code is |
|---|---|
HTTP 4xx or 5xx, detail is an object | detail.code. detail.message explains it, if it is there. |
HTTP 4xx or 5xx, detail is a text | There is no code. Use the HTTP status and the text. |
HTTP 422, detail is a list | There is no code. Each item names a field that is not correct. |
HTTP 200, success: false | status. The error field explains it. |
HTTP 429 | There is no code. The error field explains it. |
| OAuth endpoints | error. The error_description field explains it. |
Example of a refusal with detail.code:
{
"detail": {
"code": "idempotency_key_reused",
"submission_request_id": "subr_0123456789ABCDEFGHIJ",
"message": "This key belongs to a different payload or an unfinished submission. Retry the same payload/key for its outcome; do not create a new send."
}
}Example of a submission that Wafeq ASP refuses with HTTP 200. The example shows only some of the fields:
{
"success": false,
"invoice_id": "INV-2026-0042",
"status": "duplicate_number",
"error": "Document number 'INV-2026-0042' was already submitted successfully. Use a unique number (resubmit the same number only to retry a failed submission)."
}Many refusals of a submission have the same code in a check. A check gives each problem as an item in errors. Thus, check each document before you submit it.
Credentials and access
These refusals are about your credentials and your grants.
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
| — | 401 | The API key or the access token is missing, not correct, or from the other mode. | Send a valid credential of the correct mode. |
| — | 400 | Your call uses an API key, but it has no x-ae-taxpayer-id header. | Add the Taxpayer ID in x-ae-taxpayer-id. |
| — | 404 | Wafeq ASP does not know the Taxpayer ID in this mode. | Use the Taxpayer ID from the connection. Do not use the TIN. |
| — | 403 | The taxpayer gave your organization no active grant. | Connect the business again. |
grant_not_active | 403 | The grant in x-ae-grant-id is not active, or it is not from this taxpayer. | Read GET /grants. Connect the business again if necessary. |
insufficient_scope | 403 | The grant does not have the scope that the call needs. detail.scope names it. | Start the authorization flow again with this scope. |
taxpayer_token_required | 403 | You sent an organization access token for a taxpayer call. | Use a token from the authorization flow, or your API key. |
| — | 403 | The text is Taxpayer is …. The taxpayer is not active, for example because it deregistered. | Do not submit documents for it. You can still read its documents. |
| — | 403 | The text is Taxpayer connection is not active. | Read GET /grants. Connect the business again if necessary. |
- A
401for an access token has the headerWWW-Authenticate: Bearer error="invalid_token". An access token expires after one hour. Get a new token with your refresh token. - An access token acts for one grant. If your
x-ae-taxpayer-idorx-ae-grant-idheader names a different taxpayer or grant, Wafeq ASP answers403. GET /invoices/{document_id}/reportsanswers422instead of400whenx-ae-taxpayer-idis missing.
OAuth token endpoint
POST /oauth/token, POST /oauth/revoke and POST /oauth/taxpayer-registration give errors in the OAuth format.
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
invalid_client | 401 | The client ID or the client secret is not correct. | Use the OAuth client of the correct mode. |
invalid_grant | 400 | The code or the refresh token is not valid. Refer to the list below. | Start the authorization flow again. |
unsupported_grant_type | 400 | grant_type is not authorization_code, refresh_token or client_credentials. | Correct grant_type. |
An invalid_grant error has one of these causes:
- The authorization code is not correct, it expired, or your app used it already.
redirect_uriis different from the value in the authorization request.- The PKCE check failed.
code_verifierdoes not matchcode_challenge. - The refresh token is not correct, it expired, or Wafeq ASP revoked it.
If your app sends a used code or an old refresh token again, Wafeq ASP revokes all the tokens of that grant. To get new tokens, start the authorization flow again.
OAuth authorization page
When the authorization request is not correct, Wafeq ASP redirects the business to your callback URL. The URL contains error, error_description and state.
| Code | Meaning | What to do |
|---|---|---|
invalid_request | A parameter is not correct. error_description names it. | Correct the parameter. |
invalid_scope | scope is empty, or it contains an unknown scope. | Send only the scopes that Authentication lists. |
unsupported_response_type | response_type is not code. | Send response_type=code. |
access_denied | The business declined your app. | Wafeq ASP created no grant. Ask the business before you try again. |
invalid_request has these causes:
- PKCE is missing, or
code_challenge_methodis notS256. code_challengedoes not have 43 to 128 characters.tin_hintis not a 10-digit TIN.statehas more than 1024 characters.external_iddoes not have 1 to 128 visible characters.- The legal registration hint is not complete.
PASalso needslegal_registration_issuing_country.
If the client ID is unknown, or the redirect URI is not in your list, Wafeq ASP does not redirect. The authorization page shows the error.
Billing
These refusals occur only in Live. Sandbox has no billing.
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
subscription_required | 402 | Your organization has no active subscription. | Buy or renew the subscription in the Wafeq ASP portal. |
wallet_insufficient_funds | 402 | Your organization has no free document credit. | Buy document credits in the Wafeq ASP portal. |
billing_status_unavailable | 503 | Wafeq ASP cannot get the current status of your subscription. | Wait a short time, then try again. |
subscription_requiredapplies to checks and to submissions.wallet_insufficient_fundsgivesrequiredDocumentsandavailableDocuments.wallet_insufficient_fundsalso applies when your app reads a received document that Wafeq ASP holds. Wafeq ASP holds a received document when your organization cannot pay for it. Thendetail.document_idnames the document.
When a new business approves your app in Live, Wafeq ASP checks your subscription and your free taxpayer seats. The business sees these refusals on the approval page. Your app does not receive them:
subscription_required(402): your organization has no active subscription.taxpayer_seat_limit_reached(409): all the taxpayer seats of your subscription are in use.unverified_client_limit_reached(409): your app is not verified, and it has 25 businesses in Live.
For these conditions, refer to Connect a taxpayer.
Request shape
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
| — | 422 | The body or a header does not match the API reference. detail is a list. | Correct each field that the list names. |
invalid_submission_payload | 422 | A value in the body is not valid JSON. | Remove values such as NaN or Infinity. |
invalid_participant_id | 422 | The Peppol ID in the path does not have the form scheme:value. | Send the Peppol ID, for example 0235:1999200000. |
Each item in the detail list has these fields:
loc: the path to the field, for example["body", "customer", "address"].msg: what is not correct.type: the kind of problem, for examplemissing.
These two headers also cause this error if they are not correct:
Idempotency-Keymust have 1 to 128 visible ASCII characters.Preferaccepts only the valuerespond-async.
Idempotency
These refusals come from the Idempotency-Key header of a submission.
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
idempotency_key_required | 422 | This submission needs an Idempotency-Key. Refer to the list below. | Send the submission again with a key. |
idempotency_key_reused | 409 | The key belongs to a submission with a different body. | Send the original body with this key, or use a new key. |
idempotency_in_progress | 409 | The first request with this key is still in progress. | Wait, then send the same request again. |
idempotency_unconfirmed | 409 | The first request with this key stopped. Its result is not known. | Refer to the list below. |
idempotency_unavailable | 503 | Wafeq ASP cannot store the submission or its result. | Send the same request again, with the same key. |
document_already_submitted | 409 | The taxpayer already submitted a document with this number. | Do not submit it again. Track the first submission. |
queued_delivery_unavailable | 503 | Queued delivery is not available at this time. | Try again later. |
A submission needs an Idempotency-Key in these cases:
- A submission with
Prefer: respond-async(queued delivery). - A submission that Wafeq ASP reports to the FTA only.
- A correction.
Wafeq ASP stores the response of each key when the submission ends. A refusal is also a response. For example, Wafeq ASP stores a 402 and each HTTP 200 with success: false. If you send the same key again, you get the stored response again. Thus, after such a refusal, correct the cause and use a new key. Wafeq ASP accepted nothing, so a new key does not submit the document two times.
Some refusals come before Wafeq ASP stores anything: 400, 401 and 404 for credentials, 422 with a list, and 429. After these refusals, you can send the same key again.
After idempotency_unconfirmed, do these steps:
- Do not send the request again with the same key. The answer does not change.
- Look for the number of the document in
GET /invoicesorGET /credit-notes. Filter by the issue date of the document. - If the document is in the list, Wafeq ASP accepted it. Track it.
- If the document is not in the list, submit it again with a new key.
Document checks
Wafeq ASP checks each document against the UAE rules. A check gives each problem in errors. A submission stops at the first kind of problem, and gives it in status.
Errors from the UAE rules
A check returns errors, warnings and info. Each item has these fields:
code: the code of the problem.message: the explanation.severity:error,warningorinfo.location: where the problem is in the XML document that Wafeq ASP makes from your request, ornull.
A submission with this kind of problem returns HTTP 200, success: false and status: validation_failed. validation_errors then contains a maximum of 10 items. These items have code, message and location. To see all the problems, check the document.
Read the codes in this way:
SCH:followed by a rule ID is an official UAE rule of PINT-AE, the UAE e-invoice format. For example,SCH:ibr-167-ae.- The message of an
SCH:rule uses the field numbers of the PINT-AE specification.IBT-…is a field.IBG-…is a group of fields.BTAE-…is a field that only the UAE uses. UBL-004means that the XML does not match the UBL schema.
Example: SCH:ibr-167-ae says that a line with VAT category E has no VAT exemption reason code (IBT-186). Add tax_exemption_reason_code to the line. For the VAT fields, refer to VAT on each line.
The warnings SCH-002, SCH-003 and UBL-003 tell you that Wafeq ASP could not run all the checks. Check the document again later.
During a queued submission, or a submission that goes to the FTA only, Wafeq ASP must run all the checks. If it cannot, it answers 503 with a text and no code. Try again later.
Other problems with the document
A submission returns these codes in status, with HTTP 200 and success: false. A check returns the same codes in errors, except where the table says something different.
| Code | Meaning | What to do |
|---|---|---|
duplicate_number | The taxpayer already used this number for a document that succeeded. A check gives duplicate_invoice_number. | Use a new number. |
missing_supplier | The taxpayer has no registered profile. A self-billed document gives missing_customer. | Ask the business to complete its onboarding. |
incomplete_profile | The registered profile of the taxpayer has no street or no city. | Ask the business to add them to its registered profile. |
seller_without_trn_taxable_lines | The seller has no VAT TRN, and a line has a VAT category other than E, O or Z. | Use E, O or Z on each line. |
buyer_legal_registration_required | A commercial document (480 or 81) has no legal registration for the buyer. | Add customer.legal_registration. |
transaction_flags_not_allowed | A commercial document (480 or 81) has a special scenario that it cannot have, for example a deemed supply. | Remove the flag from transaction_type_code. |
previous_invoice_not_found | The taxpayer did not issue a document with this previous_document_id. | Use the document ID of an invoice of this taxpayer. |
invalid_previous_document | The original is not an invoice that the taxpayer issued, its type does not match, or it has no number or date. | Use the document ID of the invoice that the credit note corrects. |
previous_invoice_party_mismatch | The credit note and the original invoice have different buyers. For self-billing, they have different sellers. | Use the party of the original invoice. |
previous_invoice_lookup_failed | Wafeq ASP could not read the original invoice. | Try again later. |
conversion_failed | Wafeq ASP could not make the XML document from your request. | Read error, and correct the request. |
profile_mismatch | The value of profile does not match the document. | Do not send profile. Wafeq ASP then uses the correct value. |
For the document types and the legal registration, refer to Document types. For special scenarios, refer to Special scenarios.
Buyer lookup on Peppol
Wafeq ASP looks for the buyer on Peppol before it delivers a document. These codes come from this lookup.
| Code | Where | Meaning | What to do |
|---|---|---|---|
smp_unavailable | Check: warning | Wafeq ASP could not look for the buyer at this time. | Submit as usual. The submission looks again. |
smp_unavailable | Submission: 503 | The lookup failed at this time. Wafeq ASP accepted nothing. | Send the same request again later, with the same key. |
smp_unavailable | Submission: 200, status | The lookup failed at this time. | Submit again later, with a new key. |
smp_lookup_failed | Check: error. Submission: 200, status | The buyer is not on Peppol, and the document cannot go to the FTA only. | Read Who receives the document. |
smp_lookup_error | Check: error | The lookup stopped with an error. | Check the document again later. |
reporting_only_unavailable | Check: error. Submission: 503 | Wafeq ASP cannot report this document to the FTA at this time. | Try again later. For a submission, use the same key. |
reporting_route_unavailable | Submission: 200, status | The document must go to the FTA only, but the submission did not select this route. | Check the document again, then submit it again with a new key. |
A check also gives codes that are not problems:
fta_reporting_only(warning): Wafeq ASP will report the document to the FTA only. The buyer gets no delivery.smp_resolved(info): Wafeq ASP found the buyer on Peppol.sandbox_simulated_deliveryandsandbox_simulated_reporting(info): Sandbox simulates the delivery or the report.
To look for a buyer before you build a document, send GET /recipients/{participant_id}/reachability. If error is not null, the lookup did not give an answer. Then reachable: false means "not known", not "not on Peppol".
Corrections
These refusals apply to a correction, and to POST /invoices/{document_id}/void. For the procedure, refer to Correct or cancel a document.
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
correction_not_ready | 409 | Wafeq ASP is still processing the report of the original document. | Wait, then send the same request again, with the same key. |
correction_number_or_type_mismatch | 422 | The number or the type is different from the original. | Use the number and the type of the original. |
c3_validation_rejection_required | 409 | The provider of the buyer did not reject the original with BV or SV. | You cannot correct this document. Refer to the procedure. |
correction_not_available | Check only | The original has a replacement already, or a different recovery is in progress. | Do not correct it again. |
correction_not_ready_or_already_replaced | 409 | The original is not ready for a correction, or another document replaced it. | Read the original with GET /invoices/{document_id}. |
different_recovery_requires_reconciliation | 409 | A different recovery of the original is in progress. Wafeq ASP must resolve it first. | Contact Wafeq ASP. |
transport_reconciliation_required | 409 | The delivery of the original is in progress at this moment. | Wait, then send the same request again. |
queued_document_not_found | 404 | The original is not a document of this taxpayer with queued delivery. | You can correct only documents that used queued delivery. |
document_owner_changed | 403 | Your organization did not submit the original. | Only the organization that submitted the original can correct it. |
sandbox_reporting_disabled | 403 | Corrections are not available in Sandbox. | — |
delivery_unsettled | 409 | Void only. The delivery of the original is not complete, or a recovery is in progress. | Try again after the delivery ends. |
correction_not_readyalso containsready: falseandreporting_recovery, the current state of the recovery.- These codes tell you that Wafeq ASP does not have the records that a correction needs:
document_evidence_unavailable,c3_evidence_unavailableandcorrection_lineage_invalid. Contact Wafeq ASP. - A check of a correction gives these codes as items in
errors. If Wafeq ASP cannot check the original, the item iscorrection_validation_unavailable. Check the document again later.
POST /invoices/{document_id}/void also gives these refusals, with a text and no code:
400: the document is a credit note, or the taxpayer received it.409: a credit note already credits the invoice.422: Wafeq ASP cannot rebuild the original request of the invoice.
Rate limits
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
| — | 429 | Your organization sent too many requests to this path in one minute. | Wait, then try again with exponential backoff. |
- The body has an
errorfield, for example"error": "Rate limit exceeded: 60 per 1 minute". - The response has no
Retry-Afterheader. - When you send a submission again, use the same
Idempotency-Key.
For the limit of each path, refer to Rate limits.
Updated about 14 hours ago