Skip to content

Entornos y autenticación

Cada solicitud se autentica con una clave de API en el header:

Authorization: Bearer pgz_live_...
Authorization: Bearer pgz_test_...
  • La clave determina el entorno. No existe header de modo en la superficie externa: pgz_live_ opera en producción; pgz_test_ opera en el sandbox aislado.
  • El aislamiento del sandbox es total. Una solicitud pgz_test_ nunca alcanza al proveedor de pago, nunca crea un cobro real y nunca aparece en datos de producción. Los recursos creados con una clave de un entorno son invisibles para el otro.
  • Emisión de claves. El merchant genera y revoca claves de sandbox y live en el cockpit autenticado. La clave en texto plano se muestra solo al crearla; después de eso la plataforma guarda solo key_hash.
  • Clave inválida o revocada → 401 (invalid_api_key). Alcance insuficiente → 403 (insufficient_scope). El permiso nunca devuelve 404.
  • Cada clave lleva alcances (scopes). Los alcances por endpoint están en la Referencia.

Idempotencia

Cada POST que crea un recurso requiere el header:

Idempotency-Key: 3f1a9b2c-6d4e-4a71-9c2f-8e5b1d0a7c33
  • Requerido en POST /v1/payment_links, POST /v1/quotes, POST /v1/quotes/{id}/accept y POST /v1/payment_intents. Faltante o vacío → 400 (missing_idempotency_key); más de 255 chars → 400 (invalid_idempotency_key). Cualquier cadena única sirve — recomendamos un UUID v4, pero el formato no es exigido (ADR-0010).
  • TTL de 24h, en una tabla dedicada de idempotencia. Un replay de la misma clave dentro del TTL devuelve la respuesta original, byte a byte, con el header Idempotent-Replay: true.
  • Misma clave con un cuerpo diferente → 409 (idempotency_key_reuse).
  • Después de 24h la clave se libera.

Envelope de error

Cada respuesta de error tiene la misma forma. Cada respuesta (éxito o error) lleva el header X-Request-Id.

json
{
  "error": {
    "code": "invalid_request",
    "message": "...",
    "param": "amount",
    "request_id": "req_9f8c..."
  }
}
  • param es el nombre del campo cuando el error es de un campo específico; null en caso contrario.
  • request_id está en el cuerpo y en el header X-Request-Id — cítelo en cualquier solicitud de soporte.

Los schemas son estrictos. Una clave desconocida en el cuerpo de cualquier solicitud → 400 con error.code = "unknown_parameter" y error.param = el nombre de la clave. Nunca hay descarte silencioso.


Paginación

Los listados son cursor-based:

GET /v1/payments?limit=50&starting_after=pay_9f8c...
  • limit: entero, default 20, máximo 100. Por encima de 100400 (invalid_request) — no se trunca en silencio, para que usted no pagine creyendo que recibió la página entera.
  • starting_after: id del último objeto de la página anterior.
  • Respuesta: { "data": [ ... ], "has_more": true }.

Versionado y deprecación

  • La versión vive en el path: /v1/. Un cambio breaking requiere una nueva versión de path (/v2/).
  • Agregar un campo a una respuesta no es breaking y ocurre dentro de /v1/ sin aviso. Los clientes deben ignorar campos desconocidos.
  • Deprecación: una versión deprecada recibe aviso con al menos 12 meses de anticipación. Durante ese período, las respuestas de la versión llevan el header Sunset (RFC 8594) con la fecha de apagado y un header Deprecation: true. La fecha de Sunset nunca se adelanta.