Guatemala — integration recipes
The rails that return a payload on the alternative-payments /payments endpoint for Guatemala are: BAM PaymentButton, Zigi, Akisi QR, Banco Industrial, QuickPay QR, and Pronet. Each section below is self-contained: pre-requisites, exact curl, expected response, status delivery, sandbox data, common errors, and a done checklist.
Setup (do this once)
All recipes assume the variables below. Set them in your shell before running any curl. The host (sb-mw.migopayments.com) and the path (/api/v1/integrations/...) are the public sandbox that external integrators can reach — the older mw.dev.migopayments.com host with /v1/mw-trxs is internal and uses a different auth model (AWS SigV4); do not use it.
export MIGO_BASE="https://sb-mw.migopayments.com"
export MIGO_CLIENT="<your-client-slug>" # e.g. "migoDeveloper"
export MIGO_TOKEN="<your-64-char-merchant-token>" # 64 hex chars
export MIGO_USER_ID="+50224865444"
The 64-char merchant token is the same secret Migo issues for Payment Links. The Alternative Payments routes accept it as a Bearer token — see Authentication → Header format by endpoint.
Create one transaction you'll reuse across the rest of this page (Migo returns the rails enabled for your client inside paymentMethods):
export UID=$(
curl -s -X POST "$MIGO_BASE/api/v1/integrations/transactions" \
-H "Authorization: Bearer $MIGO_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"amount\": 50,
\"channel\": \"web\",
\"client\": \"$MIGO_CLIENT\",
\"userId\": \"$MIGO_USER_ID\",
\"customKeys\": { \"orderId\": \"recipe-test\" }
}" | jq -r '.data.uid'
)
echo "trx uid: $UID"
Inspect the returned paymentMethods to confirm which of the rails below your client has enabled. The enabled set is resolved at runtime from clientConfig.processors (per-merchant, MongoDB) intersected with the platform alternative-payment-methods config, so it is environment- and merchant-dependent — any example array is illustrative only. If a rail you expect is missing, contact Migo Operations.
BAM PaymentButton (bamPaymentButton)
Country: Guatemala · Type: Hosted button (BAM-Banco Agromercantil domain) · Pre-call
payment-intents: No · Response payload:url.
Pre-requisites
clientConfig.processorsincludesbamPaymentButton.- You can render an external redirect from your checkout.
- Optional user input: number of installments.
Process payment
curl -X POST "$MIGO_BASE/api/v1/integrations/transactions/$UID/payments" \
-H "Authorization: Bearer $MIGO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"processor": "bamPaymentButton",
"data": { "installments": 1 }
}'
Expected response — the redirect link is at data.data:
{
"success": true,
"message": "Success",
"data": {
"uid": "trx_…",
"type": "url",
"data": "https://pagosbam.com.gt/…",
"cancelAt": null
}
}
Redirect the customer to data.data. The customer authorizes the payment on BAM's domain and is bounced back to your successUrl / failureUrl. Status is delivered via the merchant callback (clientConfig.callback); the installments echo is merchant-callback-dependent rather than guaranteed.
Sandbox data
- Use any installments value
1..12. - The redirect URL points to the BAM staging environment in sandbox.
Done checklist
-
paymentMethodscontainedbamPaymentButton. - Payment response was
data.type === "url", link read fromdata.data. - Redirect happened, BAM bounced back, callback received.
Zigi (zigi)
Country: Guatemala · Type: Wallet redirect — customer authorizes inside the Zigi app · Pre-call
payment-intents: No · Response payload:url.
Process payment
curl -X POST "$MIGO_BASE/api/v1/integrations/transactions/$UID/payments" \
-H "Authorization: Bearer $MIGO_TOKEN" \
-d '{ "processor": "zigi", "data": {} }'
Response — the challenge payload (type and data from the processor) is at data.data:
{
"success": true,
"message": "success",
"data": {
"uid": "trx_…",
"type": "<challenge.type>",
"data": "<challenge.data>",
"cancelAt": null
}
}
Open the redirect from data.data in a webview or via deep-link to the Zigi app. Status is delivered via the merchant callback (clientConfig.callback).
Refunds: zigi revert/refund are available on the middleware-pay surface via POST $MIGO_BASE/revert and POST $MIGO_BASE/refund with body {"transactionUid":"$UID","processor":"zigi"} (JWT-Bearer scheme, separate from this merchant-token surface).
Done checklist
- Customer redirected to Zigi, authorized, bounced back, callback received.
Akisi / Akisi QR (akisi, akisiQR)
Country: Guatemala · Type: Akisi wallet — push (
akisi) or scannable QR (akisiQR) · Pre-callpayment-intents: No · Response payload:json(push) orbase64(QR).
Process payment — push
akisi (push) is a registered processor key, but the alternative-payments handler only has a response case for akisiQR (QR). A akisi push call hits the handler's default branch and returns no rail-specific payload. Use the QR variant below, or contact Migo Operations to confirm the push integration path.
curl -X POST "$MIGO_BASE/api/v1/integrations/transactions/$UID/payments" \
-H "Authorization: Bearer $MIGO_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "processor": "akisi", "data": {} }'
Process payment — QR
curl -X POST "$MIGO_BASE/api/v1/integrations/transactions/$UID/payments" \
-H "Authorization: Bearer $MIGO_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "processor": "akisiQR", "data": {} }'
Response (verified against sb-mw.migopayments.com):
{
"success": true,
"message": "Success",
"data": {
"transaction_id": "12740927961946781727",
"type": "base64",
"data": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJQAAA…"
}
}
data.data is a complete data:image/png;base64,… URI: drop it directly into <img src=...> without any decoding step. The customer scans the rendered image from the Akisi app. (type and data are taken straight from the processor's paymentRequest; for akisiQR this is a base64 image URI.)
type valueOlder versions of this recipe described the response as { "type": "qr", "value": "data:image/png;..." }. The current runtime returns the payload at data.data, not data.value. If you still have parsers reading data.value, switch them.
Status is delivered via the merchant callback (clientConfig.callback).
akisiQR supports revert via POST $MIGO_BASE/revert with body {"transactionUid":"$UID","processor":"akisiQR"} (JWT-Bearer scheme, separate from this merchant-token surface).
Done checklist
- QR rendered from
data.data. - Callback received (or expiry handled after the QR TTL).
Banco Industrial (bancoIndustrial)
Country: Guatemala · Type: BI push QR · Pre-call
payment-intents: No · Response payload:base64.
Process payment
curl -X POST "$MIGO_BASE/api/v1/integrations/transactions/$UID/payments" \
-H "Authorization: Bearer $MIGO_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "processor": "bancoIndustrial", "data": {} }'
Response — the image is a base64 data-URI at data.data:
{
"success": true,
"message": "success",
"data": {
"uid": "trx_…",
"type": "base64",
"data": "data:image/png;base64,…",
"cancelAt": null
}
}
Drop data.data directly into <img src=...>; the customer scans it from the BI app. Status is delivered via the merchant callback (clientConfig.callback).
Done checklist
- Sandbox returns a base64 data-URI image at
data.data. - Callback arrives after the customer scans in QA.
QuickPay QR (quickPayQR)
Country: Guatemala (also SV, HN, CR) · Type: Interbank QR aggregator · Pre-call
payment-intents: No · Response payload:json(with QR string + reference).
Process payment
curl -X POST "$MIGO_BASE/api/v1/integrations/transactions/$UID/payments" \
-H "Authorization: Bearer $MIGO_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "processor": "quickPayQR", "data": {} }'
Response — type and data come straight from the processor's paymentRequest:
{
"success": true,
"message": "Success",
"data": {
"transaction_id": "…",
"type": "<paymentRequest.type>",
"data": "<paymentRequest.data>",
"cancelAt": null
}
}
Status is delivered via the merchant callback (clientConfig.callback).
quickPayQR supports revert via POST $MIGO_BASE/revert with body {"transactionUid":"$UID","processor":"quickPayQR"} (JWT-Bearer scheme, separate from this merchant-token surface).
Done checklist
- QR payload rendered from
data.data. - Callback arrives after scanning in any participating bank app.
Pronet (pronet) — cash references
Country: Guatemala · Type: Cash references payable at convenience stores · Pre-call
payment-intents: No · Response payload:json.
Process payment
curl -X POST "$MIGO_BASE/api/v1/integrations/transactions/$UID/payments" \
-H "Authorization: Bearer $MIGO_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "processor": "pronet", "data": {} }'
Response — the reference sits under data.data, with limitDate and total:
{
"success": true,
"message": "success",
"data": {
"uid": "trx_…",
"type": "json",
"data": {
"reference": "…",
"limitDate": "…",
"total": 50,
"cancelAt": null
}
}
}
Show data.data.reference to the customer; they pay it at a Pronet convenience store. Status is delivered via the merchant callback (clientConfig.callback) after the cash-confirm flow.
pronet reversals are supported via the cash-confirm flow.
Done checklist
- Reference number from
data.data.referenceshown to the customer withlimitDate. - Callback arrives once the cash payment is confirmed.
Common errors across rails
The alternative-payments middleware raises 4-digit own-codes (not the ALI Gateway 7xxx catalog):
| HTTP | own-code | When |
|---|---|---|
| 400 | 5000 | Missing/invalid params (amount, channel, client, userId, customKeys, or processor) |
| 400 | — | processor not allowed for this client |
| 400 | 5004 | Client config not found |
| 400 | 2002 | Transaction create failed |
| 400 | 2003 | Amount outside the allowed range |
Receiving payment status
Status is delivered via the merchant callback you configure in clientConfig.callback — the payload is whatever your callback data template defines, not a fixed platform envelope. See Merchant Generic Callback.
No outbound webhook signer exists in code today — the platform does not currently emit an X-Migo-Signature header.
Final checklist
- Merchant token authenticated (sent as
Authorization: Bearer $MIGO_TOKEN) — see Authentication → Header format. - One transaction created;
paymentMethodscontains every rail you plan to expose. - Each available rail above tested at least once in sandbox; rail payload read from
data.data. - Refund/void paths tested for the rails that support them.
- Production keys rotated separately from sandbox keys (sandbox token does not work in production).