Errors
Every error answer is application/problem+json (RFC 9457):
{ "type": "https://flashpi.com.ec/docs/en/errors/validation_failed", "title": "Validation failed", "status": 422, "detail": "One or more fields are invalid. See errors for details.", "instance": "/v1/invoices", "code": "validation_failed", "errors": [ { "field": "customer.id", "code": "invalid_check_digit", "message": "The check digit of this identification number is wrong." }, { "field": "items[0].quantity", "code": "invalid_decimal", "message": "This field must be a decimal number written as a string with a dot, with at most 6 decimals." } ], "requestId": "01a1412b-9c03-7e55-b1a8-27f4d6e0c913"}| Member | Description |
|---|---|
code |
A stable English slug, the same in every language. Branch on it, never on type or the texts. |
type |
The page of the code (below), in the language of the answer: https://flashpi.com.ec/docs/en/errors/<code> in English, https://flashpi.com.ec/docs/errors/<code> in Spanish. It changes with the language, so do not branch on it. |
title, detail |
A short summary of the problem and an explanation of this occurrence. |
status |
The HTTP status, repeated. |
instance |
The path of the request. |
errors[] |
The field errors (empty when there are none), each with its field path, code and message. |
requestId |
The request’s ID, also in the x-request-id header of every answer. |
Some errors add members of their own, such as limit and resetsAt on daily limits, expectedTotal and computedTotal on total_mismatch, or documentId on an Idempotency-Key that already created a document.
Language
Section titled “Language”title, detail, errors[].message and the texts in documents (sriMessages, failure) are in English by default, and in Spanish when the Accept-Language entry with the highest priority (q) is es or es- plus a region, such as es-EC. Content-Language says which language was used. The type follows the language too: it points at the English page of the code (/docs/en/errors/<code>) or at the Spanish one (/docs/errors/<code>). Codes never change with the language, so your code should branch on code and errors[].code only.
curl https://api.flashpi.com.ec/v1/documents/01a1412b-ae38-7c39-8c71-16d2b5dfc472 \ -H "Authorization: Bearer $FLASHPI_API_KEY" \ -H "Accept-Language: es"The SRI’s answers are never passed through as they are: Flashpi maps them to its own codes and texts.
Request and correlation IDs
Section titled “Request and correlation IDs”- Every answer carries
x-request-id, a UUIDv7 that Flashpi generates. It is therequestIdof errors and appears in the console’s request logs. Include it when you contact support. - You may send
X-Correlation-Id(1 to 128 letters, digits and-_.:/+=) to tie a request to your own records, such as your order number. Flashpi echoes it back in the same header and logs it next to the request ID. An invalid value gets400invalid_correlation_id.
Every code has a page at the URL of its type, in English and in Spanish, with what to do about it, whether to retry and its texts in both languages. The list comes from Flashpi’s error catalog, so it is complete. Most codes come from the invoicing API; the console’s own codes are listed too, because its answers point at these pages as well.
Invoicing API
| HTTP | Code | Title |
|---|---|---|
| 400 | bad_request | Bad request |
| 400 | malformed_json | Malformed JSON |
| 400 | invalid_correlation_id | Invalid correlation ID |
| 400 | invalid_idempotency_key | Invalid idempotency key |
| 401 | authentication_required | Authentication required |
| 401 | invalid_api_key | Invalid API key |
| 403 | key_scope_mismatch | API key scope mismatch |
| 403 | key_read_only | Read-only API key |
| 403 | ip_not_allowed | IP address not allowed |
| 403 | sandbox_not_enabled | Sandbox not enabled |
| 403 | account_suspended | Account suspended |
| 404 | not_found | Not found |
| 409 | conflict | Conflict |
| 409 | idempotency_key_in_progress | Request in progress |
| 409 | issuer_already_exists | Issuer already exists |
| 409 | establishment_already_exists | Establishment already exists |
| 409 | emission_point_already_exists | Emission point already exists |
| 409 | resource_in_use | Resource in use |
| 409 | issuer_onboarding_not_ready | Onboarding not ready |
| 409 | issuer_onboarding_expired | Onboarding expired |
| 409 | issuer_onboarding_completed | Onboarding already completed |
| 409 | issuer_onboarding_rejected | Certificate rejected |
| 409 | sequential_already_used | Sequential already used |
| 409 | sequentials_exhausted | Sequentials exhausted |
| 409 | document_not_authorized | Document not authorized |
| 409 | ride_not_available | RIDE not available |
| 409 | email_recipient_missing | No email recipient |
| 409 | email_already_queued | Email already queued |
| 409 | email_sending_paused | Document emails paused |
| 409 | test_recipient_not_allowed | Test email recipient not allowed |
| 409 | webhook_endpoint_disabled | Webhook endpoint disabled |
| 409 | webhook_endpoint_already_verified | Webhook endpoint already verified |
| 409 | webhook_endpoint_not_verified | Webhook endpoint not verified |
| 409 | webhook_delivery_in_progress | Webhook delivery in progress |
| 413 | payload_too_large | Payload too large |
| 415 | unsupported_media_type | Unsupported media type |
| 422 | validation_failed | Validation failed |
| 422 | idempotency_key_reused | Idempotency key reused |
| 422 | total_mismatch | Total mismatch |
| 422 | document_schema_invalid | Document does not match the SRI schema |
| 422 | document_too_large | Document too large |
| 429 | email_resend_limit_reached | Resend limit reached |
| 429 | account_email_limit_reached | Daily email limit reached |
| 429 | platform_email_limit_reached | Flashpi's daily email limit reached |
| 429 | demo_issuer_quota_exceeded | Demo issuer quota exceeded |
| 500 | internal_error | Internal server error |
| 503 | demo_issuer_unavailable | Demo issuer unavailable |
Console
| HTTP | Code | Title |
|---|---|---|
| 400 | invalid_token | Invalid link |
| 401 | invalid_credentials | Invalid credentials |
| 403 | forbidden | Forbidden |
| 403 | email_not_verified | Email not verified |
| 403 | email_verification_session_mismatch | Open the link where you asked for it |
| 403 | csrf_check_failed | Request refused |
| 403 | reauthentication_required | Confirm your identity |
| 403 | mfa_reauthentication_required | Confirm with your authenticator |
| 403 | mfa_required | Two-factor authentication required |
| 403 | mfa_enrollment_required | Set up two-factor authentication |
| 403 | invitation_email_mismatch | Invitation for another email |
| 409 | email_already_verified | Email already verified |
| 409 | password_not_set | No password set |
| 409 | legal_acceptance_required | Accept the legal documents |
| 409 | mfa_not_enabled | Two-factor authentication is not enabled |
| 409 | mfa_enrollment_not_started | No setup in progress |
| 409 | mfa_disable_not_allowed | Two-factor authentication is required |
| 409 | last_owner | Last owner |
| 409 | already_member | Already a member |
| 409 | invitation_requires_login | Log in to accept |
| 409 | live_key_requirements_not_met | Live access not ready |
| 429 | too_many_attempts | Too many attempts |
| 503 | google_sign_in_unavailable | Google sign-in unavailable |
Reserved (no endpoint returns them today)
| HTTP | Code | Title |
|---|---|---|
| 405 | method_not_allowed | Method not allowed |
| 406 | not_acceptable | Not acceptable |
| 429 | rate_limited | Too many requests |
| 503 | service_unavailable | Service unavailable |
Every 429 carries a Retry-After header with the seconds to wait.
Field error codes
Section titled “Field error codes”The code of each item of errors[], with the message it carries in English (in Spanish with Accept-Language: es). {name} marks a value of each occurrence, such as the number of decimals a field allows.
| Code | Message (errors[].message) |
|---|---|
required | This field is required. |
unknown_field | This field is not allowed. |
invalid_type | This field has the wrong type. |
invalid_format | This field has an invalid format. |
invalid_option | This field must be one of the allowed values. |
too_short | This field is too short. |
too_long | This field is too long. |
out_of_range | This field is out of the allowed range. |
invalid_value | This field has an invalid value. |
unsupported_character | This field contains the character {character}, which SRI documents cannot carry. |
not_found | No resource with this ID exists. |
invalid_decimal | This field must be a decimal number written as a string with a dot, with at most {decimals} decimals. |
invalid_identification | This is not a valid identification number of type {idType}. |
invalid_check_digit | The check digit of this identification number is wrong. |
final_consumer_not_allowed | A final consumer cannot be the counterparty of this document type; identify it with a RUC, cédula, passport or foreign ID. |
not_in_force | This value is not valid on {date}. |
too_many_additional_fields | A document carries at most {max} additional fields, and {legends} of them are taken by the legends Flashpi adds. |
reserved_name | This name is reserved for a legend Flashpi adds automatically. |
amount_mismatch | These amounts must add up to {expected}; they add up to {actual}. |
future_date | The date cannot be later than today in Ecuador ({today}). |
date_too_early | The date must be on or after {date}. |
date_too_late | The date must be on or before {date}. |
discount_exceeds_amount | The discount is larger than quantity × unit price. |
duplicate | This value can appear only once. |
vat_required | Each line needs exactly one VAT tax (use rate "0", "exempt" or "not_subject" when no VAT applies). |
unsupported_tax | This document type does not accept this tax. |
rate_mismatch | The percentage of this code is {rate}. |
incompatible_issuer_profile | The issuer's {field} cannot be written in this document type, which accepts at most {max} characters. |
url_not_allowed | Webhook URLs must be public HTTPS URLs without credentials ({reason}). |
incorrect_password | The password is incorrect. |
invalid_code | The code is incorrect or has expired. |
demo_issuer_test_only | The demo issuer can only be used with test (fp_test_) API keys. |
demo_issuer_sequential_not_allowed | The shared demo issuer assigns the sequential itself; leave out sequential. |
ruc_mismatch | This RUC does not match the certificate, which supports {expected}. A certificate with only a cédula supports the RUCs whose first 10 digits are that cédula. |