Skip to content

Environments and authentication

Every request authenticates with an API key in the header:

Authorization: Bearer pgz_live_...
Authorization: Bearer pgz_test_...
  • The key determines the environment. There is no mode header on the external surface: pgz_live_ operates in production; pgz_test_ operates in the isolated sandbox.
  • Sandbox isolation is total. A pgz_test_ request never reaches the payment provider, never creates a real charge, and never appears in production data. Resources created with a key from one environment are invisible to the other.
  • Key issuance. The merchant generates and revokes sandbox and live keys in the authenticated cockpit. The plaintext key is shown only at creation; after that the platform stores only key_hash.
  • Invalid or revoked key → 401 (invalid_api_key). Insufficient scope → 403 (insufficient_scope). Permission never returns 404.
  • Every key carries scopes. The scopes per endpoint are in the Reference.

Idempotency

Every POST that creates a resource requires the header:

Idempotency-Key: 3f1a9b2c-6d4e-4a71-9c2f-8e5b1d0a7c33
  • Required on POST /v1/payment_links, POST /v1/quotes, POST /v1/quotes/{id}/accept, and POST /v1/payment_intents. Missing or empty → 400 (missing_idempotency_key); over 255 chars → 400 (invalid_idempotency_key). Any unique string works — we recommend a UUID v4, but the format is not required (ADR-0010).
  • 24h TTL, in a dedicated idempotency table. A replay of the same key within the TTL returns the original response, byte for byte, with the Idempotent-Replay: true header.
  • Same key with a different body → 409 (idempotency_key_reuse).
  • After 24h the key is released.

Error envelope

Every error response has the same shape. Every response (success or error) carries the X-Request-Id header.

json
{
  "error": {
    "code": "invalid_request",
    "message": "...",
    "param": "amount",
    "request_id": "req_9f8c..."
  }
}
  • param is the field name when the error is about a specific field; null otherwise.
  • request_id is in the body and in the X-Request-Id header — cite it in any support request.

Schemas are strict. An unknown key in the body of any request → 400 with error.code = "unknown_parameter" and error.param = the key name. There is never a silent drop.


Pagination

Listings are cursor-based:

GET /v1/payments?limit=50&starting_after=pay_9f8c...
  • limit: integer, default 20, maximum 100. Above 100400 (invalid_request) — it is not silently truncated, so you do not paginate thinking you received the whole page.
  • starting_after: id of the last object from the previous page.
  • Response: { "data": [ ... ], "has_more": true }.

Versioning and deprecation

  • The version lives in the path: /v1/. A breaking change requires a new path version (/v2/).
  • Adding a field to a response is not breaking and happens within /v1/ without notice. Clients should ignore unknown fields.
  • Deprecation: a deprecated version gets at least 12 months notice. During that period, the version's responses carry the Sunset header (RFC 8594) with the shutdown date and a Deprecation: true header. The Sunset date is never moved earlier.