Payments
A payment (pay_...) is the central resource of the Paytami API. It's created once and its status advances as the customer completes the payment flow — see the status catalog.
The Payment object
{
"id": "pay_8f2c1a9d4e6b7c0a1d2e3f40",
"status": "created",
"currency": "GTQ",
"amount": "15000",
"paytami_fee": "435",
"net_amount": "14565",
"description": "Tuition — August 2026",
"checkout_url": "https://app.paytami.com/api/v1/checkout/pay_8f2c1a9d4e6b7c0a1d2e3f40",
"created_at": "2026-08-28T15:04:00.000Z"
}| Field | Type | Description |
|---|---|---|
id | string | Public identifier, pay_ prefix. Stable over time. |
status | string | See the status catalog. |
currency | string | GTQ or USD. |
amount | string | Gross charge amount, integer in the minor unit (cents), never a number. |
paytami_fee | string | Paytami's fee on this charge, same unit as amount. |
net_amount | string | What your merchant receives: amount - paytami_fee. |
description | string | undefined | Only present if sent when creating the payment. |
checkout_url | string | Payment page, always on Paytami's domain. |
created_at | string | ISO 8601, UTC. |
TIP
checkout_url always lives on Paytami's own domain — it's part of the platform's stable contract.
POST /v1/payments
Creates a charge.
Authentication: required (Authorization: Bearer sk_...). Headers: Idempotency-Key required — see Idempotency.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
amount | string | Yes | Integer in the minor unit, as a string (e.g. "15000" = Q150.00). |
currency | string | Yes | GTQ or USD. |
method_type | string | Yes | card or bank_transfer. |
success_url | string | Yes | Where the customer returns to if the payment completes. |
cancel_url | string | Yes | Where the customer returns to if they cancel or it fails. |
description | string | No | Up to 500 characters. Shown to the customer at checkout. |
customer.email | string | No | End customer's email. |
customer.name | string | No | End customer's name. |
Example
curl https://app.paytami.com/api/v1/payments \
-X POST \
-H "Authorization: Bearer sk_test_..." \
-H "Idempotency-Key: 6e4b6f0a-a5f0-4b9a-9b8b-1a2b3c4d5e6f" \
-H "Content-Type: application/json" \
-d '{
"amount": "15000",
"currency": "GTQ",
"method_type": "card",
"success_url": "https://your-site.com/thanks",
"cancel_url": "https://your-site.com/cart"
}'const res = await fetch('https://app.paytami.com/api/v1/payments', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PAYTAMI_SECRET_KEY}`,
'Idempotency-Key': crypto.randomUUID(),
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: '15000',
currency: 'GTQ',
method_type: 'card',
success_url: 'https://your-site.com/thanks',
cancel_url: 'https://your-site.com/cart'
})
})
const payment = await res.json()Response: 201 Created with the Payment object.
Possible errors: 401 unauthorized, 400 idempotency_key_required, 409 idempotency_key_reused, 400 validation_error, 400 currency_not_supported, 400 method_not_supported, 400 amount_below_minimum, 400 amount_above_maximum.
GET /v1/payments/{id}
Looks up a charge by its public id.
Authentication: required. Only returns payments belonging to the authenticated merchant — an id from another merchant returns 404, same as a nonexistent one, so it never leaks which identifiers exist.
curl https://app.paytami.com/api/v1/payments/pay_8f2c1a9d4e6b7c0a1d2e3f40 \
-H "Authorization: Bearer sk_test_..."Response: 200 OK with the Payment object. Possible errors: 401 unauthorized, 404 unknown_payment.
GET /v1/payments
Lists the authenticated merchant's charges, most recent first.
Authentication: required.
Query parameters
| Parameter | Type | Description |
|---|---|---|
limit | number | Between 1 and 100. Defaults to 25. |
starting_after | string | A payment id; returns the page after it. |
status | string | Filters by an exact state. |
curl "https://app.paytami.com/api/v1/payments?limit=10&status=captured" \
-H "Authorization: Bearer sk_test_..."Response
{
"data": [ { "id": "pay_...", "status": "captured", "...": "..." } ],
"has_more": true
}For the next page, pass the id of the last item in data as starting_after.
Cursor pagination: the list is ordered by creation date descending; using starting_after instead of a numeric offset prevents a new payment from shifting the page while you paginate.

