{"data":[{"code":"validation_failed","type":"https://api.invox.page/v1/errors/validation_failed","status":400,"title":"The request is not valid","retryable":"after_fixing_request","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["Read `errors`: it lists every problem, each with the path of the field.","Fix them all and send the request again; the same Idempotency-Key can be reused."],"reproduce":"Send POST /v1/organizations with an empty JSON body."},{"code":"malformed_request","type":"https://api.invox.page/v1/errors/malformed_request","status":400,"title":"The request body is not valid JSON","retryable":"after_fixing_request","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["Send a JSON body with `Content-Type: application/json`."],"reproduce":"Send POST /v1/organizations with the body `{`."},{"code":"unauthenticated","type":"https://api.invox.page/v1/errors/unauthenticated","status":401,"title":"No credential was sent","retryable":"after_fixing_request","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["Send `Authorization: Bearer <credential>`: a service-account key (`sk_test_…` / `sk_live_…`) or a person's access token.","To obtain a person's access token without a browser on your side, start the device flow described at GET /v1."],"reproduce":"Call GET /v1/me without an Authorization header."},{"code":"invalid_credential","type":"https://api.invox.page/v1/errors/invalid_credential","status":401,"title":"The credential is not valid","retryable":"after_external_change","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["A person's access token expires quickly: refresh it and retry.","A service-account key that was revoked, or whose service account was disabled, must be replaced by a new key."],"reproduce":"Call GET /v1/me with `Authorization: Bearer sk_test_invalid`."},{"code":"person_credential_required","type":"https://api.invox.page/v1/errors/person_credential_required","status":403,"title":"This route is for a person, not for a service account","retryable":"after_external_change","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["Listing and creating organizations belongs to a person: use a person's access token (see GET /v1)."],"reproduce":"Call GET /v1/organizations with a service-account key."},{"code":"missing_scope","type":"https://api.invox.page/v1/errors/missing_scope","status":403,"title":"The credential lacks the permission this operation requires","retryable":"after_external_change","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["`required_scope` names the permission. GET /v1/me lists the ones this credential holds.","Ask a person with an owner or admin role to grant it, or use another credential."],"reproduce":"Create a service account with only `invoices:read` and call POST /v1/invoices with its key."},{"code":"not_found","type":"https://api.invox.page/v1/errors/not_found","status":404,"title":"The resource does not exist in this organization","retryable":"never","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["Check the id and the organization: a resource of another organization is reported as not found.","A test resource does not exist in the live organization, and the reverse."],"reproduce":"Call GET /v1/invoices/00000000-0000-4000-8000-000000000000."},{"code":"route_not_found","type":"https://api.invox.page/v1/errors/route_not_found","status":404,"title":"There is no such route","retryable":"never","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["GET /v1/openapi.json lists every route with its permission and its errors."],"reproduce":"Call GET /v1/nothing-here."},{"code":"organization_required","type":"https://api.invox.page/v1/errors/organization_required","status":400,"title":"This credential needs to say which organization it acts on","retryable":"after_fixing_request","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["A person's access token is not tied to one organization: send the `X-Organization` header with the organization id.","GET /v1/organizations lists yours, each with the id of its live and of its test organization."],"reproduce":"Call GET /v1/issuer with a person's access token and no X-Organization header."},{"code":"organization_mismatch","type":"https://api.invox.page/v1/errors/organization_mismatch","status":403,"title":"The X-Organization header names another organization than the key's","retryable":"after_fixing_request","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["A service-account key always acts on its own organization: remove the `X-Organization` header, or use a key of that organization."],"reproduce":"Call GET /v1/me with a service-account key and `X-Organization` set to any other organization id."},{"code":"organization_archived","type":"https://api.invox.page/v1/errors/organization_archived","status":403,"title":"The organization is archived","retryable":"never","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["An archived organization only answers reads. Create or use another organization."],"reproduce":"Archive an organization with POST /v1/organizations/{id}/archive and then call PUT /v1/issuer on it."},{"code":"organization_limit_reached","type":"https://api.invox.page/v1/errors/organization_limit_reached","status":409,"title":"This person already owns the maximum number of organizations","retryable":"after_external_change","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["Archive an organization that has issued nothing in live mode (POST /v1/organizations/{id}/archive); it stops counting."],"reproduce":"Create organizations with one person until the answer is this error (the limit is in GET /v1)."},{"code":"organization_not_archivable","type":"https://api.invox.page/v1/errors/organization_not_archivable","status":409,"title":"The organization has live invoices and cannot be archived","retryable":"never","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["An organization that issued real invoices is kept: its records are fiscal documents."],"reproduce":null,"not_reproducible_because":"Requires an invoice accepted in live mode, which test mode never produces."},{"code":"last_owner","type":"https://api.invox.page/v1/errors/last_owner","status":409,"title":"An organization always keeps at least one active owner","retryable":"after_external_change","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["Give the owner role to another member first, then repeat this change."],"reproduce":"With a single owner, call PUT /v1/members/{user_id} with role `admin` on yourself."},{"code":"scope_not_grantable","type":"https://api.invox.page/v1/errors/scope_not_grantable","status":403,"title":"A permission in the request cannot be granted","retryable":"after_fixing_request","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["A credential never grants a permission it does not hold, and some permissions are for people only.","`rejected_scopes` lists them. Remove them, or ask a person who holds them to make the change."],"reproduce":"With a service-account key, create another service account asking for `members:write`."},{"code":"live_organization_required","type":"https://api.invox.page/v1/errors/live_organization_required","status":400,"title":"Members are managed on the live organization","retryable":"after_fixing_request","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["Memberships live on the live organization and govern its test twin too.","Send the id of the live organization in `X-Organization` (GET /v1/organizations shows both ids)."],"reproduce":"Call PUT /v1/members/{user_id} with `X-Organization` set to a test organization id."},{"code":"service_account_disabled","type":"https://api.invox.page/v1/errors/service_account_disabled","status":409,"title":"The service account is disabled","retryable":"never","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["A disabled service account gets no new keys. Create another service account."],"reproduce":"Disable a service account and then call POST /v1/service_accounts/{id}/keys."},{"code":"key_limit_reached","type":"https://api.invox.page/v1/errors/key_limit_reached","status":409,"title":"The service account already has the maximum number of keys","retryable":"after_external_change","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["Revoke a key that is no longer used (DELETE /v1/service_accounts/{id}/keys/{key_id}), then retry."],"reproduce":"Create keys on one service account until the answer is this error (the limit is in GET /v1)."},{"code":"provider_not_connected","type":"https://api.invox.page/v1/errors/provider_not_connected","status":409,"title":"The issuer has no provider connection","retryable":"after_external_change","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["A test organization is born connected to the simulated provider. A live organization is connected when it is activated for production."],"reproduce":"Call POST /v1/series on a LIVE organization after PUT /v1/issuer."},{"code":"idempotency_key_required","type":"https://api.invox.page/v1/errors/idempotency_key_required","status":400,"title":"This write needs an Idempotency-Key header","retryable":"after_fixing_request","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["Send `Idempotency-Key: <unique value>` (a UUID works). Reuse the same value when you retry the same operation."],"reproduce":"Call POST /v1/invoices without the Idempotency-Key header."},{"code":"idempotency_key_reused","type":"https://api.invox.page/v1/errors/idempotency_key_reused","status":422,"title":"This Idempotency-Key was already used with a different request","retryable":"after_fixing_request","effect":"Nothing new was created. The resource created by the first request is untouched.","next_steps":["To retry the first operation, send exactly the same body.","To do a different operation, use a new Idempotency-Key."],"reproduce":"Send POST /v1/invoices twice with the same Idempotency-Key and a different `total`."},{"code":"rate_limited","type":"https://api.invox.page/v1/errors/rate_limited","status":429,"title":"Too many requests","retryable":"same_request","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["Wait the seconds in the `Retry-After` header, then send the same request again."],"reproduce":null,"not_reproducible_because":"Limits protect the service and are not lowered in test mode; GET /v1 publishes them."},{"code":"wait_limit_reached","type":"https://api.invox.page/v1/errors/wait_limit_reached","status":429,"title":"Too many waiting requests are open with this credential","retryable":"same_request","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["Close a waiting request (`wait=`) or let one finish, then retry after `Retry-After`."],"reproduce":"Open more simultaneous GET /v1/events?wait=30 calls with one credential than GET /v1 allows."},{"code":"test_scenario_not_allowed","type":"https://api.invox.page/v1/errors/test_scenario_not_allowed","status":400,"title":"The Test-Scenario header is only accepted in a test organization served by the simulator","retryable":"after_fixing_request","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["Remove the `Test-Scenario` header, or send the request to the test organization (a `sk_test_…` key).","GET /v1/me tells which environment and which provider this credential reaches."],"reproduce":"Call POST /v1/invoices with `Test-Scenario: rejected` and a credential of a live organization."},{"code":"test_scenario_unknown","type":"https://api.invox.page/v1/errors/test_scenario_unknown","status":400,"title":"The Test-Scenario header names a scenario that does not exist","retryable":"after_fixing_request","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["GET /v1/test/scenarios lists the scenarios, what each one does and how to resolve it."],"reproduce":"Call POST /v1/invoices in a test organization with `Test-Scenario: no-such-scenario`."},{"code":"test_only_route","type":"https://api.invox.page/v1/errors/test_only_route","status":403,"title":"This route only exists in a test organization","retryable":"never","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["Routes under /v1/test act on the simulated provider. Use a `sk_test_…` key."],"reproduce":"Call POST /v1/test/invoices/{id}/resolve with a credential of a live organization."},{"code":"issuer_not_configured","type":"https://api.invox.page/v1/errors/issuer_not_configured","status":409,"title":"The organization has no issuer yet","retryable":"after_external_change","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["Set the fiscal data of the issuer with PUT /v1/issuer, then retry."],"reproduce":"Create an organization and call POST /v1/invoices on its LIVE organization before PUT /v1/issuer."},{"code":"tax_id_already_claimed","type":"https://api.invox.page/v1/errors/tax_id_already_claimed","status":409,"title":"This RUC already issues from another organization","retryable":"never","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["A RUC issues in live mode from one place only. If it is yours, find the organization that holds it; otherwise contact support."],"reproduce":null,"not_reproducible_because":"The lock is taken when an organization is activated for production, which is not part of test mode."},{"code":"series_not_found","type":"https://api.invox.page/v1/errors/series_not_found","status":404,"title":"The series does not exist or is not active for this document type","retryable":"after_fixing_request","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["GET /v1/series lists the series of the organization and the document type of each."],"reproduce":"Call POST /v1/invoices with `series: \"F999\"`."},{"code":"series_already_exists","type":"https://api.invox.page/v1/errors/series_already_exists","status":409,"title":"A series with this code already exists","retryable":"never","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["GET /v1/series lists the existing ones."],"reproduce":"Call POST /v1/series with the code `F001` in a test organization."},{"code":"external_ref_already_used","type":"https://api.invox.page/v1/errors/external_ref_already_used","status":409,"title":"An invoice in force already exists for this external reference","retryable":"never","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["`existing_invoice_id` is the invoice issued for this `external_ref`: read it with GET /v1/invoices/{id}.","One external reference has one invoice in force. Another can be issued only after that one is voided."],"reproduce":"Send POST /v1/invoices twice with the same `external_ref` and different Idempotency-Keys."},{"code":"invoice_not_resolvable","type":"https://api.invox.page/v1/errors/invoice_not_resolvable","status":409,"title":"The invoice is not waiting for a test resolution","retryable":"never","effect":"The invoice was not changed.","next_steps":["Only an invoice issued with a scenario that stays pending can be resolved by hand. GET /v1/invoices/{id} shows its state."],"reproduce":"Call POST /v1/test/invoices/{id}/resolve on an invoice that is already accepted."},{"code":"cursor_invalid","type":"https://api.invox.page/v1/errors/cursor_invalid","status":400,"title":"The `after` cursor is not valid","retryable":"after_fixing_request","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["Use the `next_cursor` of a previous answer, or omit `after` to start from the oldest event."],"reproduce":"Call GET /v1/events?after=not-a-cursor."},{"code":"provider_account_suspended","type":"https://api.invox.page/v1/errors/provider_account_suspended","status":503,"title":"The account with the invoicing provider is suspended","retryable":"same_request","effect":"Nothing was created or changed, and no invoice number was used. No invoice is marked failed or rejected because of the account: what is in process stays in process.","next_steps":["Nothing in the request is wrong. Send the same request again after `Retry-After`.","GET /v1/provider shows the state of the account and since when it is blocked.","Invoices can still be issued: they are taken (202) and sent by themselves when the account recovers."],"reproduce":"In a test organization, call PUT /v1/test/provider with the condition that simulates a suspended account, then call an operation that asks the provider at once (POST /v1/invoices/{id}/correction). GET /v1/provider shows the same code."},{"code":"provider_account_unpaid","type":"https://api.invox.page/v1/errors/provider_account_unpaid","status":503,"title":"The account with the invoicing provider is blocked for lack of payment","retryable":"same_request","effect":"Nothing was created or changed, and no invoice number was used. No invoice is marked failed or rejected because of the account: what is in process stays in process.","next_steps":["Nothing in the request is wrong. Send the same request again after `Retry-After`.","GET /v1/provider shows the state of the account and since when it is blocked.","Invoices can still be issued: they are taken (202) and sent by themselves when the account recovers."],"reproduce":"In a test organization, call PUT /v1/test/provider with the condition that simulates an unpaid account, then call an operation that asks the provider at once (POST /v1/invoices/{id}/correction)."},{"code":"provider_auth_failed","type":"https://api.invox.page/v1/errors/provider_auth_failed","status":503,"title":"The invoicing provider rejected the credential of the account","retryable":"same_request","effect":"Nothing was created or changed, and no invoice number was used. No invoice is marked failed or rejected because of the account: what is in process stays in process.","next_steps":["Nothing in the request is wrong. Send the same request again after `Retry-After`.","GET /v1/provider shows the state of the account. The credential is fixed by whoever operates the account, not by the caller."],"reproduce":"In a test organization, call PUT /v1/test/provider with the condition that simulates a rejected credential, then call an operation that asks the provider at once (POST /v1/invoices/{id}/correction)."},{"code":"provider_config_invalid","type":"https://api.invox.page/v1/errors/provider_config_invalid","status":503,"title":"The connection to the invoicing provider is misconfigured","retryable":"same_request","effect":"Nothing was created or changed, and no invoice number was used. No invoice is marked failed or rejected because of the connection: what is in process stays in process.","next_steps":["Nothing in the request is wrong. Send the same request again after `Retry-After`.","GET /v1/provider shows which connection is affected; GET /v1/readiness lists what is missing and who must do it."],"reproduce":"In a test organization, call PUT /v1/test/provider with the condition that simulates a misconfigured connection, then call an operation that asks the provider at once (POST /v1/invoices/{id}/correction)."},{"code":"test_condition_unknown","type":"https://api.invox.page/v1/errors/test_condition_unknown","status":400,"title":"The condition asked of the simulated provider does not exist","retryable":"after_fixing_request","effect":"The simulated provider was not changed.","next_steps":["GET /v1/test/scenarios lists the conditions the simulated provider can be put in and how each one recovers."],"reproduce":"Call PUT /v1/test/provider in a test organization with the condition `no-such-condition`."},{"code":"not_waiting","type":"https://api.invox.page/v1/errors/not_waiting","status":409,"title":"There is no wait to skip: the invoice is not waiting for anything","retryable":"never","effect":"The invoice was not changed.","next_steps":["Only an invoice or a void that is waiting for its next step can be advanced. GET /v1/invoices/{id} shows whether it is final and its next step."],"reproduce":"Call POST /v1/test/invoices/{id}/advance on a test invoice that is already accepted."},{"code":"invoice_not_voidable","type":"https://api.invox.page/v1/errors/invoice_not_voidable","status":409,"title":"Only an invoice accepted by SUNAT can be voided","retryable":"after_external_change","effect":"No void was created. The invoice was not changed.","next_steps":["GET /v1/invoices/{id} shows the state. An invoice in process can be voided once it is accepted.","A rejected or failed invoice was never in force before SUNAT: there is nothing to void. Correct it or issue another."],"reproduce":"Issue a test invoice with `Test-Scenario: rejected` and call POST /v1/invoices/{id}/void/preview on it."},{"code":"invoice_held","type":"https://api.invox.page/v1/errors/invoice_held","status":409,"title":"The invoice is held: the provider gave an answer the service cannot interpret","retryable":"after_external_change","effect":"Nothing was done. The invoice is still in process and nothing was resent to the provider.","next_steps":["GET /v1/invoices/{id} shows the `held` block: since when and why. The staff of the service was told and releases it once the service understands the answer.","Do not issue another invoice for the same sale: the provider may have it."],"reproduce":"Issue a test invoice with `Test-Scenario: unrecognized_answer` and wait until it is held, then try to correct or void it."},{"code":"void_not_available","type":"https://api.invox.page/v1/errors/void_not_available","status":409,"title":"Voiding is not available for invoices issued through this provider","retryable":"after_external_change","effect":"No void was created or sent. The invoice is still accepted and was not changed.","next_steps":["Voiding through a provider is enabled only once its voids have been proven against its sandbox. GET /v1/invoices/{id} shows the provider of the invoice; `provider` in this answer says which one refused.","If the invoice was reversed by hand at the provider, record it with POST /v1/invoices/{id}/mark_externally_reversed."],"reproduce":null,"not_reproducible_because":"Every provider an invoice can be issued through today, the simulated one included, is enabled for voids. The refusal exists for a provider added later, which starts disabled until its voids are proven."},{"code":"void_in_progress","type":"https://api.invox.page/v1/errors/void_in_progress","status":409,"title":"A void of this invoice is already in progress","retryable":"after_external_change","effect":"No second void was created. The void in progress is untouched.","next_steps":["GET /v1/invoices/{id}/void shows the void in progress, whether it is final and its next step. Wait for its outcome."],"reproduce":"Void a test invoice with `Test-Scenario: void_pending` and, before resolving it, call POST /v1/invoices/{id}/void/preview on the same invoice."},{"code":"void_window_expired","type":"https://api.invox.page/v1/errors/void_window_expired","status":409,"title":"The window to void this invoice has passed","retryable":"never","effect":"No void was created or sent. The invoice is still accepted.","next_steps":["`void_deadline` on the invoice is the last day it could be voided (7 days from its issue date).","If it was reversed by hand at the provider, record it with POST /v1/invoices/{id}/mark_externally_reversed."],"reproduce":"Call POST /v1/invoices/{id}/void/preview on an accepted test invoice with `Test-Scenario: void_out_of_window`."},{"code":"already_voided","type":"https://api.invox.page/v1/errors/already_voided","status":409,"title":"The invoice is already voided","retryable":"never","effect":"No void was created. The invoice was not changed.","next_steps":["Nothing to do: GET /v1/invoices/{id}/void shows the void that was accepted."],"reproduce":"Void a test invoice and, once it is `voided`, call POST /v1/invoices/{id}/void/preview on it again."},{"code":"invoice_externally_reversed","type":"https://api.invox.page/v1/errors/invoice_externally_reversed","status":409,"title":"The invoice was recorded as reversed by hand at the provider","retryable":"never","effect":"Nothing was created or sent. The invoice was not changed.","next_steps":["An invoice marked as externally reversed is not voided or marked again. GET /v1/invoices/{id} shows the note and who recorded it."],"reproduce":"Mark an accepted test invoice with POST /v1/invoices/{id}/mark_externally_reversed, then call POST /v1/invoices/{id}/void/preview on it."},{"code":"preview_token_required","type":"https://api.invox.page/v1/errors/preview_token_required","status":400,"title":"This action needs the token of its preview","retryable":"after_fixing_request","effect":"The action was not performed. Nothing was created, sent or changed.","next_steps":["Ask for the preview of the action first (POST /v1/invoices/{id}/void/preview, GET /v1/invoices/{id}/correction): its answer carries `preview_token`.","Show the preview to the person who approves, then send the action with that `preview_token`."],"reproduce":"Call POST /v1/invoices/{id}/void on an accepted test invoice without `preview_token`."},{"code":"preview_token_invalid","type":"https://api.invox.page/v1/errors/preview_token_invalid","status":409,"title":"The preview token expired or no longer matches what would be done","retryable":"after_fixing_request","effect":"The action was not performed. Nothing was created, sent or changed.","next_steps":["A preview token lasts 10 minutes and is valid only for the exact action that was previewed.","Ask for the preview again, show it to the person who approves, and send the action with the new `preview_token`."],"reproduce":"Call POST /v1/invoices/{id}/void with the `preview_token` of the preview of ANOTHER invoice."},{"code":"invoice_not_correctable","type":"https://api.invox.page/v1/errors/invoice_not_correctable","status":409,"title":"Only a failed or rejected invoice can be corrected","retryable":"never","effect":"The invoice was not changed and no number was used.","next_steps":["GET /v1/invoices/{id} shows the state. An accepted invoice is voided, not corrected; one in process has no verdict yet."],"reproduce":"Call GET /v1/invoices/{id}/correction on an accepted test invoice."},{"code":"correction_proposal_changed","type":"https://api.invox.page/v1/errors/correction_proposal_changed","status":409,"title":"The invoice changed since the correction was proposed","retryable":"after_fixing_request","effect":"The correction was not applied. The invoice was not changed and no number was used.","next_steps":["Ask for the proposal again (GET /v1/invoices/{id}/correction): the number, the date or the state of the document changed meanwhile.","Ask for the proposal again (GET /v1/invoices/{id}/correction): if the provider now holds the document as accepted, it will say `adopt` instead of proposing a correction."],"reproduce":null,"not_reproducible_because":"It needs the invoice to change between the proposal and the correction (another correction, or the provider reporting the document as accepted), which one caller cannot time."},{"code":"file_not_ready","type":"https://api.invox.page/v1/errors/file_not_ready","status":409,"title":"The file is not stored yet","retryable":"same_request","effect":"Nothing was changed. The file is still being fetched or rendered.","next_steps":["GET /v1/invoices/{id}/files lists each file with its state; `delivery` on the invoice says the same.","Send the same request again in a few seconds, or wait for the event `invoice.files_stored`."],"reproduce":"Issue a test invoice with `Test-Scenario: pending` and call GET /v1/invoices/{id}/files/xml before resolving it."},{"code":"file_not_found","type":"https://api.invox.page/v1/errors/file_not_found","status":404,"title":"The invoice has no file of that kind","retryable":"never","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["GET /v1/invoices/{id}/files lists the files this invoice has (`xml`, `cdr`, `pdf`) and the state of each."],"reproduce":"Call GET /v1/invoices/{id}/files/zip on any test invoice."},{"code":"file_not_refetchable","type":"https://api.invox.page/v1/errors/file_not_refetchable","status":409,"title":"This file cannot be asked again from the provider","retryable":"never","effect":"Nothing was changed: the file keeps its state and nothing was asked of the provider.","next_steps":["Only a file the provider serves (`xml`, `cdr`, `void_xml`, `void_cdr`) that `failed` for a reason that asking again can fix is asked again. `reason` in this answer says why this one is not.","The PDF is rendered by this service, not fetched: render it again with POST /v1/invoices/{id}/files/pdf/regenerate.","A stored file is already downloadable: GET /v1/invoices/{id}/files/{kind}."],"reproduce":"Call POST /v1/invoices/{id}/files/xml/refetch on an accepted test invoice whose files are stored."},{"code":"email_recipient_required","type":"https://api.invox.page/v1/errors/email_recipient_required","status":400,"title":"There is nobody to send the email to","retryable":"after_fixing_request","effect":"No email was queued or sent.","next_steps":["The invoice has no customer email: send `to` with at least one address in the request."],"reproduce":"Issue a test invoice without `customer.email` and call POST /v1/invoices/{id}/emails with an empty body."},{"code":"export_too_large","type":"https://api.invox.page/v1/errors/export_too_large","status":400,"title":"The export would exceed the maximum number of rows","retryable":"after_fixing_request","effect":"Nothing was exported.","next_steps":["Narrow the filter (a shorter date range, one series) and export in parts. `max_rows` says the limit; GET /v1 publishes it."],"reproduce":null,"not_reproducible_because":"It needs more invoices than the export limit in one organization; the limit is not lowered in test mode."},{"code":"webhook_endpoint_not_found","type":"https://api.invox.page/v1/errors/webhook_endpoint_not_found","status":404,"title":"The webhook destination does not exist in this organization","retryable":"never","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["GET /v1/webhook_endpoints lists the destinations of this organization. A deleted destination is not found."],"reproduce":"Call GET /v1/webhook_endpoints/00000000-0000-4000-8000-000000000000."},{"code":"webhook_url_not_allowed","type":"https://api.invox.page/v1/errors/webhook_url_not_allowed","status":400,"title":"The URL of the webhook destination is not allowed","retryable":"after_fixing_request","effect":"The destination was not created or changed, and nothing was sent to that URL.","next_steps":["A destination is a public `https://` URL: no credentials in it, no IP address or name that resolves to a private, loopback or link-local address.","To receive events without a public URL, follow them with GET /v1/events?wait=30 instead."],"reproduce":"Call POST /v1/webhook_endpoints with `url: \"https://127.0.0.1/hook\"`."},{"code":"webhook_endpoint_limit_reached","type":"https://api.invox.page/v1/errors/webhook_endpoint_limit_reached","status":409,"title":"The organization already has the maximum number of webhook destinations","retryable":"after_external_change","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["Delete a destination that is no longer used (DELETE /v1/webhook_endpoints/{id}), then retry."],"reproduce":"Create webhook destinations in one test organization until the answer is this error (the limit is in GET /v1)."},{"code":"webhook_endpoint_disabled","type":"https://api.invox.page/v1/errors/webhook_endpoint_disabled","status":409,"title":"The webhook destination is disabled","retryable":"after_external_change","effect":"Nothing was queued for the destination and nothing was sent to it.","next_steps":["GET /v1/webhook_endpoints/{id} says why it is disabled (`disabled_reason`).","Enable it with PATCH /v1/webhook_endpoints/{id} and `enabled: true`, then resend. To check a receiver before enabling it, POST /v1/webhook_endpoints/{id}/test works on a disabled destination."],"reproduce":"Disable a destination with PATCH /v1/webhook_endpoints/{id} and `enabled: false`, then call POST /v1/events/{event_id}/resend with that `endpoint_id`."},{"code":"event_not_found","type":"https://api.invox.page/v1/errors/event_not_found","status":404,"title":"The event does not exist in this organization","retryable":"never","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["GET /v1/events lists the events of this organization, each with its id."],"reproduce":"Call GET /v1/events/00000000-0000-4000-8000-000000000000."},{"code":"invitation_not_found","type":"https://api.invox.page/v1/errors/invitation_not_found","status":404,"title":"The invitation does not exist, was revoked or was already used","retryable":"never","effect":"Nobody was added to any organization.","next_steps":["Ask whoever invited you to send a new invitation (POST /v1/invitations)."],"reproduce":"Call POST /v1/invitations/accept with a person's access token and `token: \"not-a-token\"`."},{"code":"invitation_expired","type":"https://api.invox.page/v1/errors/invitation_expired","status":409,"title":"The invitation expired","retryable":"after_external_change","effect":"Nobody was added to any organization.","next_steps":["Ask an owner or admin to send it again: POST /v1/invitations/{id}/resend issues a new token."],"reproduce":null,"not_reproducible_because":"An invitation expires only with the passage of days, and test mode does not move the clock."},{"code":"invitation_email_mismatch","type":"https://api.invox.page/v1/errors/invitation_email_mismatch","status":403,"title":"The invitation was sent to another email address","retryable":"never","effect":"Nobody was added to any organization. The invitation is still pending.","next_steps":["Sign in with the account whose email received the invitation, or ask for an invitation to this account's email."],"reproduce":"Invite one email address and call POST /v1/invitations/accept with its token, signed in as a person with another email."},{"code":"invitation_resend_limit_reached","type":"https://api.invox.page/v1/errors/invitation_resend_limit_reached","status":409,"title":"This invitation was already sent again the maximum number of times","retryable":"never","effect":"No email was sent and the token was not changed: the invitation is still pending with the token of its last email.","next_steps":["The person can still accept with the last email they received, until `expires_at`.","To start over, revoke it (DELETE /v1/invitations/{id}) and invite the email again (POST /v1/invitations). The limit is published in GET /v1 under `limits`."],"reproduce":"Invite an email (POST /v1/invitations) and call POST /v1/invitations/{id}/resend on it one time more than `limits.max_resends_per_invitation` in GET /v1."},{"code":"email_not_verified","type":"https://api.invox.page/v1/errors/email_not_verified","status":403,"title":"The email of this person is not verified","retryable":"after_external_change","effect":"Nobody was added to any organization. The invitation is still pending.","next_steps":["Verify the email with the identity provider (the sign-in page offers it), then accept the invitation again."],"reproduce":null,"not_reproducible_because":"It depends on the state of a real person's account at the identity provider, which test mode does not simulate."},{"code":"already_member","type":"https://api.invox.page/v1/errors/already_member","status":409,"title":"This person is already a member of the organization","retryable":"never","effect":"No invitation was created and no membership was changed.","next_steps":["To change the role of a member use PUT /v1/members/{user_id}."],"reproduce":"Call POST /v1/invitations with the email of a person who is already a member of the organization."},{"code":"nothing_held","type":"https://api.invox.page/v1/errors/nothing_held","status":404,"title":"Nothing is held under that signature or those ids","retryable":"never","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["GET /v1/staff/held lists what is held, grouped by signature."],"reproduce":"Call POST /v1/staff/held/release with a signature that nothing carries."},{"code":"staff_required","type":"https://api.invox.page/v1/errors/staff_required","status":403,"title":"This operation is reserved to the staff of the service","retryable":"never","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["GET /v1/readiness lists what is missing for production and who must do each thing. Contact support for this step."],"reproduce":"Call the production activation route with a person's access token that does not belong to the staff."},{"code":"issuer_tax_id_locked","type":"https://api.invox.page/v1/errors/issuer_tax_id_locked","status":409,"title":"The RUC of an issuer activated for production cannot be changed","retryable":"never","effect":"The issuer was not changed.","next_steps":["The RUC is locked to this issuer since it was activated. Another RUC issues from another organization."],"reproduce":null,"not_reproducible_because":"The lock is taken when an organization is activated for production, which is not part of test mode."},{"code":"production_already_active","type":"https://api.invox.page/v1/errors/production_already_active","status":409,"title":"The organization is already activated for production","retryable":"never","effect":"Nothing was changed: the existing activation stands.","next_steps":["GET /v1/provider shows the production connection; GET /v1/readiness shows what, if anything, is still missing."],"reproduce":null,"not_reproducible_because":"Activation acts on a live organization and is done by the staff of the service; test mode has no production connection."},{"code":"internal_error","type":"https://api.invox.page/v1/errors/internal_error","status":500,"title":"The service failed","retryable":"same_request","effect":"Unknown from this answer alone. Retrying with the same Idempotency-Key is safe: it cannot create a duplicate.","next_steps":["Retry the same request with the same Idempotency-Key.","If it keeps failing, report the `request_id`."],"reproduce":null,"not_reproducible_because":"It is a defect of the service, not a scenario."},{"code":"service_unavailable","type":"https://api.invox.page/v1/errors/service_unavailable","status":503,"title":"The service cannot answer right now","retryable":"same_request","effect":"Nothing was created or changed, and no invoice number was used.","next_steps":["Wait the seconds in `Retry-After` and send the same request again."],"reproduce":null,"not_reproducible_because":"It reflects a real outage of the database or the platform."}],"invoice_status_reasons":{"fiscal_rejected":{"meaning":"SUNAT rejected the content of the invoice. Its number was not used before SUNAT.","what_to_do":"Read `sunat` for SUNAT's code and text, fix the data and issue the invoice again.","reproduce":"Issue a test invoice with `Test-Scenario: rejected`."},"provider_validation_failed":{"meaning":"The provider refused the document before sending it to SUNAT.","what_to_do":"Fix what the provider points at and issue the invoice again.","reproduce":null},"issue_date_expired":{"meaning":"The legal window to send the document passed before it could be sent (factura: 3 days; boleta: 7).","what_to_do":"Issue it again with a current issue date.","reproduce":"Issue a test invoice with `Test-Scenario: pending` and an `issue_date` more than 3 days in the past is refused at once; the code appears when a delay outlasts the window."},"number_already_registered":{"meaning":"SUNAT holds this number, for this issuer and series, with other data (its code 1033). It was asked again and did not change. The number was never changed automatically.","what_to_do":"GET /v1/invoices/{id}/correction proposes the next number of the series (or adopts the document, if the provider turns out to hold yours as accepted); POST it with its preview token.","reproduce":"Issue a test invoice with `Test-Scenario: sunat_1033` and call POST /v1/test/invoices/{id}/advance until it settles."},"test_scenario_expired":{"meaning":"A test invoice waited 24 hours for a manual resolution and was closed.","what_to_do":"Nothing: it was a test. Issue another and resolve it with POST /v1/test/invoices/{id}/resolve.","reproduce":"Issue a test invoice with `Test-Scenario: pending` and do not resolve it for 24 hours."}},"void_status_reasons":{"fiscal_rejected":{"meaning":"SUNAT rejected the void. The invoice is still accepted and in force.","what_to_do":"Read `sunat` on the void for SUNAT's code and text. A new void can be requested once the cause is fixed.","reproduce":"Void a test invoice with `Test-Scenario: void_rejected`."},"void_window_expired":{"meaning":"The window to void the invoice passed before the void could be sent (7 days from its issue date).","what_to_do":"If it was reversed by hand at the provider, record it with POST /v1/invoices/{id}/mark_externally_reversed.","reproduce":"Void a test invoice with `Test-Scenario: void_out_of_window`."},"test_scenario_expired":{"meaning":"A test void waited 24 hours for a manual resolution and was closed. The invoice is still accepted.","what_to_do":"Nothing: it was a test. Request another void and resolve it by hand.","reproduce":"Void a test invoice with `Test-Scenario: void_pending` and do not resolve it for 24 hours."}}}