Core

Errors

Standard HTTP status codes plus a typed JSON envelope.

Error envelope

Toda respuesta de error tiene la misma forma: el campo error.code es la fuente de verdad — los message pueden cambiar, los códigos no. Usa el requestId al contactar soporte.

json
{
  "error": {
    "code": "card_declined",
    "type": "invalid_request_error",
    "message": "The card was declined by the issuer.",
    "param": "source.number",
    "decline_code": "insufficient_funds",
    "requestId": "req_3kf91… "
  }
}

HTTP statuses

Mapeo de códigos HTTP que devuelve la API. El status de la respuesta es coherente con el tipo de error (4xx = problema del cliente, 5xx = problema nuestro).

StatusMeaningDescription
200OKEverything worked.
201CreatedA new resource was created.
400Bad requestRequest is malformed or missing required parameters.
401UnauthorizedMissing or invalid API key.
402Payment failedProvider declined the charge.
403ForbiddenKey kind is not allowed for this endpoint.
404Not foundResource does not exist.
409ConflictIdempotency-Key reused with a different request body.
415Unsupported media typeContent-Type must be application/json.
422Unprocessable entityNo provider in the cascade can accept this charge.
429Too many requestsRate limit exceeded — back off and retry with jitter.
500Server errorInternal failure. Safe to retry idempotently.
503Service unavailableTemporary maintenance / upstream outage.

Error codes

Lista exhaustiva de cada error.code que puede aparecer en una respuesta /v1, agrupado por type. Estos códigos son estables — están versionados con la API. Si recibes uno que no está aquí, abre un issue.

Authentication errors · 6
CodeHTTPCuándo se devuelve
missing_credentials401El request no llegó con header Authorization (o lo enviaste vacío).
invalid_api_key401La key no existe, está rotada, o pertenece a otro entorno (sandbox vs production).
invalid_token401JWT corrupto, alterado o firmado con otro secreto.
token_expired401El JWT expiró (vida útil 1h). Reinicia el flow llamando POST /v1/auth/token.
production_key_refused400El endpoint sandbox rechaza credenciales live por seguridad.
shop_required401El token no carga `shopId`. Probablemente vino de credenciales merchant-level legacy.
Permission errors · 2
CodeHTTPCuándo se devuelve
key_kind_not_allowed403Estás usando una `pk_*` en una operación que requiere `sk_*`.
forbidden403El recurso pertenece a otro merchant/shop o tu rol no lo permite.
Invalid request errors · 21
CodeHTTPCuándo se devuelve
content_type_required415Mandaste form-urlencoded, multipart u otro tipo. Setea `Content-Type: application/json`.
invalid_json400El cuerpo no se pudo parsear. Revisa comas y comillas.
invalid_request400Uno o más campos no cumplen el schema. Mira el array `details.issues` para detalles.
missing_field400Falta un campo obligatorio. El campo se indica en `param`.
unsupported_method400El `method` solicitado no está en el allow-list del shop. Usa GET /v1/payment-methods para ver los disponibles.
unsupported_country400El método elegido no aplica al país del usuario.
unsupported_currency400Revisa `currencyLimits` del método para ver las monedas válidas.
amount_invalid400El monto vino vacío, en cero, negativo o no numérico.
amount_below_minimum400El monto es menor al mínimo que el provider acepta para este método.
amount_above_maximum400El monto excede el máximo que el provider acepta para este método.
idempotency_conflict409Reusaste una `Idempotency-Key` con un body distinto. Genera una nueva o repite el body original.
card_declined402El emisor rechazó el cobro. `decline_code` indica la razón específica.
insufficient_funds402Sub-caso de card_declined.
fraud_blocked402El motor de riesgo (nuestro o del provider) marcó la operación.
kyc_required402El monto/método requiere verificación. Inicia con POST /v1/kyc/init.
three_ds_required402Redirige al usuario al `redirectUrl` que devuelve el response.
three_ds_failed402El usuario no completó el challenge o falló. La transacción queda en estado failed.
expired_card402Sub-caso de card_declined.
balance_insufficient422Aplicado al solicitar withdrawals/refunds que exceden el available.
settlement_already_paid409No se puede pagar dos veces el mismo settlement.
claim_already_resolved409Los claims terminales no aceptan más evidencia ni cambios de estado.
Rate limit errors · 1
CodeHTTPCuándo se devuelve
rate_limited429Excediste el rate limit del tier. El header `Retry-After` indica cuánto esperar.
API / server errors · 11
CodeHTTPCuándo se devuelve
shop_not_found404El shop fue eliminado o nunca existió. Verifica el id en /admin/shops.
merchant_not_found404El merchant referenciado no existe.
transaction_not_found404El `id` de transacción no existe o pertenece a otro merchant.
settlement_not_found404El settlement no existe o ya fue archivado.
claim_not_found404El claim no existe o pertenece a otro merchant.
wallet_not_found404La payout wallet no existe en este merchant.
webhook_not_found404El webhook subscription no existe (o pertenece a otro merchant). Verifica el id contra GET /api/v1/webhooks.
webhook_delivery_not_found404El delivery id no existe bajo este webhook subscription. Lista las entregas con GET /api/v1/webhooks/{id}/deliveries.
cascade_exhausted422Todos los providers configurados rechazaron o están deshabilitados. Revisa `attempts` en el response.
service_unavailable503Mantenimiento o un upstream caído. Reintenta con backoff exponencial.
internal_error500Bug del servidor o un panic no controlado. Manda el `requestId` a soporte.
Cómo manejar errores en tu integración: recomendamos hacer switch sobre error.code para decidir la acción (retry, mostrar mensaje al usuario, escalar a soporte). Nunca hagas parsing del message: ese texto puede cambiar entre versiones.