Errores
Toda respuesta de error es application/problem+json (RFC 9457). Este ejemplo es la respuesta a una solicitud con Accept-Language: es:
{ "type": "https://flashpi.com.ec/docs/errors/validation_failed", "title": "Error de validación", "status": 422, "detail": "Uno o más campos no son válidos. Revisa errors para ver el detalle.", "instance": "/v1/invoices", "code": "validation_failed", "errors": [ { "field": "customer.id", "code": "invalid_check_digit", "message": "El dígito verificador de este número de identificación es incorrecto." }, { "field": "items[0].quantity", "code": "invalid_decimal", "message": "Este campo debe ser un número decimal escrito como texto con punto, con máximo 6 decimales." } ], "requestId": "01a1412b-9c03-7e55-b1a8-27f4d6e0c913"}| Miembro | Descripción |
|---|---|
code |
Un identificador estable en inglés, el mismo en todos los idiomas. Decide según él, nunca según type ni según los textos. |
type |
La página del código (abajo), en el idioma de la respuesta: https://flashpi.com.ec/docs/errors/<code> en español, https://flashpi.com.ec/docs/en/errors/<code> en inglés. Cambia con el idioma, así que no decidas según él. |
title, detail |
Un resumen corto del problema y una explicación de este caso. |
status |
El estado HTTP, repetido. |
instance |
La ruta de la solicitud. |
errors[] |
Los errores de campo (vacío cuando no hay), cada uno con la ruta del campo (field), su code y su message. |
requestId |
El ID de la solicitud, también en el encabezado x-request-id de toda respuesta. |
Algunos errores agregan miembros propios, como limit y resetsAt en los límites diarios, expectedTotal y computedTotal en total_mismatch, o documentId en una Idempotency-Key que ya creó un comprobante.
title, detail, errors[].message y los textos de los comprobantes (sriMessages, failure) están en inglés por defecto, y en español cuando la entrada de Accept-Language con la prioridad (q) más alta es es o es- con una región, como es-EC. Content-Language indica qué idioma se usó. El type también sigue el idioma: apunta a la página en inglés del código (/docs/en/errors/<code>) o a la página en español (/docs/errors/<code>). Los códigos nunca cambian con el idioma, así que tu código debe decidir solo según code y errors[].code.
curl https://api.flashpi.com.ec/v1/documents/01a1412b-ae38-7c39-8c71-16d2b5dfc472 \ -H "Authorization: Bearer $FLASHPI_API_KEY" \ -H "Accept-Language: es"Las respuestas del SRI nunca se reenvían tal cual: Flashpi las traduce a sus propios códigos y textos.
ID de solicitud y de correlación
Sección titulada «ID de solicitud y de correlación»- Toda respuesta trae
x-request-id, un UUIDv7 que genera Flashpi. Es elrequestIdde los errores y aparece en los request logs de la consola. Inclúyelo cuando escribas a soporte. - Puedes enviar
X-Correlation-Id(de 1 a 128 letras, dígitos y-_.:/+=) para relacionar una solicitud con tus propios registros, como tu número de pedido. Flashpi lo devuelve en el mismo encabezado y lo registra junto al ID de la solicitud. Un valor no válido recibe400invalid_correlation_id.
Códigos
Sección titulada «Códigos»Cada código tiene una página en la URL de su type, en español y en inglés, con qué hacer, si conviene reintentar y sus textos en ambos idiomas. La lista sale del catálogo de errores de Flashpi, así que está completa. La mayoría de los códigos vienen de la API de facturación; también se listan los propios de la consola, porque sus respuestas también apuntan a estas páginas.
API de facturación
| HTTP | Código | Título |
|---|---|---|
| 400 | bad_request | Solicitud incorrecta |
| 400 | malformed_json | JSON mal formado |
| 400 | invalid_correlation_id | ID de correlación no válido |
| 400 | invalid_idempotency_key | Clave de idempotencia no válida |
| 401 | authentication_required | Autenticación requerida |
| 401 | invalid_api_key | API key no válida |
| 403 | key_scope_mismatch | Alcance de la API key insuficiente |
| 403 | key_read_only | API key de solo lectura |
| 403 | ip_not_allowed | Dirección IP no permitida |
| 403 | sandbox_not_enabled | Sandbox no habilitado |
| 403 | account_suspended | Cuenta suspendida |
| 404 | not_found | No encontrado |
| 409 | conflict | Conflicto |
| 409 | idempotency_key_in_progress | Solicitud en curso |
| 409 | issuer_already_exists | El emisor ya existe |
| 409 | establishment_already_exists | El establecimiento ya existe |
| 409 | emission_point_already_exists | El punto de emisión ya existe |
| 409 | resource_in_use | Recurso en uso |
| 409 | issuer_onboarding_not_ready | Alta aún no lista |
| 409 | issuer_onboarding_expired | Alta vencida |
| 409 | issuer_onboarding_completed | Alta ya completada |
| 409 | issuer_onboarding_rejected | Certificado rechazado |
| 409 | sequential_already_used | Secuencial ya utilizado |
| 409 | sequentials_exhausted | Secuenciales agotados |
| 409 | document_not_authorized | Comprobante no autorizado |
| 409 | ride_not_available | RIDE no disponible |
| 409 | email_recipient_missing | Sin destinatario de correo |
| 409 | email_already_queued | Correo ya en cola |
| 409 | email_sending_paused | Correos de comprobantes pausados |
| 409 | test_recipient_not_allowed | Destinatario de prueba no permitido |
| 409 | webhook_endpoint_disabled | Endpoint de webhooks deshabilitado |
| 409 | webhook_endpoint_already_verified | Endpoint de webhooks ya verificado |
| 409 | webhook_endpoint_not_verified | Endpoint de webhooks no verificado |
| 409 | webhook_delivery_in_progress | Entrega de webhook en curso |
| 413 | payload_too_large | Contenido demasiado grande |
| 415 | unsupported_media_type | Tipo de contenido no soportado |
| 422 | validation_failed | Error de validación |
| 422 | idempotency_key_reused | Clave de idempotencia reutilizada |
| 422 | total_mismatch | El total no coincide |
| 422 | document_schema_invalid | El comprobante no cumple el esquema del SRI |
| 422 | document_too_large | Comprobante demasiado grande |
| 429 | email_resend_limit_reached | Límite de reenvíos alcanzado |
| 429 | account_email_limit_reached | Límite diario de correos alcanzado |
| 429 | platform_email_limit_reached | Límite diario de correos de Flashpi alcanzado |
| 429 | demo_issuer_quota_exceeded | Cuota del emisor de demostración agotada |
| 500 | internal_error | Error interno del servidor |
| 503 | demo_issuer_unavailable | Emisor de demostración no disponible |
Consola
| HTTP | Código | Título |
|---|---|---|
| 400 | invalid_token | Enlace no válido |
| 401 | invalid_credentials | Credenciales no válidas |
| 403 | forbidden | Acceso denegado |
| 403 | email_not_verified | Correo no verificado |
| 403 | email_verification_session_mismatch | Abre el enlace donde lo solicitaste |
| 403 | csrf_check_failed | Solicitud rechazada |
| 403 | reauthentication_required | Confirma tu identidad |
| 403 | mfa_reauthentication_required | Confirma con tu app de autenticación |
| 403 | mfa_required | Verificación en dos pasos requerida |
| 403 | mfa_enrollment_required | Configura la verificación en dos pasos |
| 403 | invitation_email_mismatch | Invitación para otro correo |
| 409 | email_already_verified | Correo ya verificado |
| 409 | password_not_set | No tienes contraseña |
| 409 | legal_acceptance_required | Acepta los documentos legales |
| 409 | mfa_not_enabled | La verificación en dos pasos no está activada |
| 409 | mfa_enrollment_not_started | No hay una configuración en curso |
| 409 | mfa_disable_not_allowed | La verificación en dos pasos es obligatoria |
| 409 | last_owner | Último propietario |
| 409 | already_member | Ya es miembro |
| 409 | invitation_requires_login | Inicia sesión para aceptar |
| 409 | live_key_requirements_not_met | Acceso de producción no habilitado |
| 429 | too_many_attempts | Demasiados intentos |
| 503 | google_sign_in_unavailable | Inicio con Google no disponible |
Reservados (ningún endpoint los devuelve hoy)
| HTTP | Código | Título |
|---|---|---|
| 405 | method_not_allowed | Método no permitido |
| 406 | not_acceptable | No aceptable |
| 429 | rate_limited | Demasiadas solicitudes |
| 503 | service_unavailable | Servicio no disponible |
Todo 429 trae un encabezado Retry-After con los segundos que debes esperar.
Códigos de error de campo
Sección titulada «Códigos de error de campo»El code de cada elemento de errors[], con el message que trae en español (con Accept-Language: es; en inglés por defecto). {nombre} marca un valor de cada caso, como la cantidad de decimales que admite un campo.
| Código | Mensaje (errors[].message) |
|---|---|
required | Este campo es obligatorio. |
unknown_field | Este campo no está permitido. |
invalid_type | Este campo tiene un tipo de dato incorrecto. |
invalid_format | Este campo tiene un formato no válido. |
invalid_option | Este campo debe ser uno de los valores permitidos. |
too_short | Este campo es demasiado corto. |
too_long | Este campo es demasiado largo. |
out_of_range | Este campo está fuera del rango permitido. |
invalid_value | Este campo tiene un valor no válido. |
unsupported_character | Este campo contiene el carácter {character}, que los comprobantes del SRI no admiten. |
not_found | No existe un recurso con este ID. |
invalid_decimal | Este campo debe ser un número decimal escrito como texto con punto, con máximo {decimals} decimales. |
invalid_identification | Este no es un número de identificación válido del tipo {idType}. |
invalid_check_digit | El dígito verificador de este número de identificación es incorrecto. |
final_consumer_not_allowed | Un consumidor final no puede ser la contraparte de este tipo de comprobante; identifícalo con RUC, cédula, pasaporte o identificación del exterior. |
not_in_force | Este valor no está vigente el {date}. |
too_many_additional_fields | Un comprobante admite máximo {max} campos adicionales, y {legends} de ellos los ocupan las leyendas que agrega Flashpi. |
reserved_name | Este nombre está reservado para una leyenda que Flashpi agrega automáticamente. |
amount_mismatch | Estos valores deben sumar {expected}; suman {actual}. |
future_date | La fecha no puede ser posterior a hoy en Ecuador ({today}). |
date_too_early | La fecha debe ser igual o posterior al {date}. |
date_too_late | La fecha debe ser igual o anterior al {date}. |
discount_exceeds_amount | El descuento es mayor que cantidad × precio unitario. |
duplicate | Este valor solo puede aparecer una vez. |
vat_required | Cada línea necesita exactamente un impuesto IVA (usa la tarifa "0", "exempt" o "not_subject" cuando no aplique IVA). |
unsupported_tax | Este tipo de comprobante no admite este impuesto. |
rate_mismatch | El porcentaje de este código es {rate}. |
incompatible_issuer_profile | El campo {field} del emisor no se puede escribir en este tipo de comprobante, que acepta máximo {max} caracteres. |
url_not_allowed | Las URL de webhooks deben ser URL HTTPS públicas y sin credenciales ({reason}). |
incorrect_password | La contraseña es incorrecta. |
invalid_code | El código es incorrecto o ya venció. |
demo_issuer_test_only | El emisor de demostración solo puede usarse con API keys de prueba (fp_test_). |
demo_issuer_sequential_not_allowed | El emisor de demostración compartido asigna el secuencial; no envíes sequential. |
ruc_mismatch | Este RUC no coincide con el certificado, que respalda {expected}. Un certificado que solo tiene cédula respalda los RUC cuyos primeros 10 dígitos son esa cédula. |