Skip to main content
A one-time payment (OTP) is a secure, single-use checkout link that allows your customers to complete a purchase through Compago’s hosted payment page. This is ideal for non-recurring transactions, custom payment requests, or integrations where the payment flow is triggered externally.

What You Can Do

With one-time payments, you can:
  • Generate Secure Payment Links: Create unique, time-limited checkout URLs for each transaction
  • Accept Card Payments: Process credit and debit card payments through Compago’s PCI-compliant infrastructure
  • Customize the Experience: Control where customers are redirected after payment completion
  • Track Payments: Use your own external IDs to link Compago payments with your internal systems
  • Offer Installment Plans: Support monthly installment payments (Meses Sin Intereses) when available, and choose exactly which plans each payment offers
  • Set Custom Expiration Times: Configure payment link expiration from 10 minutes to 48 hours based on your needs

Use Cases

One-time payments are perfect for:
  • Invoicing: Send payment links to customers via email or messaging
  • Custom Integrations: Trigger payments from CRM, ERP, or internal tools
  • eCommerce: Accept payments for online stores and marketplaces
  • Service Businesses: Request deposits or full payments for appointments or bookings
  • Point of Sale: Create payment links for in-person transactions (when integrated with terminal apps)

How It Works

  1. Create: Your backend calls the Compago API to create a payment link, providing the amount, customer details, and redirect URLs
  2. Receive: Compago returns a secure checkout URL where your customer will complete the payment
  3. Redirect: Send your customer to the checkout URL where they enter their payment details
  4. Process: Compago processes the payment securely through its payment infrastructure
  5. Callback: After successful payment, Compago redirects the customer back to your redirectUrl with query parameters id and externalId appended
  6. Verify: On your callback page, extract the payment id from the URL and fetch the final payment status using the GET endpoint
  7. Fulfill: Update your internal systems (mark order as paid, send confirmation email, etc.)

Prerequisites

Before creating one-time payments, ensure you have:
  • An active Compago account with API access
  • A valid API key, created at Configuraciones → Desarrollador in the dashboard of the environment you call (demo-app.compago.com for Demo, app.compago.com for Production). See Environments.
  • Your integration configured to use MXN currency
One-time payments currently support MXN (Mexican Peso) only. Transactions in other currencies will be rejected.

Creating a One-Time Payment

These examples call the production host. While you build, replace https://api-harmony.compago.com with https://demo-api-harmony.compago.com and use a key from the Demo dashboard. See Environments.

Endpoint

API reference: POST /one-time-payment

Authentication

Include your API key in the request headers:

Request Body

Field Descriptions

Billing Information

The object as a whole is optional. When you do send it, these fields are all required.

Address

Response

Use the returned redirectUrl to redirect your customer to Compago’s secure checkout page.

Example with cURL

Who provides the customer details

Compago needs the payer’s name, email and phone to process a card. There are two ways it gets them, and you choose per payment by including billingInformation or leaving it out. You already know the customer. Send billingInformation when you create the payment. The checkout page asks only for the card and lets the customer correct the phone number, so they type as little as possible. This is the right choice for invoicing, for an online store that already has an account, or for anywhere your system holds the customer record. You do not know the customer. Leave billingInformation out. The checkout page then asks the payer for their own name, email and phone alongside the card, exactly as a Compago payment link does. This is the right choice for a counter or a QR code handed to a walk-in, where asking a stranger to read out their email is slower than letting them type it themselves. Either way the details end up on the payment, so a charge created without them is fully attributed once it is paid. Nothing else about the integration changes.
Sending billingInformation remains fully supported and is unchanged. If your integration already sends it, you do not need to do anything.
A payment created without billingInformation reads back with billingInformation: null until it is paid. If your callback or reporting code reads the customer’s email off the payment, guard for that case.

Choosing the installment plans

By default the checkout offers every installment plan active on your account, and the customer picks one. Send allowedTerms to decide the financing yourself: the checkout offers only the plans you list, and the customer cannot choose any other. Each entry is a number of monthly installments, the same terms a payment carries once it is paid. 1 is a single payment, and any larger number is that many months without interest (MSI).
Rules for the list:
  • Every entry must be a whole number from 1 to 48, and the list cannot be empty. To offer every plan, leave the field out.
  • Every entry must be a plan active on your account when you create the payment. Otherwise the request is rejected with ALLOWED_TERMS_UNAVAILABLE, and the response lists both the terms that are not available and the ones that are.
  • Duplicates are removed and the list is stored sorted, so [12, 3, 12] is saved as [3, 12]. GET /developer/v1/one-time-payment/{id} returns it as allowedTerms.
Months without interest require a credit card. When a payment offers only installment plans, a customer paying with a debit card is asked to use a credit card instead.
The plans on your account can change after you create the payment, for example if a plan is deactivated. The checkout never replaces a plan you listed with one you did not: a plan that stops being available is simply no longer offered, and if none of your listed plans is still available the checkout shows that the payment cannot be completed. If a plan stops being available while the customer is paying, the charge is refused and nothing is taken from the card.

Display Modes

Compago supports two display modes for the one-time payment checkout experience. In LINK mode, you redirect the customer to the redirectUrl returned by the API. The customer completes the payment on a full-page Compago checkout page and is then redirected back to your redirectUrl with id and externalId query parameters. This is the simplest integration. Just redirect the customer:

EMBEDDED Mode

In EMBEDDED mode, you embed the checkout URL in an iframe on your own page. This keeps the customer on your site throughout the process. Customize the submit button using buttonText and buttonColor.
Embed the checkout URL in your page:
These dimensions are sized to comfortably contain the standard 3DS challenge window the buyer’s bank may render during payment authorization. Smaller envelopes risk clipping the bank’s verification dialog.
In EMBEDDED mode, the iframe handles the entire payment flow. Listen for iframe events to react to loading, success, and error states in real time. The iframe never self-redirects — your parent page decides what to render after a successful payment.

Iframe Events (EMBEDDED Mode)

In EMBEDDED mode, the checkout iframe sends postMessage events to the parent window so you can react without waiting for a redirect.

Events Reference

Listening for Events

Error Codes

The error.code field on COMPAGO_ONE_TIME_PAYMENT_ERROR events lets you distinguish failure modes:
Validate that event.data.type starts with COMPAGO_ONE_TIME_PAYMENT_ before processing. This filters out unrelated postMessage events from other scripts or browser extensions.
Even when using iframe events, always verify the payment status via the API before fulfilling the order. The COMPAGO_ONE_TIME_PAYMENT_SUCCESS event confirms the checkout completed, but your backend should call GET /api/one-time-payment/{id} to confirm the status is CONFIRMED.

Handling the Payment Callback

When a customer successfully completes a payment, Compago redirects them back to your redirectUrl with two query parameters automatically appended:
  • id: The Compago one-time payment ID
  • externalId: The external ID you provided when creating the payment
This allows you to identify which payment completed and take appropriate action in your system.

How the Redirect Works

If you created a payment with:
And Compago returns payment ID aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee, then after the customer completes payment, they’ll be redirected to:

Implementation Example

Here’s how to handle the callback in your application:

Best Practices for Callback Handling

Never trust the redirect alone. Always fetch the payment details from Compago’s API to confirm the status. The redirect happens client-side and could be manipulated.
Implement validation to handle cases where query parameters might be missing (user navigating directly to the URL, etc.).
The callback URL might be accessed multiple times (user refreshing page, browser back button). Ensure your fulfillment logic is idempotent.
Always use HTTPS URLs for your redirectUrl to ensure query parameters are transmitted securely.
If your redirectUrl already contains query parameters, Compago will append id and externalId to them. Design your callback handler to work with multiple parameters.

Security Considerations

Never skip verification! The redirect URL is visible to the customer and could potentially be manipulated. Always fetch the payment status from Compago’s API using the id parameter before fulfilling the order.
Your callback implementation should:
  1. Validate query parameters exist before processing
  2. Fetch payment status from Compago API - Don’t trust the redirect alone
  3. Verify the externalId matches your records - Ensure it corresponds to a real order in your system
  4. Check payment status is CONFIRMED before fulfilling the order
  5. Log all callback attempts for debugging and security monitoring
  6. Use rate limiting on your callback endpoint to prevent abuse

Testing Your Callback Handler

To test your callback implementation:
  1. Create a one-time payment using your test API key
  2. Complete the payment in the Compago checkout page
  3. Verify your callback page receives the id and externalId parameters
  4. Confirm your system correctly fetches and processes the payment status
  5. Test the failure case by creating a payment and letting it expire
You can also manually test by navigating to your callback URL with test parameters:
(Your code should handle this gracefully, likely returning a “payment not found” or similar error.)

Important Business Rules

Payment Expiration

One-time payment links expire 48 hours after creation by default. If a customer does not complete the payment within this time, the link becomes invalid and cannot be used.
You can customize the expiration time using the ttlMinutes parameter (see Custom Expiration Times below). If your OTP expired and you need to create a new payment for the same transaction, generate a new OTP using a different externalId.

Custom Expiration Times

You can set a custom expiration time for payment links using the optional ttlMinutes parameter. This allows you to create payment links that expire sooner or later based on your business needs. Configuration:
  • Minimum: 10 minutes
  • Maximum: 2,880 minutes (48 hours)
  • Default: 2,880 minutes (48 hours) if not specified
Common use cases:
For time-sensitive promotions or limited inventory:
Use short expiration times (10-60 minutes) to create urgency and ensure inventory isn’t held indefinitely.
For typical invoice payments:
The default 48-hour window gives customers plenty of time to complete payment at their convenience.
For event registrations with registration deadlines:
Match the TTL to your event registration deadline to automatically close registration.
For quotes that customers need time to review:
Give customers the maximum time to review and approve quotes before they expire.
Best practices:
  • Balance security and convenience when setting expiration times
  • Shorter TTLs (10-60 min) work well for in-person transactions or time-sensitive offers
  • Longer TTLs (12-48 hours) are better for invoices and asynchronous payment flows
  • Consider your customer’s payment behavior and typical checkout time
  • Communicate the expiration time to customers (e.g., “Complete payment within 30 minutes”)

Minimum Amount

Each Compago account has a configured minimum payment amount. Requests with amounts below this threshold will be rejected with a 400 error. If you receive this error, ensure your payment amount meets your account’s minimum requirement.

External ID Uniqueness

The externalId must be unique within your organization. Attempting to create a payment with a duplicate externalId will result in a 400 error:
Use unique identifiers for each payment attempt. If a payment fails or expires, create a new one-time payment with a new externalId.

Currency Restriction

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

Payment Status

One-time payments have three statuses:
  • PENDING: Payment link is active and waiting for customer to complete payment
  • CONFIRMED: Customer has successfully completed the payment
  • CANCELLED: Payment link has been cancelled and can no longer be used
Once a payment is marked as CONFIRMED or CANCELLED, the one-time payment link can no longer be used. See the Cancel One-Time Payment guide to learn how to cancel pending payments.

Retrieving Payment Details

You can retrieve the status and details of a one-time payment using the GET endpoint. Common use case: After receiving a payment callback at your redirectUrl, use the id query parameter to fetch the payment status and verify completion before fulfilling the order. See Handling the Payment Callback for complete implementation examples.

Endpoint

API reference: GET /one-time-payment/{id}

Response for Active Payments

If the payment is still PENDING and has not expired, you’ll receive full payment details:

Response for Completed or Expired Payments

If the payment is no longer PENDING or has expired, the response will contain limited information:
The expired field indicates whether the payment link has passed its 48-hour expiration time, regardless of its status.

Supported Mexican States

Use the following state codes in the address.state field:

Error Handling

Common Errors

Example Error Response

An allowedTerms entry that is not active on your account also carries a code to branch on, and both lists:

Best Practices

  1. Generate Unique External IDs: Use a combination of order ID and timestamp to ensure uniqueness
  2. Handle Expiration: Implement logic to create new payment links if the 48-hour window expires
  3. Validate Amounts: Ensure amounts meet your account’s minimum payment threshold before calling the API
  4. Store Payment IDs: Save the returned one-time payment ID to track and verify payments later
  5. Implement Webhooks: Use webhooks (if available) to receive real-time payment status updates
  6. Test Thoroughly: Use the demo environment to test your integration before going live
  7. Implement Robust Callback Handling: Always verify payment status in your redirectUrl callback by fetching the payment using the id query parameter. Never assume payment success based on the redirect alone. See Handling the Payment Callback.

Support

If you encounter issues with one-time payments:
  • Verify your API key is valid in Configuraciones → Desarrollador of the dashboard of the environment you call (Demo or Production), and that you call the host of that same environment
  • Ensure all required fields are included in your request
  • Check that amounts meet the minimum threshold
  • Verify your organization settings are configured correctly
  • Contact Compago support at help@compago.com for assistance