Accept payment with Inttegro Checkout
Create an order and redirect your customer to the invoice URL. Inttegro handles the payment flow, OTP verification, and receipt generation.
Recommended approach. See Inttegro Checkout for why this works better than custom checkout.
Step 1: Create an order
Call /orders/create with customer details, line items, and finalize: true. Finalization seals the order and generates its hosted invoice URLs. Store the order ID for status tracking.
Create order
- cURL
- TypeScript
- Go
- Python
- PHP
- Ruby
- Java
- C#
curl https://api.inttegro.com/orders/create \
-H "Authorization: Bearer $INTTEGRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"request_meta": {
"idempotency_key": "order_inv_001"
},
"customer_data": {
"name": "Gloria Kesewaa",
"email_address": "[email protected]",
"phone_number": "+233544998605"
},
"finalize": true,
"line_items": [
{
"type": "product",
"product": {
"type": "physical",
"name": "Utility Sneakers",
"quantity": 1,
"price": {
"currency": "ghs",
"value": 20000
}
}
}
]
}'
import { CommerceClient } from '@zebo-commerce/typescript-sdk'
const commerce = new CommerceClient({
apiKey: process.env.INTTEGRO_API_KEY!,
})
const result = await commerce.orders.create({
"request_meta": {
"idempotency_key": "order_inv_001"
},
"customer_data": {
"name": "Gloria Kesewaa",
"phone_number": "+233544998605"
},
"finalize": true,
"line_items": [
{
"type": "product",
"product": {
"type": "physical",
"name": "Utility Sneakers",
"quantity": 1,
"price": {
"currency": "ghs",
"value": 20000
}
}
}
]
})
package main
import (
"context"
"encoding/json"
"log"
"os"
commerce "github.com/zebodotdev/commerce-sdk-go"
)
func main() {
ctx := context.Background()
client := commerce.NewClient(os.Getenv("INTTEGRO_API_KEY"))
var params commerce.OrderCreateParams
if err := json.Unmarshal([]byte(`{
"request_meta": {
"idempotency_key": "order_inv_001"
},
"customer_data": {
"name": "Gloria Kesewaa",
"email_address": "[email protected]",
"phone_number": "+233544998605"
},
"finalize": true,
"line_items": [
{
"type": "product",
"product": {
"type": "physical",
"name": "Utility Sneakers",
"quantity": 1,
"price": {
"currency": "ghs",
"value": 20000
}
}
}
]
}`), ¶ms); err != nil {
log.Fatal(err)
}
result, err := client.Orders.Create(ctx, params)
if err != nil {
log.Fatal(err)
}
_ = result
}
import os
from commerce import CommerceClient
client = CommerceClient(api_key=os.environ["INTTEGRO_API_KEY"])
result = client.orders.create({
"request_meta": {
"idempotency_key": "order_inv_001",
},
"customer_data": {
"name": "Gloria Kesewaa",
"phone_number": "+233544998605",
},
"finalize": True,
"line_items": [
{
"type": "product",
"product": {
"type": "physical",
"name": "Utility Sneakers",
"quantity": 1,
"price": {
"currency": "ghs",
"value": 20000,
},
},
},
],
})
<?php
use Commerce\Client;
$client = new Client($_ENV['INTTEGRO_API_KEY']);
$result = $client->orders->create([
'request_meta' => [
'idempotency_key' => 'order_inv_001',
],
'customer_data' => [
'name' => 'Gloria Kesewaa',
'phone_number' => '+233544998605',
],
'finalize' => true,
'line_items' => [
[
'type' => 'product',
'product' => [
'type' => 'physical',
'name' => 'Utility Sneakers',
'quantity' => 1,
'price' => [
'currency' => 'ghs',
'value' => 20000,
],
],
],
],
]);
require "commerce"
client = Commerce::Client.new(api_key: ENV.fetch("INTTEGRO_API_KEY"))
result = client.orders.create({
request_meta: {
idempotency_key: "order_inv_001",
},
customer_data: {
name: "Gloria Kesewaa",
phone_number: "+233544998605",
},
finalize: true,
line_items: [
{
type: "product",
product: {
type: "physical",
name: "Utility Sneakers",
quantity: 1,
price: {
currency: "ghs",
value: 20000,
},
},
},
],
})
import com.zebodotdev.commerce.CommerceClient;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zebodotdev.commerce.model.OrderModels.OrderCreateParams;
public class Example {
public static void main(String[] args) throws Exception {
var client = new CommerceClient(System.getenv("INTTEGRO_API_KEY"));
var mapper = new ObjectMapper();
var params = mapper.readValue("""
{
"request_meta": {
"idempotency_key": "order_inv_001"
},
"customer_data": {
"name": "Gloria Kesewaa",
"email_address": "[email protected]",
"phone_number": "+233544998605"
},
"finalize": true,
"line_items": [
{
"type": "product",
"product": {
"type": "physical",
"name": "Utility Sneakers",
"quantity": 1,
"price": {
"currency": "ghs",
"value": 20000
}
}
}
]
}
""", OrderCreateParams.class);
var result = client.orders().create(params);
}
}
using Commerce;
using var commerce = new CommerceClient(
Environment.GetEnvironmentVariable("INTTEGRO_API_KEY")!
);
var result = await commerce.Orders.CreateAsync(new {
request_meta = new {
idempotency_key = "order_inv_001",
},
customer_data = new {
name = "Gloria Kesewaa",
phone_number = "+233544998605",
},
finalize = true,
line_items = new[] {
new {
type = "product",
product = new {
type = "physical",
name = "Utility Sneakers",
quantity = 1,
price = new {
currency = "ghs",
value = 20000,
},
},
},
},
});
Response
Partial response. See complete Order object.
{
"order": {
"id": "or_XyZ9kL2mQrTfVqYz1wNb",
"number": "INV-2025-001",
"status": "requires_payment",
"invoice": {
"format": {
"web": {
"url": "https://pages.inttegro.com/invoices/or_XyZ9kL2mQrTfVqYz1wNb"
},
"pdf": {
"url": "https://pages.inttegro.com/invoices/or_XyZ9kL2mQrTfVqYz1wNb/pdf"
}
}
}
}
}
Step 2: Direct customer to payment
Choose how to get the customer to the payment page:
- Redirect immediately
- Share invoice link
Extract response.order.invoice.format.web.url from the response envelope and return it to your client. Check that order.invoice is present before redirecting; it is omitted when the order is still a draft.
// Server: Return URL to client
return {
invoiceURL: response.order.invoice.format.web.url,
}
// Client: Redirect to invoice
const response = await fetch('/api/create-order', { ... })
const { invoiceURL } = await response.json()
window.location.href = invoiceURL
If immediate redirect doesn't fit your flow, share the URL asynchronously. Send it through email, SMS, WhatsApp, or your notification system—the URL works in any browser context. Useful for offline orders, delayed billing, or when the customer isn't in your app.
const invoiceURL = response.order.invoice.format.web.url
// Send via your notification system
Step 3: Track payment status
Use /orders/lookup to check payment status. Poll periodically or check when the customer returns to your app. When status becomes "paid", funds are in your Inttegro balance.
Check status
- cURL
- TypeScript
- Go
- Python
- PHP
- Ruby
- Java
- C#
curl https://api.inttegro.com/orders/lookup \
-H "Authorization: Bearer $INTTEGRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"order_id": "or_XyZ9kL2mQrTfVqYz1wNb"
}'
import { CommerceClient } from '@zebo-commerce/typescript-sdk'
const commerce = new CommerceClient({
apiKey: process.env.INTTEGRO_API_KEY!,
})
const result = await commerce.orders.lookup({
"order_id": "or_XyZ9kL2mQrTfVqYz1wNb"
})
package main
import (
"context"
"log"
"os"
commerce "github.com/zebodotdev/commerce-sdk-go"
)
func main() {
ctx := context.Background()
client := commerce.NewClient(os.Getenv("INTTEGRO_API_KEY"))
result, err := client.Orders.Lookup(ctx, "or_XyZ9kL2mQrTfVqYz1wNb")
if err != nil {
log.Fatal(err)
}
_ = result
}
import os
from commerce import CommerceClient
client = CommerceClient(api_key=os.environ["INTTEGRO_API_KEY"])
result = client.orders.lookup("or_XyZ9kL2mQrTfVqYz1wNb")
<?php
use Commerce\Client;
$client = new Client($_ENV['INTTEGRO_API_KEY']);
$result = $client->orders->lookup("or_XyZ9kL2mQrTfVqYz1wNb");
require "commerce"
client = Commerce::Client.new(api_key: ENV.fetch("INTTEGRO_API_KEY"))
result = client.orders.lookup(order_id: "or_XyZ9kL2mQrTfVqYz1wNb")
import com.zebodotdev.commerce.CommerceClient;
public class Example {
public static void main(String[] args) throws Exception {
var client = new CommerceClient(System.getenv("INTTEGRO_API_KEY"));
var result = client.orders().lookup("or_XyZ9kL2mQrTfVqYz1wNb");
}
}
using Commerce;
using var commerce = new CommerceClient(
Environment.GetEnvironmentVariable("INTTEGRO_API_KEY")!
);
var result = await commerce.Orders.LookupAsync("or_XyZ9kL2mQrTfVqYz1wNb");
Customization
Configure redirect and cancel URLs
{
"checkout_settings": {
"redirect_url": "https://yoursite.com/order/complete",
"cancel_url": "https://yoursite.com/order/cancelled"
}
}
Strongly recommended for a delightful customer experience. When payment completes, customers land on your redirect_url where you can show order confirmation and next steps. When customers abandon checkout without paying, they land on your cancel_url where you can show incomplete order details or offer alternative payment methods.
Set payment due time
{
"payment_due_after": "2026-09-15T23:59:59Z"
}
Use an RFC 3339 timestamp. The value is returned as payment_due_at on the order.
Add line item details
{
"product": {
"name": "Utility Sneakers",
"about": "Size: 42 | Color: Black"
}
}
Appears below product name on invoice.
Update branding
Change logo, business name, and colors in the Inttegro dashboard under Settings → Branding. Applies to all new invoices instantly.
See Checkout customization for more options.
Common patterns
Subscriptions: Create new order each cycle, send new invoice URL.
Deposits: Create separate orders for deposit and balance. Link via reference field.
Multi-currency: Create one order per currency.
Order limits: Each order can contain up to 64 line items. Order totals are capped at 100,000 for ghs and 50,000 for all other supported currencies, measured in the currency's smallest unit. Contact support if you need these limits increased.
See Common patterns for implementation details.
Next steps
- Inttegro Checkout — Why Inttegro Checkout works better than custom checkout
- Orders — Complete order API reference
- Accept a payment — Build custom checkout (advanced)