Errors
Embolcall d'error normalitzat, catàleg de type i code amb àncores estables, i estratègia de reintents.
Tota resposta d'error de l'API pública usa un embolcall JSON
consistent. L'estat HTTP indica la categoria general; el camp type
desambigua i el camp code apunta a la causa específica.
Embolcall
{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "El campo client_id es obligatorio.",
"param": "client_id",
"request_id": "req_01HKQS5N8VR7QXJ9K3T6BWPMZA",
"doc_url": "https://docs.factuarea.com/guides/errors#parameter_invalid"
}
}Camps:
type— categoria general de l'error. Estable i enumerada (llista a sota).code— causa específica. Estable i enumerada.subcode— opcional. Present en algunes respostes409 conflict_error/resource_already_existsper assenyalar la clau duplicada exacta — p. ex.subcode: "tax_id_already_exists".message— text per a persones en castellà. No es garanteix estable entre versions; útil per a logging i visualització.param— opcional, present en errors de validació. Apunta al camp problemàtic.doc_url— opcional. Enllaç a aquesta guia amb àncora alcodeespecífic (#{code}).request_id— identificador únic de la petició (req_<ULID>). Inclou-lo sempre quan contactis amb suport. També es retorna al header de respostaX-Request-Id.
L'objecte error sempre porta type, code i message; la resta
de camps són presents quan és rellevant.
Tipus d'error
| type | HTTP | Descripció |
|---|---|---|
invalid_request_error | 400 o 422 | Payload malformat, paràmetres absents/invàlids o fallada de validació de negoci. |
authentication_error | 401 | L'API key falta, és invàlida, està revocada, ha expirat o la IP no és a la llista d'accés. |
authorization_error | 403 | La key és vàlida però el scope no cobreix l'endpoint. |
permission_error | 403 | El pla/add-on no dona accés a la funcionalitat. |
not_found_error | 404 | El recurs sol·licitat no existeix o no pertany a l'empresa de la key. |
conflict_error | 409 | Conflicte de creació, lock d'idempotència o recurs duplicat (p. ex. un tax_id ja registrat). |
idempotency_error | 409 | Reutilització d'Idempotency-Key amb un payload diferent. |
rate_limit_error | 429 | Superada la quota per minut o mensual, o massa fallades d'autenticació. |
api_error | 500 | Error inesperat del backend. Els reintents poden ajudar; reporta a suport amb el request_id. |
service_unavailable_error | 503 | API pública deshabilitada via kill-switch, o caiguda d'una dependència (Stripe, mailer). |
Les violacions de regles de negoci (transició d'estat invàlida, una acció no
permesa en l'estat actual del document) responen 422 amb
type: invalid_request_error i code: invalid_status_transition —
no 409. 409 conflict_error es reserva per a creació duplicada,
conflictes d'idempotència i locks de concurrència.
Catàleg de codes
L'àncora de cada encapçalament H3 coincideix exactament amb el valor del camp
code de l'embolcall. El doc_url que retorna l'API resol a la secció
específica. La llista de sota cobreix els codes que trobaràs a la pràctica;
la referència OpenAPI en viu documenta els codes exactes per endpoint.
invalid_request_error
parameter_invalid
Un paràmetre de la petició falta o és invàlid. param apunta al
camp problemàtic (p. ex. client_id, lines[0].quantity).
parameter_invalid_format
El format d'un valor és incorrecte per a la seva semàntica (regex, longitud, codificació, un UUID malformat, una data fora de format).
parameter_invalid_range
Un valor numèric o de data està fora del rang permès (p. ex. limit
fora d'1..100).
parameter_invalid_cursor
El cursor starting_after / ending_before no és un id de recurs
vàlid. Consulta Paginació.
parameter_unknown
El body conté un camp no documentat (en endpoints estrictes).
invalid_param_format
Va fallar una restricció de format en un camp tipat — p. ex. el header
Idempotency-Key o el header Factuarea-Version està malformat.
invalid_param_value
El valor no compleix una restricció (enum, format, regla semàntica).
invalid_period
El període de report sol·licitat és invàlid (p. ex. un trimestre/any que no existeix).
invalid_status_transition
La transició sol·licitada està prohibida per la màquina d'estats del document
(p. ex. enviar una factura que no està en un estat enviable). Les violacions
de regles de negoci com aquesta són 422, no 409.
invoice_already_paid
mark-paid sobre una factura ja pagada.
quote_already_accepted
Acció que entra en conflicte amb un pressupost ja acceptat.
business_rule_violation
Una invariant de domini va bloquejar l'operació. El subcode identifica la
regla i param el camp infractor. El fa servir el ledger de pagaments
(Registrar pagaments):
payment_exceeds_pending_amount(param: "amount") — l'import del pagament és més gran que el saldo pendent de la factura. S'aplica tant aPOST /v1/invoices/{id}/paymentscom aPOST /v1/purchase_invoices/{id}/payments.invalid_payment_date(param: "paid_on") — la data de pagament cau fora de la finestra permesadata_emissió … avui(factures de compra).purchase_invoice_not_payable(param: "status") — la factura de compra està cancel·lada i ja no admet pagaments.
{
"error": {
"type": "invalid_request_error",
"code": "business_rule_violation",
"subcode": "payment_exceeds_pending_amount",
"message": "El importe del pago (1.500,00 €) supera el importe pendiente de la factura (710,00 €).",
"param": "amount",
"doc_url": "https://docs.factuarea.com/guides/errors#business_rule_violation",
"request_id": "req_..."
}
}unsupported_format
El format d'exportació/report sol·licitat no està suportat.
insufficient_data_for_report
No hi ha prou dades per generar el report d'impostos sol·licitat.
signature_payload_too_large
La imatge de signatura de l'albarà supera la mida màxima.
authentication_error
missing_api_key
No hi ha header d'autenticació present (Authorization: Bearer o
X-API-Key).
invalid_api_key
La key no existeix o el secret no coincideix amb el hash emmagatzemat.
api_key_revoked
La key va ser revocada. Crea'n una de nova al dashboard.
too_many_auth_failures
S'han limitat fallades d'autenticació repetides des del teu client. Espera (back off) i verifica les teves credencials.
authorization_error
insufficient_scope
La key no té el scope que requereix l'endpoint. Consulta el catàleg a Autenticació › Scopes.
permission_error
feature_not_available_in_plan
El pla actual no inclou el mòdul requerit (p. ex.
recurring_invoices).
addon_not_active
L'add-on developer_api està inactiu o fora del seu període de gràcia.
not_found_error
resource_not_found
El recurs no existeix o no pertany a la teva empresa.
tax_report_not_found
El report d'impostos sol·licitat no existeix.
conflict_error
resource_already_exists
Intent de crear un duplicat (p. ex. un tax_id ja registrat). El
subcode (p. ex. tax_id_already_exists) assenyala la clau duplicada.
resource_conflict
L'operació entra en conflicte amb l'estat actual del recurs (p. ex. una modificació concurrent).
max_api_keys_exceeded
L'empresa ha assolit el seu nombre màxim d'API keys actives.
idempotency_error
idempotency_key_reused
Mateix Idempotency-Key, body de petició diferent. Usa una key nova. Consulta
Idempotència.
rate_limit_error
rate_limit_exceeded
Vas superar la quota per minut o mensual del teu tier. El header
Retry-After indica els segons a esperar. Consulta
Límits de peticions.
api_error
internal_error
Error inesperat. Ja està capturat per la nostra banda, però comparteix el request_id
amb suport.
service_unavailable_error
service_unavailable
L'API pública no està disponible temporalment — deshabilitada globalment via kill-switch, en una finestra de manteniment, o una dependència (base de dades, mailer, Stripe) no està sana. Reintenta després d'un back-off curt.
Errors tipats amb el SDK oficial
Els SDKs de TypeScript i PHP mapegen aquest embolcall a una jerarquia
d'excepcions tipada, així ramifiques segons una classe (i llegeixes code, type,
param, request_id) en lloc de parsejar JSON. La teva API key mai no
s'inclou en cap excepció.
import {
FactuareaError,
ValidationError,
RateLimitError,
} from "@factuarea/sdk";
try {
await factuarea.invoices.create(body);
} catch (error) {
if (error instanceof ValidationError) {
console.error(error.fields); // { client_id: ["obligatorio"], … }
} else if (error instanceof RateLimitError) {
console.error(error.retryAfter); // seconds to wait
} else if (error instanceof FactuareaError) {
console.error(error.code, error.type, error.requestId);
}
}La jerarquia també exporta AuthenticationError, NotFoundError,
ConflictError, ServerError i ConnectionError.
use Factuarea\Sdk\Models\Errors\ErrorThrowable;
try {
$factuarea->invoices->publicApiV1InvoicesCreate($body);
} catch (ErrorThrowable $e) {
$error = $e->container->error;
echo $error->type->value; // e.g. "invalid_request_error"
echo $error->code; // e.g. "parameter_invalid"
echo $error->param; // e.g. "client_id"
echo $error->requestId; // quote this to support
}Consulta SDKs › Gestió d'errors per veure la jerarquia completa. La política de reintents de sota l'apliquen automàticament ambdós SDKs.
request_id i suport
Tota resposta inclou un request_id. Adjunta'l a qualsevol tiquet o
petició a support@factuarea.com:
Subject: 422 on POST /v1/invoices — request_id req_01JBVH7K9Y4N3CDQ2EHJB1AGSVAmb el request_id correlacionem logs, mètriques i traces per
investigar ràpid.
Estratègia de reintents
4xxexcepte429→ no reintentis: l'error és a la petició. Corregeix-lo i reenvia.429→ respecta el headerRetry-After. Implementa back-off exponencial amb jitter.5xx→ back-off exponencial (2^n * 100ms) amb jitter, màxim 5 intents.
Stripe publica un patró canònic que també aplica aquí: stripe.com/docs/error-handling.