Skip to main content
A payment intent represents a request to collect a card-present payment through a Compago POS terminal. Unlike one-time payments (which generate hosted checkout links for online use), payment intents are designed for in-person, terminal-based payment flows where your system orchestrates the transaction and a physical terminal handles card capture.

What You Can Do

With payment intents, you can:
  • Initiate Terminal Payments: Create a payment request that a POS terminal picks up and processes
  • Track Payment Status: Poll for real-time status updates as the terminal processes the card
  • Cancel Pending Payments: Cancel payment intents that haven’t been completed yet
  • Link to Your Systems: Use external IDs to correlate Compago payments with your internal records
  • Target Specific Terminals: Optionally route payment requests to a specific terminal by its serial number

Use Cases

Payment intents are designed for:
  • Custom POS Integrations: Build your own point-of-sale system that uses Compago terminals for card processing
  • ERP Payment Modules: Add card-present payment capabilities to ERP systems (e.g., Odoo, SAP)
  • Kiosk Applications: Self-service kiosks that accept card payments through connected terminals
  • Restaurant/Retail Systems: Any in-person checkout flow where your software manages the transaction

How It Works

After creating a payment intent, there are two ways to handle the payment flow depending on your setup. Both start the same way (your backend creates the payment intent via the API), but differ in how the card payment is captured. Use this when the Compago POS app is installed on the same device as your integration (e.g., an Android tablet running both your POS app and the Compago app). Your app opens the Compago app via a deep link, and the Compago app handles the entire card capture flow. When the payment is complete, control returns to your app.
1

Your system creates a payment intent

POST /api/payment-intent with amount, currency, externalId, and optionally terminalCode. Compago returns the payment intent with status: PENDING.
2

Your app opens the Compago POS app

Use the deep link compago-pos-app:///charge/payment-intent/{id} to hand off to the Compago app. The Compago app displays the payment screen and handles card capture.
3

Your system polls for status

While the Compago app handles the payment, your system polls GET /api/payment-intent/{id} every 3 seconds to detect when the payment completes.
4

Your system fulfills the order

Once paymentSummary.status is SUCCESS, mark the order as paid, print a receipt, update inventory, etc.

Separate-Device Flow (Polling Only)

Use this when the Compago POS terminal is a separate physical device from the one running your integration (e.g., your ERP runs on a desktop and the terminal sits on the counter). Your system simply polls for status while the terminal operator processes the card on the Compago device.
1

Your system creates a payment intent

POST /api/payment-intent with amount, currency, externalId, and terminalCode. Compago returns the payment intent with status: PENDING.
2

Compago notifies the POS terminal

The terminal automatically receives a notification alerting it that a new payment request is waiting.
3

The terminal processes the card

The terminal operator sees the incoming payment request on the Compago POS app and processes the customer’s card.
4

Your system polls for status

GET /api/payment-intent/{id} every 3 seconds. Once the terminal completes the payment, the response includes paymentSummary.status: "SUCCESS".
5

Your system fulfills the order

Mark the order as paid, print a receipt, update inventory, etc.
Both flows use the same API endpoints. The only difference is whether your client-side app opens the Compago POS app via deep link before polling. Choose based on whether your app and the Compago POS app run on the same device.

Prerequisites

Before creating payment intents, ensure you have:
  • An active Compago merchant account with API access
  • A valid API key (generate one at Configuraciones -> Desarrollador in your Compago Dashboard)
  • At least one Compago POS terminal registered to your organization
  • Your integration configured to use MXN currency
Payment intents currently support MXN (Mexican Peso) only. Transactions in other currencies will be rejected.

Creating a Payment Intent

Endpoint

POST /api/payment-intent
API reference: POST /payment-intent

Authentication

Include your API key in the request headers:
x-api-key: YOUR_API_KEY
Content-Type: application/json

Request Body

{
  "amount": 350.50,
  "currency": "MXN",
  "externalId": "order_12345_pos",
  "terminalCode": "TERMINAL-001"
}

Field Descriptions

FieldTypeRequiredDescription
amountnumberYesPayment amount in MXN.
currencystringYesCurrency code. Must be "MXN".
externalIdstringYesYour unique identifier for this payment intent. Must be unique per organization.
terminalCodestringNoSerial number of the target POS terminal. If provided, the payment intent is routed to that specific terminal. If omitted, the payment intent is available to any terminal in your organization.

Response

{
  "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "status": "PENDING",
  "amount": 350.50,
  "currency": "MXN",
  "externalId": "order_12345_pos",
  "organizationId": "org-uuid",
  "terminalId": "terminal-uuid",
  "createdAt": "2026-03-11T10:00:00.000Z",
  "updatedAt": "2026-03-11T10:00:00.000Z"
}
Save the returned id. You will need it to poll for status, open the Compago app, or cancel the payment intent.

Example with cURL

curl -X POST https://api.harmony.compago.com/api/payment-intent \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 350.50,
    "currency": "MXN",
    "externalId": "order_12345_pos",
    "terminalCode": "TERMINAL-001"
  }'

Opening the Compago App (Same-Device Flow)

If the Compago POS app is installed on the same device as your integration, you can open it directly using a deep link. The Compago app will display the payment screen for the given payment intent and handle the full card capture flow.
compago-pos-app:///charge/payment-intent/{id}
Replace {id} with the payment intent ID returned from the create endpoint.

Implementation Example

On Android-based POS devices, you can trigger the deep link by navigating to the URL. For web-based integrations running on the same device, a common approach is using a hidden iframe:
function openCompagoApp(paymentIntentId) {
  const url = `compago-pos-app:///charge/payment-intent/${paymentIntentId}`;

  const iframe = document.createElement('iframe');
  iframe.style.display = 'none';
  iframe.src = url;

  document.body.appendChild(iframe);

  // Clean up the iframe after it triggers the intent
  setTimeout(() => document.body.removeChild(iframe), 1000);
}
The deep link requires the Compago POS app to be installed on the device. If the app is not installed, the deep link will have no effect. Your integration should still poll for status regardless, so the payment can also be processed from a separate device.
After opening the Compago app, your system should immediately begin polling for the payment status (see next section). The polling logic is identical for both flows.

Polling for Payment Status

After creating a payment intent (and optionally opening the Compago app via deep link), your system should poll the GET endpoint to detect when the terminal completes the payment.

Endpoint

GET /api/payment-intent/{id}
API reference: GET /payment-intent/{id}

Response

When the payment is still being processed:
{
  "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "status": "PENDING",
  "expired": false
}
When the payment has been completed successfully:
{
  "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "status": "CONFIRMED",
  "expired": false,
  "paymentSummary": {
    "status": "SUCCESS"
  }
}

How to Poll

The recommended approach is:
  1. Wait 3 seconds between each request
  2. Check the response for a terminal state:
    • paymentSummary.status is "SUCCESS": the payment was completed. Fulfill the order.
    • expired is true: the payment intent timed out. Prompt the user to retry.
    • status is "CANCELLED": the payment intent was cancelled. Handle accordingly.
  3. Repeat until one of the above conditions is met, or until a maximum timeout (e.g., 10 minutes)

Example

# Poll every 3 seconds until the status changes
curl -X GET https://api.harmony.compago.com/api/payment-intent/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee \
  -H "x-api-key: YOUR_API_KEY"

Cancelling a Payment Intent

You can cancel a pending payment intent before it is completed or expires. This is useful when the user changes their mind, navigates away, or the order is voided.

Endpoint

POST /api/payment-intent/{id}/cancel
API reference: POST /payment-intent/{id}/cancel For the full cancel guide, see Cancel Payment Intent.

Example

curl -X POST https://api.harmony.compago.com/api/payment-intent/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cancel \
  -H "x-api-key: YOUR_API_KEY"
Cancelling a payment intent also notifies the POS terminal that the payment request has been withdrawn.

Important Business Rules

Payment Intent Expiration

Payment intents expire 10 minutes after creation. If the terminal does not process the payment within this window, the payment intent becomes invalid. Create a new payment intent if needed.

Terminal Routing

When you provide a terminalCode:
  • The payment intent is routed to that specific terminal
  • Any other PENDING payment intents for that terminal are automatically cancelled
  • This ensures only one active payment intent exists per terminal at any time
When you omit terminalCode:
  • The payment intent is available to any terminal in your organization
  • This is useful when you don’t know which terminal will process the payment

External ID Uniqueness

The externalId must be unique within your organization. Attempting to create a payment intent with a duplicate externalId will result in an error. Use a combination of your internal identifiers with a timestamp or random suffix to ensure uniqueness across retries. For example: order-789_1710150000_a1b2c3.

Currency Restriction

Currently, only MXN (Mexican Peso) is supported. Requests with other currencies will be rejected.

Payment Intent Status

Payment intents have three statuses:
StatusDescription
PENDINGPayment intent is active, waiting for the terminal to process the card payment.
CONFIRMEDThe terminal has successfully processed the card payment. This is a final state.
CANCELLEDThe payment intent was cancelled (manually or by creating a new intent for the same terminal). This is a final state.

Error Handling

Common Errors

Status CodeErrorSolution
400User does not have an organizationVerify your API key is associated with a valid merchant organization
400Only MXN currency is supportedUse "MXN" as the currency
400Payment intent already confirmedThe payment was already processed. Cannot cancel a confirmed intent.
401UnauthorizedCheck your API key is valid and included in headers
404Terminal not foundVerify the terminalCode matches a terminal registered to your organization
404Payment intent not foundThe payment intent ID does not exist or does not belong to your organization

Example Error Response

{
  "message": "Only MXN currency is supported."
}

Best Practices

When you know which terminal should process the payment, always provide the terminalCode. This ensures the payment intent is routed to the correct terminal and automatically cancels any stale pending intents on that terminal.
Payment intents expire after 10 minutes. Your integration should:
  1. Detect expiration in your polling loop (when expired is true)
  2. Offer the user the option to retry
  3. Create a new payment intent with a new externalId if they choose to retry
Combine your internal identifiers with a timestamp or random suffix to avoid collisions. For example: session-5_order-abc_1710150000. Avoid reusing the same ID for retries, since duplicate externalId values within the same organization will be rejected.
If the user navigates away from the payment screen or cancels the order, send a cancel request for the pending payment intent. This frees up the terminal and prevents stale intents from blocking new payments.

Support

If you encounter issues with payment intents:
  • Verify your API key is valid in Configuraciones -> Desarrollador at app.compago.com
  • Ensure you have at least one terminal registered to your organization
  • Check that the terminalCode matches your terminal’s serial number
  • Contact Compago support at help@compago.com for assistance