---
title: "Accept a payment"
description: "Accept one-time payments with Inttegro in two simple steps: create an order and confirm payment."
canonical: "https://studio.inttegro.com/guides/accept-a-payment"
format: inttegro-machine-docs/v1
language: "TypeScript"
sdk_version: "v12.0.0"
reader_profile: optional
reader_manifest: "https://studio.inttegro.com/machine/typescript/readers/index.json"
reader_identification: "Optional: declare your client only if known and your current-session capabilities; use reader_manifest for supplemental recommendations."
preamble_estimated_tokens: 514
model_token_report: "https://studio.inttegro.com/machine/token-report.json"
preamble_questions: 5
preamble_source: "curated"
recommended_mcp_tools: ["get_integration_guide","check_integration_readiness","get_order"]
estimated_tokens: 3480
token_estimate_method: "utf8_bytes_divided_by_4"
---

## Machine preamble

**Summary:** Start one payment from an order, complete the requested customer confirmation, and read the order again before treating it as paid.

### Five questions

#### Q1. Which create-order fields choose the customer and start payment?

Use customer data for a new customer or a customer ID for a returning one, supply line items and payment-method details, and set execute-payment to true. [Create an order](https://studio.inttegro.com/machine/typescript/api/orders.md#create-an-order) defines the selected language's exact parameter names and response.

#### Q2. Does creating the order finish the charge?

No. Creation may begin payment and return a confirmation action. Use [Confirm a payment](https://studio.inttegro.com/machine/typescript/api/orders.md#confirm-a-payment) when the flow requests the customer's OTP; provider authorization can continue after that call.

#### Q3. What if the create request has an uncertain response?

Preserve the original request and its stable idempotency key. Consult [Idempotent requests](https://studio.inttegro.com/machine/typescript/api/idempotency.md) before retrying, then look up the order by its saved ID rather than starting a duplicate purchase.

#### Q4. What is the completion check?

[Look up the order](https://studio.inttegro.com/machine/typescript/api/orders.md#lookup-an-order) and inspect its current order and payment states. An accepted confirmation, delivered OTP, or provider prompt is not proof of a paid outcome.

#### Q5. Where can MCP help without handling the customer token?

With an authenticated connection, [create_order](https://studio.inttegro.com/machine/typescript/inttegro-mcp/tools.md#create_order) creates without executing payment. [pay_order](https://studio.inttegro.com/machine/typescript/inttegro-mcp/tools.md#pay_order) can start it after exact amount and masked-method confirmation; new details and OTP stay in secure Checkout. Use [get_order](https://studio.inttegro.com/machine/typescript/inttegro-mcp/tools.md#get_order) to verify the outcome.

## Document 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.

> Mcp Guide Callout is interactive content. Use the canonical page to view it.

## 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](https://studio.inttegro.com/machine/typescript/guides/order-lifecycle.md)** 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**

```typescript
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: "gloria@example.com",
    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](https://studio.inttegro.com/machine/typescript/api/orders.md#the-order-object) for all available fields.

```json
{
  "order": {
    "id": "or_48ZW7BGvYUBWc1i6WBkL2jr0iPQP5jUy76mmmHpt",
    "status": "requires_payment",
    "customer": {
      "id": "cu_abc123",
      "name": "Gloria Kesewaa",
      "email_address": "gloria@example.com"
    },
    "payment": {
      "id": "py_xyz789",
      "status": "requires_action",
      "payment_method": {
        "id": "pm_saved_method",
        "type": "mobile_money",
        "network": "mtn"
      },
      "next_action": {
        "type": "confirm_payment",
        "confirm_payment": {
          "expires_at": "2025-01-13T10:08:00Z",
          "request": {
            "id": "otc_req_8Ks2Vn",
            "recipient": "0544998605",
            "sent_via": "sms"
          }
        }
      }
    }
  }
}
```

**Key attributes**:

- [`order.id`](https://typescript.inttegro.dev/v12.0.0)
  - Store this for the next step
- [`payment.nextAction.type`](https://typescript.inttegro.dev/v12.0.0)
  :
  `"confirm_payment"`
  - OTP collection needed
- [`order.payment.nextAction.confirmPayment.expiresAt`](https://typescript.inttegro.dev/v12.0.0)
  - OTP expires in ~8 minutes
- [`customer.id`](https://typescript.inttegro.dev/v12.0.0)
  - Save for future orders from this customer
- [`order.payment.paymentMethod.id`](https://typescript.inttegro.dev/v12.0.0)
  - Save to charge this customer again without re-entering payment details

## 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[`order.payment.id`](https://typescript.inttegro.dev/v12.0.0) as `payment_id` and[`order.payment.nextAction.confirmPayment.request.id`](https://typescript.inttegro.dev/v12.0.0) as `confirmation_id`, then submit those values with `orderId` and
> `token`.

**Confirm payment — POST /orders/confirm\_payment**

```typescript
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**

```typescript
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 [`order.payment.customer.id`](https://typescript.inttegro.dev/v12.0.0) and [`order.payment.paymentMethod.id`](https://typescript.inttegro.dev/v12.0.0)—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](https://studio.inttegro.com/machine/typescript/guides/charge-repeat-customers.md)** 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 [`order.lineItemGroup.total`](https://typescript.inttegro.dev/v12.0.0) field of the response.

**Create a multi-item order — POST /orders/create**

```typescript
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**

```typescript
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 `"requires_payment"` status and its latest payment attempt is marked `"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 [`order.payment.latestAttempt`](https://typescript.inttegro.dev/v12.0.0). You can prompt the customer to add funds and retry, or offer another payment method.

**Look up the order — POST /orders/lookup**

```typescript
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](https://studio.inttegro.com/machine/typescript/api/orders.md#confirm-a-payment) with `orderId`, `payment_id`, `confirmation_id`, 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 [`order.id`](https://typescript.inttegro.dev/v12.0.0) 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

- **[Charge repeat customers](https://studio.inttegro.com/machine/typescript/guides/charge-repeat-customers.md)** - Fast checkout for returning customers

- **[Retry payment with new payment method](https://studio.inttegro.com/machine/typescript/guides/retry-a-payment.md)** - Retry failed payments with alternative methods

- **[Order now, pay later](https://studio.inttegro.com/machine/typescript/guides/order-now-pay-later.md)** - Create orders without immediate payment

- **[Orders API](https://studio.inttegro.com/machine/typescript/api/orders.md)** - Full API reference with all parameters

- **[Refunds](https://studio.inttegro.com/machine/typescript/api/refunds.md)** - Handle returns and cancellations

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