Skip to main content

Accept a payment

This guide shows you how to accept a one-time payment. You'll create an order with payment details, confirm customer intent with an OTP, then wait for payment authorization. The entire flow takes two API calls and about 30 seconds.

Use MCP to prepare and track a payment

An authenticated AI agent can create an unpaid order, then start payment with pay_order only after you confirm the exact amount and masked method. New payment details and OTP stay in secure Inttegro Checkout; get_order verifies the outcome.

MCP tools: create_order, pay_order or get_order

Confirmed MCP actions require explicit form confirmation before Inttegro changes state.

How it works

Every payment follows a three-phase pattern: create the order, confirm customer intent with an OTP, then wait for provider authorization. The entire flow typically completes in under 30 seconds. For detailed information on order and payment status transitions at each step, see the Order lifecycle guide.

Step 1: create the order

Creating an order bundles everything about the transaction—who's paying, what they're buying, and how they'll pay—into a single atomic unit. You'll provide either customerData for new customers or customerId for returning ones, along with lineItems describing the products, fees, or shipping charges. When you set executePayment: true, Inttegro begins payment execution and sends a 6-digit OTP to the customer's phone.

Create order

POST/orders/create
SDK versionv12.0.0
import * as Inttegro from '@inttegro/inttegro-sdk'

const inttegro = new Inttegro.InttegroClient({
apiKey: process.env.INTTEGRO_API_KEY!,
})
const result = await inttegro.orders.create({
requestMeta: {
idempotencyKey: "order_2025_001",
},
executePayment: true,
customerData: {
name: "Gloria Kesewaa",
emailAddress: "[email protected]",
phoneNumber: "+233544998605",
},
paymentMethodData: {
type: Inttegro.PaymentMethodTypes.MobileMoney,
mobileMoney: {
network: Inttegro.MobileMoneyNetworks.MTN,
accountNumber: "0544998605",
},
},
lineItems: [
{
type: Inttegro.LineItemTypes.Product,
product: {
type: Inttegro.ProductTypes.Physical,
name: "Utility Sneakers",
quantity: 1,
price: {
currency: "ghs",
value: 20000,
},
},
},
],
})

Response​

Note

This is a partial response showing key attributes. See the complete Order object for all available fields.

Response excerpt

SDK versionv12.0.0
OrderResponse {
order: { … },
}

Key attributes:

Step 2: confirm customer intent with OTP

The customer receives a confirmation token. Collect it through your UI and submit it with the order, payment, and confirmation-request IDs from the preceding response. Those four values bind the token to the exact payment action being confirmed.

Note

Confirmation is bound to one order, payment, and confirmation request. Use

payment.id

as

paymentId

and

payment.nextAction.confirmPayment.id

as

confirmationId

, then submit those values with

orderId

and token.

Confirm payment

POST/orders/confirm_payment
SDK versionv12.0.0
import * as Inttegro from '@inttegro/inttegro-sdk'

const inttegro = new Inttegro.InttegroClient({
apiKey: process.env.INTTEGRO_API_KEY!,
})
const result = await inttegro.orders.confirmPayment({
confirmationId: "otc_req_8Ks2Vn",
orderId: "or_48ZW7BGvYUBWc1i6WBkL2jr0iPQP5jUy76mmmHpt",
paymentId: "py_xyz789",
token: "302673",
})

After confirmation, check the order status before fulfilling it:

Check status

POST/orders/lookup
SDK versionv12.0.0
import * as Inttegro from '@inttegro/inttegro-sdk'

const inttegro = new Inttegro.InttegroClient({
apiKey: process.env.INTTEGRO_API_KEY!,
})
const result = await inttegro.orders.lookup({
orderId: "or_48ZW7BGvYUBWc1i6WBkL2jr0iPQP5jUy76mmmHpt",
})

What happens after payment

When you create an order with customerData and paymentMethodData, Inttegro automatically creates a customer record and attaches the payment method to it. The response includes both payment.customer.id and payment.paymentMethod.id—store these for future use. Next time this customer checks out, you can skip collecting their details again and charge them instantly. See Charge repeat customers to learn how.

Common patterns

Multiple items​

Real shopping carts contain more than just products—there are shipping charges, processing fees, and taxes. The lineItems array supports three types: "product", "shipping", and "fee". Each line item has its own structure with a lineItems[].type discriminator and a nested object containing the details. Inttegro automatically sums all the line items to calculate the order total, which you'll see in the lineItemGroup.total field of the response.

Create a multi-item order

POST/orders/create
SDK versionv12.0.0
import * as Inttegro from '@inttegro/inttegro-sdk'

const inttegro = new Inttegro.InttegroClient({
apiKey: process.env.INTTEGRO_API_KEY!,
})
const result = await inttegro.orders.create({
requestMeta: {
idempotencyKey: "multi_item_order_001",
},
customerId: "cu_abc123",
lineItems: [
{
type: Inttegro.LineItemTypes.Product,
product: {
type: Inttegro.ProductTypes.Physical,
name: "Shoes",
quantity: 2,
price: {
currency: "ghs",
value: 25000,
},
},
},
{
type: Inttegro.LineItemTypes.Shipping,
shipping: {
fee: {
currency: "ghs",
value: 2000,
},
},
},
{
type: Inttegro.LineItemTypes.Fee,
fee: {
label: "Processing fee",
amount: {
currency: "ghs",
value: 500,
},
},
},
],
})

Handling errors

OTP expired or wrong​

OTP codes expire after about 8 minutes, and customers sometimes mistype them. When either happens, call /orders/request_confirmation to generate and send a fresh code. The customer can retry with the new code without losing their order or having to start over.

Send a new confirmation token

POST/orders/request_confirmation
SDK versionv12.0.0
import * as Inttegro from '@inttegro/inttegro-sdk'

const inttegro = new Inttegro.InttegroClient({
apiKey: process.env.INTTEGRO_API_KEY!,
})
const result = await inttegro.orders.requestConfirmation({
orderId: "or_48ZW7BGvYUBWc1i6WBkL2jr0iPQP5jUy76mmmHpt",
})

Customer doesn't have funds​

If the customer approves the payment but their mobile money account has insufficient balance, the payment attempt fails after OTP confirmation. The order remains in Inttegro.OrderStatuses.RequiresPayment status and its latest payment attempt is marked Inttegro.PaymentAttemptStatuses.Failed. Keep the API error from the confirmation request for the reason you show in logs or support tooling; the order object does not repeat that error code in payment.latestAttempt. You can prompt the customer to add funds and retry, or offer another payment method.

Look up the order

POST/orders/lookup
SDK versionv12.0.0
import * as Inttegro from '@inttegro/inttegro-sdk'

const inttegro = new Inttegro.InttegroClient({
apiKey: process.env.INTTEGRO_API_KEY!,
})
const result = await inttegro.orders.lookup({
orderId: "or_48ZW7BGvYUBWc1i6WBkL2jr0iPQP5jUy76mmmHpt",
})

Testing

Use an application configured for the test environment and only payment details and confirmation values supplied for that environment. When a payment requires confirmation, follow Confirm a payment with orderId, paymentId, confirmationId, and the supplied token; do not hardcode a universal token value.

Key tips

Phone format: Mobile money providers require phone numbers in E.164 format with country code (e.g., +233544998605). If customers enter local format like 0544998605, prepend the country code before sending to Inttegro—otherwise the OTP won't be delivered.

Store order ID: The moment you receive the order creation response, persist id to your database. You'll need this ID for payment confirmation, status lookups, and linking the Inttegro order to your internal records. Don't wait until after OTP confirmation—store it immediately.

Complete flow

The language-aware samples above form the complete integration path: create the order, submit confirmation when the response requires it, and look up the order before fulfillment. The selector in the toolbar keeps every request in the same SDK language.

Next steps

That's it! You're ready to accept payments.