API Documentation
Integrate OrderConfirm's AI confirmation calls into your store with a simple REST API.
Overview
The OrderConfirm API lets you submit e-commerce orders and have an AI voice agent call your customers to confirm them — in Bangla or English. Send an order, trigger a confirmation call, and receive the outcome (confirmed, cancelled, or needing human follow-up) along with a recording and transcript. Delivery-address replacements are persisted on the order.
All endpoints are relative to the base URL:
https://api.orderconfirm.io/api/v1The typical lifecycle is: create an order → trigger a call → the agent dials your customer → you receive the result via webhook or by polling the call.
Authentication
Create an API key in the dashboard at /app/tokens and send it as the X-API-Key header on every ingestion request.
X-API-Key: ocb_live_your_key_hereYour key is shown only once
Step-by-step integration
- 01
Get an API key
Create a key in the dashboard and store it securely — it is shown only once.
- 02
Create an order
POST the order with customer phone and items to /ingest/orders.
- 03
Trigger a confirmation call
Queue a call with POST /ingest/orders/:id/calls, optionally choosing an agent.
- 04
Receive results
Poll GET /ingest/calls/:id or receive a webhook when the call completes.
Create order — request body
POST https://api.orderconfirm.io/api/v1/ingest/orders
| Field | Type | Description |
|---|---|---|
| order_id | string | Your store's order reference. |
| customer_name | string | Full name of the customer. |
| customer_phone | string | E.164 phone number, e.g. +8801712345678. |
| customer_address | string | Delivery address read back during the call; the customer may replace it. |
| country | string | ISO country code, e.g. BD. |
| language | string | Spoken language: bn or en. |
| items | array | Line items: product_name, product_price, product_quantity, and optional metadata attributes. |
Trigger a call — available agents
POST https://api.orderconfirm.io/api/v1/ingest/orders/:id/calls — pass an optional agent_id to pick a voice.
| Agent | agent_id | Description |
|---|---|---|
| Asif | a51f0000-0000-4000-8000-000000000001 | Default Bangla order-confirmation agent. |
| Alex | a1e70000-0000-4000-8000-000000000002 | English agent with the same flow and personality as Asif. |
Omit agent_id to use the default agent selected in the agent registry.
How a confirmation flows
This sequence shows the full lifecycle from creating an order to receiving the result.
Examples
Each request needs the X-API-Key header. Values below use realistic Bangladesh data.
curl -X POST https://api.orderconfirm.io/api/v1/ingest/orders \
-H "X-API-Key: ocb_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"order_id": "ORD-10231",
"customer_name": "Rahim Uddin",
"customer_phone": "+8801712345678",
"customer_address": "House 12, Road 5, Dhanmondi, Dhaka",
"country": "BD",
"language": "bn",
"items": [
{ "product_name": "Cotton Panjabi", "product_price": 1450, "product_quantity": 2,
"metadata": { "color": "black", "size": "L" } },
{ "product_name": "Leather Sandals", "product_price": 990, "product_quantity": 1,
"metadata": { "size": "42" } }
]
}'{
"order_id": "ORD-10231",
"customer_name": "Rahim Uddin",
"customer_phone": "+8801712345678",
"customer_address": "House 12, Road 5, Dhanmondi, Dhaka",
"country": "BD",
"language": "bn",
"items": [
{ "product_name": "Cotton Panjabi", "product_price": 1450, "product_quantity": 2,
"metadata": { "color": "black", "size": "L" } },
{ "product_name": "Leather Sandals", "product_price": 990, "product_quantity": 1,
"metadata": { "size": "42" } }
]
}{
"data": {
"id": "o1b2c3d4-0000-4000-8000-000000000abc",
"order_id": "ORD-10231",
"customer_name": "Rahim Uddin",
"customer_phone": "+8801712345678",
"customer_address": "House 12, Road 5, Dhanmondi, Dhaka",
"country": "BD",
"language": "bn",
"items": [
{ "product_name": "Cotton Panjabi", "product_price": 1450, "product_quantity": 2,
"metadata": { "color": "black", "size": "L" } },
{ "product_name": "Leather Sandals", "product_price": 990, "product_quantity": 1,
"metadata": { "size": "42" } }
],
"created_at": "2026-06-24T09:30:00Z"
}
}Webhooks
Instead of polling, configure a webhook URL at /app/webhook to receive call lifecycle, conversation outcome, order state, and address-change events as they happen. OrderConfirm POSTs each event independently to your endpoint. In every payload, order_id is the value you supplied when creating the order, not the internal OrderConfirm UUID.
| Event | Description |
|---|---|
| call.placed | The customer answered and the confirmation call is in progress. |
| call.completed | The call finished. Carries the business result, duration, and recording. |
| call.failed | The call never connected (no answer, busy, declined, or undialable). |
| call.status_changed | The call lifecycle moved between pending, scheduled, in progress, redial, or a terminal state. |
| call.outcome_recorded | The precise managed conversation outcome and privacy-safe summary counts were recorded. |
| call.note_added | A structured note code was recorded; customer note text and values are not sent. |
| order.status_changed | The order moved to a managed status such as callback, modification, verification, or review. |
| order.modification_requested | A typed order change was applied or requested; customer-supplied values are not sent. |
| order.callback_requested | The customer requested a callback; only whether a time was supplied is sent. |
| order.do_not_call_requested | The customer asked not to receive another call. |
| address.changed | The customer changed the delivery address during the call. Carries the old and new addresses. |
Terminal call event payload
The call.placed, call.completed, and call.failed events carry all fields below, using null where a field does not apply.
| Field | Type | Description |
|---|---|---|
| call_id | string | The call this event belongs to. |
| order_id | string | The client-supplied order reference from the create-order request. |
| status | string | Call lifecycle: pending | scheduled | in_progress | in_redial | completed | failed | cancelled. |
| result | string | Business outcome: pending | confirmed | rejected | failed | human_intervention_needed. |
| outcome | string | Precise conversation path, for example callback_requested or modification_requested. |
| reason | string | null | Why the result needs attention, e.g. the agent's note on a human_intervention_needed call, not_answered, not_dialable, or max_duration_exceeded. Null when nothing needs explaining. |
| disposition | string | null | Phone response: received | rejected | busy | no_answer | unreachable. |
| duration_seconds | number | null | Talk time of the finished call. |
| recording_url | string | null | Recording of the finished call, when available. |
Managed state payloads
State events use the common identifiers below plus event-specific typed fields. Raw customer notes, callback times, preferred-language values, and requested order values stay in authenticated API responses and dashboards.
| Field | Type | Description |
|---|---|---|
| event_id | string | Stable idempotency suffix for this state signal within the call. |
| call_id | string | The call this state event belongs to. |
| order_id | string | Your client-supplied order reference. |
| previous_status / status | string | Previous and current lifecycle or order status on state-transition events. |
| result / outcome | string | Coarse result and exact conversation path where applicable. |
| code | string | Stable note code on call.note_added; note content remains private. |
| change_type / change_status | string | Typed modification and whether it was applied, requested, or needs review. |
| sequence | number | Zero-based ordering when a call records multiple notes or changes. |
| notes_count / changes_count | number | Structured issue counts on call.outcome_recorded. |
| presence flags | boolean | Privacy-safe flags such as has_note, has_value, has_requested_time, or has_requested_value. |
Address change payload
address.changed delivery starts after the replacement address is persisted. Every webhook runs independently from call settlement and from other webhook deliveries, so a bad endpoint cannot block the saved call result or recording, and event arrival order is not guaranteed.
| Field | Type | Description |
|---|---|---|
| call_id | string | The call during which the address was changed. |
| order_id | string | The client-supplied order reference from the create-order request. |
| old_address | string | The delivery address stored before the change. |
| new_address | string | The replacement delivery address supplied by the customer. |
Verifying webhook requests
Authorization: Bearer <auth_token> header. Reject any request whose token does not match yours. POST https://your-store.com/webhooks/orderconfirm
Authorization: Bearer <your_webhook_auth_token>
Content-Type: application/json
{
"event": "call.completed",
"payload": {
"call_id": "c9f8e7d6-0000-4000-8000-000000000def",
"order_id": "ORD-10231",
"status": "completed",
"result": "confirmed",
"outcome": "confirmed",
"reason": null,
"disposition": "received",
"duration_seconds": 74,
"recording_url": "https://recordings.orderconfirm.io/c9f8e7d6.mp3"
}
}
// Terminal call events carry these exact fields; values that do not apply are null.
// A human_intervention_needed result always explains itself, e.g.
// "result": "human_intervention_needed",
// "reason": "customer wants to change item quantity"POST https://your-store.com/webhooks/orderconfirm
Authorization: Bearer <your_webhook_auth_token>
Content-Type: application/json
{
"event": "address.changed",
"payload": {
"call_id": "c9f8e7d6-0000-4000-8000-000000000def",
"order_id": "ORD-10231",
"old_address": "House 12, Road 5, Dhanmondi, Dhaka",
"new_address": "House 7, Road 11, Uttara, Dhaka"
}
}