Documentación Ver secciones

Errores y solución de problemas

Referencia rápida de los códigos de error HTTP que puede recibir y cómo resolverlos.

Errores de cliente (4xx)

400 Bad Request

La solicitud tiene un formato inválido o faltan parámetros requeridos. Casos comunes: omitir include en el detalle, omitir nombre y ruc en la búsqueda, o enviar un código de producto inválido.

401 Unauthorized

No se envió el header Authorization: Bearer pk_... en una ruta que lo exige (sin llave solo responden POST /v5/resolve y GET /v5/entities/{id}), o la llave gratuita venció (code: key_expired, abajo).

Solución: Envíe su llave API como Bearer token en cada solicitud.

402 Payment Required

No tiene saldo prepago suficiente para completar la solicitud. El cuerpo dice cuánto cuesta la llamada y, normalmente, cuánto saldo queda y cuánto falta (code: insufficient_credits).

Solución: Recargue saldo desde su panel.

403 Forbidden

La llave fue rechazada por la capa de autenticación.

Solución: Verifique que está usando una llave activa generada en su cuenta y que la copió completa.

404 Not Found

La entidad con el ID proporcionado no existe.

Solución: Verifique el id usando el endpoint de búsqueda.

Llave con saldo: saldo insuficiente y tope de gasto

Lo que recibe una llave con saldo cuando no alcanza a pagar la llamada. Ninguno de los dos se cobra. El campo error conserva su texto de siempre; para decidir, use code.

402 insufficient_credits

El saldo no cubre esta llamada. Se chequea antes de ejecutarla, al precio completo, así que no se hace trabajo (ni se paga a un tercero) para una llamada que termina en 402. price es lo que cuesta, balance el saldo actual y shortfall lo que falta; los créditos van como texto. hint aparece solo si el saldo todavía cubre una ficha DAT-FREE: esa lectura sigue respondiendo. Si otro request gastó el saldo mientras esta llamada corría, el gateway relee la billetera: si esa lectura falla, balance y shortfall no vienen; si encuentra que el saldo ya alcanza (entró una recarga), shortfall no viene y el mensaje pide reintentar. Una llave con saldo cero no recibe este error: pasa al nivel gratuito (abajo).

{"error": "insufficient credits", "code": "insufficient_credits",
 "price": "1.56", "balance": "0.90", "shortfall": "0.66",
 "hint": "GET /v5/entities/{id}?include=DAT-FREE",
 "upgrade_url": "https://platform.panadata.net/facturacion",
 "message": "Insufficient credits: this call costs 1.56 and the balance is 0.90 (0.66 short). Add credits at https://platform.panadata.net/facturacion. DAT-FREE still works: GET /v5/entities/{id}?include=DAT-FREE returns the signals card (booleans, ranges and the list of codes with data)."}
429 spending_limit_exceeded

La llamada llevaría el gasto del mes por encima del tope que fijó el dueño de la cuenta en Facturación. limit es el tope, consumed lo gastado en el período (un período vencido cuenta desde 0) y price lo que cuesta la llamada. resets_at es el primer día del mes siguiente (UTC) y la cabecera Retry-After trae los segundos hasta entonces. settings_url lleva a la sección de Facturación donde se sube o se quita el tope.

{"error": "spending_limit_exceeded", "code": "spending_limit_exceeded",
 "price": "3.50", "limit": "10.00", "consumed": "8.50",
 "resets_at": "2026-11-01T00:00:00+00:00", "settings_url": "https://platform.panadata.net/facturacion#limite",
 "message": "Monthly spending limit exceeded: this call costs 3.50 and 8.50 of this account's 10.00 monthly limit is already used. It resets at 2026-11-01T00:00:00+00:00; to continue sooner, raise the limit at https://platform.panadata.net/facturacion#limite."}

Nivel gratuito y nivel 0

Los rechazos propios de una llave sin saldo (nivel 1) y de los requests sin llave (nivel 0). Todos traen un campo code legible por máquina y un upgrade_url con el paso siguiente: la página de compra (/facturacion) cuando hay llave, la del nivel gratuito (/docs/dat-free) cuando no la hay.

401 key_expired

La llave gratuita venció: dura 90 días sin compra. Cualquier compra (Sandbox US$95 en adelante) la vuelve permanente; una llave vencida se reemplaza creando otra desde el Panel.

{"error": "api_key_expired", "code": "key_expired", "expired_at": "2026-12-20T14:02:11+00:00",
 "message": "This API key has expired. Free keys last 90 days; any purchase (Sandbox onwards) makes the key permanent.",
 "upgrade_url": "https://platform.panadata.net/facturacion"}
403 free_tier_code_locked

Una llave sin saldo pidió un código fuera del nivel gratuito (CHK-BIN, DAT-RESOLVE, DAT-FREE), una búsqueda, o un activo por id (pa_finca_, pa_ph_, pa_nave_, pa_marca_, pa_imp_…). Solución: pedir ?include=DAT-FREE o cargar saldo. Con ?dry_run=1 la misma llamada cotiza sin candado: conserva el precio en créditos y trae free_tier.locked: true.

{"error": "This data needs credits — it is not part of the free tier: DAT-CORE. The free tier answers questions about the data without returning records: CHK-BIN, DAT-FREE, DAT-RESOLVE (use ?include=DAT-FREE for booleans, ranges and the list of codes with data). Add credits to unlock all sources.",
 "code": "free_tier_code_locked", "locked_codes": ["DAT-CORE"], "free_tier_codes": ["CHK-BIN", "DAT-FREE", "DAT-RESOLVE"],
 "upgrade_url": "https://platform.panadata.net/facturacion"}
429 free_tier_limit

La llamada no cabe en el cupo de la llave gratuita: 30 entidades/día o 500/mes (100/día y 1,000/mes con dominio corporativo). Cuentan cada fila cobrable de resolve (las invalid no), cada ficha DAT-FREE o CHK-BIN y cada id de /entities/batch; dry_run y el estimador no cuentan; un dry_run de la misma llamada trae free_tier.would_exceed: true y would_status: 429 antes de gastarla. Se emite solo cuando used + filas > limit: used, remaining y requested dicen cuánto queda (un lote de 7 sí pasa con 23/30), la cabecera Retry-After trae los segundos hasta el reinicio. Los contadores se cortan por día y mes UTC: reset_at es la próxima medianoche UTC (period: day) o el próximo día 1 a las 00:00 UTC (period: month).

{"error": "This request of 11 entities would exceed today's remaining 7 (23/30 used on the free tier); a request of 7 or fewer fits. It resets at 2026-09-23T00:00:00+00:00. Add credits to unlock unlimited calls and every data source.",
 "code": "free_tier_limit", "period": "day", "limit": 30, "used": 23, "remaining": 7, "requested": 11,
 "reset_at": "2026-09-23T00:00:00+00:00", "upgrade_url": "https://platform.panadata.net/facturacion"}
400 free_tier_batch_rows

POST /v5/resolve/batch con más de 10 filas desde una llave gratuita sin with_presence (el body se valida antes que el cupo: un lote de 11 a 23/30 es este 400, no un 429). Solución: lotes de 10, o with_presence: true para el estimador (solo agregados; hasta 100 filas; 5,000 filas/mes, 402 estimator_rows_exhausted al agotarse).

{"error": "max 10 rows per batch on the free tier (the estimator, with_presence=true, takes up to 100)", "code": "free_tier_batch_rows"}
400 invalid_identifier

POST /v5/resolve con un ruc o una cedula cuyo formato no se reconoce (los identificadores se normalizan antes: espacios, «DV», minúsculas). En POST /v5/resolve/batch la misma fila no rompe el lote: sale con outcome: invalid, no se cobra ni cuenta.

{"error": "identificador no reconocido: …", "code": "invalid_identifier"}
403 public_tier_locked

Sin llave solo responden POST /v5/resolve (una fila) y GET /v5/entities/{id}. El lote, los sub-recursos, las búsquedas y las rutas v4 exigen una llave; la gratuita alcanza.

{"error": "Without an API key only POST /v5/resolve (one row) and GET /v5/entities/{id} are available; the batch needs a free key. Sign up for one — it is free.",
 "code": "public_tier_locked", "upgrade_url": "https://platform.panadata.net/docs/dat-free"}
429 public_budget_exhausted

El nivel 0 agotó el presupuesto compartido del día (1,000 consultas para todo el nivel: HTTP directo + MCP público). Se reinicia a medianoche de Panamá (America/Panama, UTC−5), no en UTC; reset_at lo dice en ISO 8601. Una llave gratuita tiene su propio cupo y no lo siente.

{"error": "The no-key tier has used today's shared budget. It resets at midnight (America/Panama). A free API key has its own allowance — sign up, it is free.",
 "code": "public_budget_exhausted", "reset_at": "2026-09-23T00:00:00-05:00",
 "upgrade_url": "https://platform.panadata.net/docs/dat-free"}
400 invalid_inline_limit

GET /v5/entities/{id}?inline_limit=N con N fuera de 1..100 o no entero. El parámetro acota las listas inline de cada sección del detalle (default 10, DETAIL_INLINE_LIMIT); vale para cualquier nivel.

{"error": "inline_limit must be an integer 1..100", "code": "invalid_inline_limit"}

Toda respuesta del nivel 1 (2xx y 429) trae X-Panadata-Tier: free, X-Panadata-Free-Remaining-Today y X-Panadata-Free-Remaining-Month (el estimador suma X-Panadata-Free-Estimator-Rows-Remaining); el nivel 0, X-Panadata-Tier: public y X-Panadata-Public-Budget-Remaining. La tasa (1 request/segundo con ráfaga de 5) la aplica el plan de uso del API Gateway: su 429 no trae code; reintente con espera exponencial. Qué devuelve cada nivel y por qué: Nivel gratuito (DAT-FREE).

Búsquedas: el backend no respondió completo

Buscar, resolver y leer el detalle dependen de OpenSearch. Cuando no da una respuesta completa y útil, la API responde con uno de tres códigos; el campo retryable dice si reintentar sirve. Ninguno se cobra ni cuenta contra el cupo gratuito, y nunca sale como un 200 con cero resultados.

502 search_backend_error

OpenSearch estaba caído, se agotó el tiempo, rechazó por carga (429 / es_rejected_execution) o respondió a medias (shards fallidos o timed_out). En una búsqueda de una sola superficie, que falte su índice también es este 502. Solución: reintentar después de los segundos que indica la cabecera Retry-After (5). POST /v5/resolve/batch reintenta una vez la fila que recibió un rechazo por carga; si vuelve a fallar, o si hay un timeout o una respuesta parcial, el 502 es de toda la llamada y no se cobra nada.

HTTP/1.1 502 Bad Gateway
Retry-After: 5

{"error": "search backend error", "code": "search_backend_error", "retryable": true}
400 invalid_search_query

OpenSearch rechazó la consulta por su forma, típicamente un valor de filtro del tipo equivocado ({"monto_min": "abc"}, un array donde va un término). Solución: corregir la consulta; repetirla igual falla igual. En POST /v5/resolve/batch no rompe el lote: esa fila vuelve con outcome: invalid y no se cobra.

{"error": "the search backend rejected the query: check the type of each filter value",
 "code": "invalid_search_query", "retryable": false}
500 internal_error

La respuesta de OpenSearch llegó y el gateway no la pudo leer: un bug de nuestro lado. No se cobra y reintentar la misma petición no ayuda; si persiste, contáctenos con la hora y la ruta.

{"error": "internal error", "code": "internal_error", "retryable": false}

Errores de servidor (5xx)

500 Internal Server Error

Error interno del servidor. Si persiste, contáctenos. Estas solicitudes no se cobran. En las búsquedas trae code: internal_error y retryable: false (arriba).

503 Service Unavailable

El servicio está temporalmente fuera de línea. Reintente en unos minutos.

Anterior: ← Webhooks