Toda respuesta no-2xx lleva { error: { code, message } }. El status code mapea al semántico HTTP; el code es específico de droprails y machine-friendly.
| status | code | significado |
|---|---|---|
| 400 | request.invalid | campo requerido faltante, JSON mal formado, o valor inválido |
| 400 | request.qty_unsupported | v0.1 solo soporta qty=1 |
| 400 | request.amount_required | SKU de monto variable requiere amount explícito |
| 400 | request.amount_invalid | amount no coincide (SKU fijo) o fuera de rango |
| 401 | receipt.unauthorized | la credencial no coincide con el railCredentialHash de la orden |
| 402 | — | credencial faltante o inválida; mppx devuelve esto con header WWW-Authenticate |
| 404 | catalog.not_found | SKU desconocido o item inactivo |
| 404 | brand.not_found | id de marca desconocido |
| 404 | item.not_found | sku de item desconocido |
| 404 | receipt.not_found | no hay orden con ese id |
| 409 | idempotency.conflict | Idempotency-Key reutilizada con body distinto, o solicitud previa en vuelo |
| 409 | credential.replayed | esta credencial MPP ya fue usada (ventana de replay de 24h) |
| 422 | upstream.start_failed | no se pudo iniciar la orden (sin stock, validación, etc.) |
| 422 | upstream.confirm_failed | upstream reportó un error fatal en confirm |
| 502 | upstream.partial_unrecoverable | cumplimiento parcial tras reintentos; reembolso por la vía requerido |
| 503 | config.no_rails | ninguna vía configurada en este servidor |
| 504 | upstream.timeout_unrecoverable | presupuesto de polling excedido; refund_required |