curl --request GET \
--url https://api.c2cpayment.net/api/merchant/orders/788fcae0-5214-403c-baa2-f318c0eb1b5b/status \
--header "C2C-API-Key: $C2C_API_KEY"
curl --request GET \
--url https://api.c2cpayment.net/api/merchant/orders/ORD-20261008120620-3f6b/status \
--header "C2C-API-Key: $C2C_API_KEY"
curl --request GET \
--url "https://api.c2cpayment.net/api/merchant/orders/status?merchantOrderRef=INV-10045" \
--header "C2C-API-Key: $C2C_API_KEY"
const BASE_URL = 'https://api.c2cpayment.net';
// Pass exactly one identifier: C2C's orderId or orderReference, or your merchantOrderRef.
async function getOrderStatus({ orderId, orderReference, merchantOrderRef }) {
const path = merchantOrderRef
? `/api/merchant/orders/status?merchantOrderRef=${encodeURIComponent(merchantOrderRef)}`
: `/api/merchant/orders/${encodeURIComponent(orderId ?? orderReference)}/status`;
const response = await fetch(`${BASE_URL}${path}`, {
headers: { 'C2C-API-Key': process.env.C2C_API_KEY },
});
if (!response.ok) throw new Error(`Status query failed: HTTP ${response.status}`);
return (await response.json()).data;
}
await getOrderStatus({ orderId: '788fcae0-5214-403c-baa2-f318c0eb1b5b' });
await getOrderStatus({ orderReference: 'ORD-20261008120620-3f6b' });
await getOrderStatus({ merchantOrderRef: 'INV-10045' });
import os
from urllib.parse import quote
import requests
BASE_URL = "https://api.c2cpayment.net"
def get_order_status(*, order_id=None, order_reference=None, merchant_order_ref=None) -> dict:
"""Pass exactly one identifier: C2C's order_id or order_reference, or your merchant_order_ref."""
if merchant_order_ref:
url, params = f"{BASE_URL}/api/merchant/orders/status", {"merchantOrderRef": merchant_order_ref}
else:
url, params = f"{BASE_URL}/api/merchant/orders/{quote(order_id or order_reference, safe='')}/status", None
response = requests.get(url, params=params, headers={"C2C-API-Key": os.environ["C2C_API_KEY"]})
response.raise_for_status()
return response.json()["data"]
get_order_status(order_id="788fcae0-5214-403c-baa2-f318c0eb1b5b")
get_order_status(order_reference="ORD-20261008120620-3f6b")
get_order_status(merchant_order_ref="INV-10045")
{
"data": {
"orderId": "788fcae0-5214-403c-baa2-f318c0eb1b5b",
"orderReference": "ORD-20261008120620-3f6b",
"status": "AwaitingMemberConfirmation",
"amount": 1500.0000,
"queuedAt": "2026-10-08T12:06:20.605646Z",
"confirmedAt": null,
"cancelledAt": null,
"merchantOrderRef": "INV-10045",
"orderType": "Deposit",
"currency": "PKR",
"fee": 30.0000,
"stage": "Sent",
"lifecycle": {
"stage": "Sent",
"createdAt": "2026-10-08T12:06:20.605646Z",
"awaitingAt": null,
"assignedAt": "2026-10-08T12:06:20.605646Z",
"sentAt": "2026-10-08T12:08:57.402113Z",
"approvedAt": null,
"rejectedAt": null,
"completedAt": null,
"failedAt": null
}
}
}
{
"data": {
"orderId": "788fcae0-5214-403c-baa2-f318c0eb1b5b",
"orderReference": "ORD-20261008120620-3f6b",
"status": "Completed",
"amount": 1500.0000,
"queuedAt": "2026-10-08T12:06:20.605646Z",
"confirmedAt": "2026-10-08T12:11:42.118204Z",
"cancelledAt": null,
"merchantOrderRef": "INV-10045",
"orderType": "Deposit",
"currency": "PKR",
"fee": 30.0000,
"stage": "Completed",
"lifecycle": {
"stage": "Completed",
"createdAt": "2026-10-08T12:06:20.605646Z",
"awaitingAt": null,
"assignedAt": "2026-10-08T12:06:20.605646Z",
"sentAt": "2026-10-08T12:08:57.402113Z",
"approvedAt": "2026-10-08T12:11:42.118204Z",
"rejectedAt": null,
"completedAt": "2026-10-08T12:11:42.118204Z",
"failedAt": null
}
}
}
{
"data": {
"orderId": "d1926af5-053d-4b39-a73b-c82f0d9af656",
"orderReference": "ORD-20261008120621-a7b8",
"status": "Awaiting",
"amount": 2000.0000,
"queuedAt": "2026-10-08T12:06:21.114502Z",
"confirmedAt": null,
"cancelledAt": null,
"merchantOrderRef": "PAYOUT-20017",
"orderType": "Withdrawal",
"currency": "PKR",
"fee": 40.0000,
"stage": "Awaiting",
"lifecycle": {
"stage": "Awaiting",
"createdAt": "2026-10-08T12:06:21.114502Z",
"awaitingAt": "2026-10-08T12:06:21.114502Z",
"assignedAt": null,
"sentAt": null,
"approvedAt": null,
"rejectedAt": null,
"completedAt": null,
"failedAt": null
}
}
}
{
"error": "Order not found."
}
Order Status
Query Order Status
Retrieve the current status, lifecycle stage and milestone timestamps of a deposit or withdrawal order, by its C2C orderId or orderReference, or by your own merchantOrderRef.
GET
/
api
/
merchant
/
orders
/
{id}
/
status
curl --request GET \
--url https://api.c2cpayment.net/api/merchant/orders/788fcae0-5214-403c-baa2-f318c0eb1b5b/status \
--header "C2C-API-Key: $C2C_API_KEY"
curl --request GET \
--url https://api.c2cpayment.net/api/merchant/orders/ORD-20261008120620-3f6b/status \
--header "C2C-API-Key: $C2C_API_KEY"
curl --request GET \
--url "https://api.c2cpayment.net/api/merchant/orders/status?merchantOrderRef=INV-10045" \
--header "C2C-API-Key: $C2C_API_KEY"
const BASE_URL = 'https://api.c2cpayment.net';
// Pass exactly one identifier: C2C's orderId or orderReference, or your merchantOrderRef.
async function getOrderStatus({ orderId, orderReference, merchantOrderRef }) {
const path = merchantOrderRef
? `/api/merchant/orders/status?merchantOrderRef=${encodeURIComponent(merchantOrderRef)}`
: `/api/merchant/orders/${encodeURIComponent(orderId ?? orderReference)}/status`;
const response = await fetch(`${BASE_URL}${path}`, {
headers: { 'C2C-API-Key': process.env.C2C_API_KEY },
});
if (!response.ok) throw new Error(`Status query failed: HTTP ${response.status}`);
return (await response.json()).data;
}
await getOrderStatus({ orderId: '788fcae0-5214-403c-baa2-f318c0eb1b5b' });
await getOrderStatus({ orderReference: 'ORD-20261008120620-3f6b' });
await getOrderStatus({ merchantOrderRef: 'INV-10045' });
import os
from urllib.parse import quote
import requests
BASE_URL = "https://api.c2cpayment.net"
def get_order_status(*, order_id=None, order_reference=None, merchant_order_ref=None) -> dict:
"""Pass exactly one identifier: C2C's order_id or order_reference, or your merchant_order_ref."""
if merchant_order_ref:
url, params = f"{BASE_URL}/api/merchant/orders/status", {"merchantOrderRef": merchant_order_ref}
else:
url, params = f"{BASE_URL}/api/merchant/orders/{quote(order_id or order_reference, safe='')}/status", None
response = requests.get(url, params=params, headers={"C2C-API-Key": os.environ["C2C_API_KEY"]})
response.raise_for_status()
return response.json()["data"]
get_order_status(order_id="788fcae0-5214-403c-baa2-f318c0eb1b5b")
get_order_status(order_reference="ORD-20261008120620-3f6b")
get_order_status(merchant_order_ref="INV-10045")
{
"data": {
"orderId": "788fcae0-5214-403c-baa2-f318c0eb1b5b",
"orderReference": "ORD-20261008120620-3f6b",
"status": "AwaitingMemberConfirmation",
"amount": 1500.0000,
"queuedAt": "2026-10-08T12:06:20.605646Z",
"confirmedAt": null,
"cancelledAt": null,
"merchantOrderRef": "INV-10045",
"orderType": "Deposit",
"currency": "PKR",
"fee": 30.0000,
"stage": "Sent",
"lifecycle": {
"stage": "Sent",
"createdAt": "2026-10-08T12:06:20.605646Z",
"awaitingAt": null,
"assignedAt": "2026-10-08T12:06:20.605646Z",
"sentAt": "2026-10-08T12:08:57.402113Z",
"approvedAt": null,
"rejectedAt": null,
"completedAt": null,
"failedAt": null
}
}
}
{
"data": {
"orderId": "788fcae0-5214-403c-baa2-f318c0eb1b5b",
"orderReference": "ORD-20261008120620-3f6b",
"status": "Completed",
"amount": 1500.0000,
"queuedAt": "2026-10-08T12:06:20.605646Z",
"confirmedAt": "2026-10-08T12:11:42.118204Z",
"cancelledAt": null,
"merchantOrderRef": "INV-10045",
"orderType": "Deposit",
"currency": "PKR",
"fee": 30.0000,
"stage": "Completed",
"lifecycle": {
"stage": "Completed",
"createdAt": "2026-10-08T12:06:20.605646Z",
"awaitingAt": null,
"assignedAt": "2026-10-08T12:06:20.605646Z",
"sentAt": "2026-10-08T12:08:57.402113Z",
"approvedAt": "2026-10-08T12:11:42.118204Z",
"rejectedAt": null,
"completedAt": "2026-10-08T12:11:42.118204Z",
"failedAt": null
}
}
}
{
"data": {
"orderId": "d1926af5-053d-4b39-a73b-c82f0d9af656",
"orderReference": "ORD-20261008120621-a7b8",
"status": "Awaiting",
"amount": 2000.0000,
"queuedAt": "2026-10-08T12:06:21.114502Z",
"confirmedAt": null,
"cancelledAt": null,
"merchantOrderRef": "PAYOUT-20017",
"orderType": "Withdrawal",
"currency": "PKR",
"fee": 40.0000,
"stage": "Awaiting",
"lifecycle": {
"stage": "Awaiting",
"createdAt": "2026-10-08T12:06:21.114502Z",
"awaitingAt": "2026-10-08T12:06:21.114502Z",
"assignedAt": null,
"sentAt": null,
"approvedAt": null,
"rejectedAt": null,
"completedAt": null,
"failedAt": null
}
}
}
{
"error": "Order not found."
}
Overview
Returns the current status, lifecycle stage and milestone timestamps of one of your merchant account’s orders. Use it to poll for the outcome, to reconcile after a missed webhook, or to confirm a webhook before you fulfil. Lookups are scoped to your merchant account, not to an API key: any of your active API keys can query any of your orders, including orders created before a key rotation. You can look an order up by any of its identifiers. All of them return the same response:| You have | Request |
|---|---|
C2C’s orderId | GET /api/merchant/orders/{orderId}/status |
C2C’s orderReference (ORD-…) | GET /api/merchant/orders/{orderReference}/status |
Your own merchantOrderRef | GET /api/merchant/orders/status?merchantOrderRef={merchantOrderRef} (see below) |
| API key | Required |
| Signature | Not required. Read-only requests are authenticated by the API key alone. |
Headers
string
required
mk_live_..., any of your merchant API keys. Authorization: Bearer mk_live_... is also accepted.Path parameters
string
required
Either of C2C’s identifiers for the order, both returned by Create deposit or Create withdrawal and present in webhooks:
- the
orderId, for example788fcae0-5214-403c-baa2-f318c0eb1b5b - the
orderReference, for exampleORD-20261008120620-3f6b
merchantOrderRef.Response
object
Hide properties
Hide properties
uuid
The order ID.
string
C2C’s human-readable reference.
string
Current status. See Status values below.
number
Order amount in the order currency.
string
ISO 8601 UTC time the order entered the queue (creation time for withdrawals).
string | null
When the order completed successfully, otherwise
null.string | null
When the order was explicitly cancelled, otherwise
null. It stays null for Rejected, Expired and CancelledTimeout; check status instead.string | null
Your
merchantOrderRef from order creation, or null.string
Deposit or Withdrawal.string
Currency code, for example
PKR.number | null
Your merchant fee for this order, fixed when the order was accepted (for a deposit, re-quoted if the customer paid with a different payment method than requested).
null if no fee applies.string
Canonical lifecycle stage:
Awaiting, Assigned, Sent, Approved, Rejected, Completed or Failed. See Lifecycle stages.object
The stage and when each milestone was reached. Timestamps are ISO 8601 UTC, or
null if the milestone wasn’t reached.Show properties
Show properties
string
Same as the top-level
stage.string
When the order was accepted.
string | null
When the order started waiting for an eligible member (
null if a member was assigned at creation).string | null
When a member was assigned.
string | null
Deposit: when the customer confirmed their payment on the payment page (with transaction ID digits, or on a QR method by tapping I’ve Completed Payment). Withdrawal: when the member sent the payout.
string | null
When the member approved the order.
string | null
When the member rejected the order.
string | null
When the order settled.
string | null
When the order ended without settlement.
curl --request GET \
--url https://api.c2cpayment.net/api/merchant/orders/788fcae0-5214-403c-baa2-f318c0eb1b5b/status \
--header "C2C-API-Key: $C2C_API_KEY"
curl --request GET \
--url https://api.c2cpayment.net/api/merchant/orders/ORD-20261008120620-3f6b/status \
--header "C2C-API-Key: $C2C_API_KEY"
curl --request GET \
--url "https://api.c2cpayment.net/api/merchant/orders/status?merchantOrderRef=INV-10045" \
--header "C2C-API-Key: $C2C_API_KEY"
const BASE_URL = 'https://api.c2cpayment.net';
// Pass exactly one identifier: C2C's orderId or orderReference, or your merchantOrderRef.
async function getOrderStatus({ orderId, orderReference, merchantOrderRef }) {
const path = merchantOrderRef
? `/api/merchant/orders/status?merchantOrderRef=${encodeURIComponent(merchantOrderRef)}`
: `/api/merchant/orders/${encodeURIComponent(orderId ?? orderReference)}/status`;
const response = await fetch(`${BASE_URL}${path}`, {
headers: { 'C2C-API-Key': process.env.C2C_API_KEY },
});
if (!response.ok) throw new Error(`Status query failed: HTTP ${response.status}`);
return (await response.json()).data;
}
await getOrderStatus({ orderId: '788fcae0-5214-403c-baa2-f318c0eb1b5b' });
await getOrderStatus({ orderReference: 'ORD-20261008120620-3f6b' });
await getOrderStatus({ merchantOrderRef: 'INV-10045' });
import os
from urllib.parse import quote
import requests
BASE_URL = "https://api.c2cpayment.net"
def get_order_status(*, order_id=None, order_reference=None, merchant_order_ref=None) -> dict:
"""Pass exactly one identifier: C2C's order_id or order_reference, or your merchant_order_ref."""
if merchant_order_ref:
url, params = f"{BASE_URL}/api/merchant/orders/status", {"merchantOrderRef": merchant_order_ref}
else:
url, params = f"{BASE_URL}/api/merchant/orders/{quote(order_id or order_reference, safe='')}/status", None
response = requests.get(url, params=params, headers={"C2C-API-Key": os.environ["C2C_API_KEY"]})
response.raise_for_status()
return response.json()["data"]
get_order_status(order_id="788fcae0-5214-403c-baa2-f318c0eb1b5b")
get_order_status(order_reference="ORD-20261008120620-3f6b")
get_order_status(merchant_order_ref="INV-10045")
{
"data": {
"orderId": "788fcae0-5214-403c-baa2-f318c0eb1b5b",
"orderReference": "ORD-20261008120620-3f6b",
"status": "AwaitingMemberConfirmation",
"amount": 1500.0000,
"queuedAt": "2026-10-08T12:06:20.605646Z",
"confirmedAt": null,
"cancelledAt": null,
"merchantOrderRef": "INV-10045",
"orderType": "Deposit",
"currency": "PKR",
"fee": 30.0000,
"stage": "Sent",
"lifecycle": {
"stage": "Sent",
"createdAt": "2026-10-08T12:06:20.605646Z",
"awaitingAt": null,
"assignedAt": "2026-10-08T12:06:20.605646Z",
"sentAt": "2026-10-08T12:08:57.402113Z",
"approvedAt": null,
"rejectedAt": null,
"completedAt": null,
"failedAt": null
}
}
}
{
"data": {
"orderId": "788fcae0-5214-403c-baa2-f318c0eb1b5b",
"orderReference": "ORD-20261008120620-3f6b",
"status": "Completed",
"amount": 1500.0000,
"queuedAt": "2026-10-08T12:06:20.605646Z",
"confirmedAt": "2026-10-08T12:11:42.118204Z",
"cancelledAt": null,
"merchantOrderRef": "INV-10045",
"orderType": "Deposit",
"currency": "PKR",
"fee": 30.0000,
"stage": "Completed",
"lifecycle": {
"stage": "Completed",
"createdAt": "2026-10-08T12:06:20.605646Z",
"awaitingAt": null,
"assignedAt": "2026-10-08T12:06:20.605646Z",
"sentAt": "2026-10-08T12:08:57.402113Z",
"approvedAt": "2026-10-08T12:11:42.118204Z",
"rejectedAt": null,
"completedAt": "2026-10-08T12:11:42.118204Z",
"failedAt": null
}
}
}
{
"data": {
"orderId": "d1926af5-053d-4b39-a73b-c82f0d9af656",
"orderReference": "ORD-20261008120621-a7b8",
"status": "Awaiting",
"amount": 2000.0000,
"queuedAt": "2026-10-08T12:06:21.114502Z",
"confirmedAt": null,
"cancelledAt": null,
"merchantOrderRef": "PAYOUT-20017",
"orderType": "Withdrawal",
"currency": "PKR",
"fee": 40.0000,
"stage": "Awaiting",
"lifecycle": {
"stage": "Awaiting",
"createdAt": "2026-10-08T12:06:21.114502Z",
"awaitingAt": "2026-10-08T12:06:21.114502Z",
"assignedAt": null,
"sentAt": null,
"approvedAt": null,
"rejectedAt": null,
"completedAt": null,
"failedAt": null
}
}
}
{
"error": "Order not found."
}
Status values
| Status | Applies to | Meaning | Final? |
|---|---|---|---|
Awaiting | Both | Accepted, waiting for an eligible member. Deposit: a member is assigned when the customer opens the payment page; if none is assigned before the checkout link expires (15 minutes), it ends CancelledTimeout. Withdrawal: assigned automatically as soon as a member is available, or CancelledTimeout after 120 minutes. A withdrawal created without customerAccountNumber first waits here for the customer to enter their account on the hosted page (CancelledTimeout if they haven’t within 15 minutes). | No |
Queued | Deposit | Created with a member assigned. The customer hasn’t opened the payment page yet, or hasn’t picked a method on it. | No |
AwaitingCustomerPayment | Deposit | Payment page opened and the account number, Till ID or QR code reserved for the customer. Waiting for the customer to pay and confirm on the page: the last digits of the transaction ID, or on the QR methods the account they pay from. | No |
AwaitingMemberConfirmation | Deposit | Customer confirmed the payment on the page. Waiting for the member to verify receipt. | No |
AwaitingMemberPayout | Withdrawal | Waiting for the member to send the payout. | No |
ManualReview | Both | Escalated to C2C operations, for example a member confirmation or payout window passed, or the member reported that a payout could not be completed normally. Resolved by C2C to Completed or Cancelled, which sends order.completed or order.failed. Stage Sent if the customer had already paid, otherwise Assigned. | No |
Completed | Both | Success. Funds received (deposit) or paid out (withdrawal). | Yes, success |
Rejected | Both | The member rejected the order, for example because no matching payment was received. | Yes, failed |
Expired | Deposit | The checkout link (15 minutes) expired before the customer paid, including when they never opened it. | Yes, failed |
CancelledTimeout | Both | No eligible member became available in time (Awaiting order timed out). | Yes, failed |
Cancelled | Both | Cancelled by C2C or the member. | Yes, failed |
CancelledAuto | Both | Cancelled automatically by the system. | Yes, failed |
Legacy statuses (older orders only)
Legacy statuses (older orders only)
Orders created by earlier versions of the platform can also report
Assigned (in progress), Frozen (in progress, past the member’s freeze window) and Confirmed (success, equivalent to Completed). Treat Confirmed as success if you see it.Fulfil a deposit or record a payout only on
Completed (or legacy Confirmed). ManualReview isn’t a failure: don’t refund or re-pay the customer until C2C resolves the order.Polling guidelines
- Prefer webhooks and poll as a fallback or to reconcile.
- Poll every 5–10 seconds while the customer is on the payment page, then back off (for example every minute) for orders waiting on a member.
- Stop polling once the status is final.
- The Merchant API has no request rate limits, but don’t poll many orders in tight loops; webhooks scale better.
ManualReviewsends no webhook until C2C resolves it, so poll those orders at a low frequency until they are final.- You can branch on
stageinstead ofstatus:Completedis success,Failedis final without settlement, anything else is in progress.
Node.js
const FINAL = new Set(['Completed', 'Confirmed', 'Rejected', 'Expired', 'CancelledTimeout', 'Cancelled', 'CancelledAuto']);
const SUCCESS = new Set(['Completed', 'Confirmed']);
// lookup: { orderId }, { orderReference } or { merchantOrderRef }, as for getOrderStatus above
async function waitForOutcome(lookup, { intervalMs = 5000, timeoutMs = 30 * 60 * 1000 } = {}) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
const { status } = await getOrderStatus(lookup);
if (FINAL.has(status)) return { status, success: SUCCESS.has(status) };
await new Promise((r) => setTimeout(r, intervalMs));
}
return { status: 'Pending', success: false }; // keep reconciling later
}
Error responses
| Status | When | Body |
|---|---|---|
401 | API key missing, invalid or revoked | Empty body |
404 | No order with this orderId or orderReference for your merchant account | {"error": "Order not found."} |
Query by merchantOrderRef
GET /api/merchant/orders/status?merchantOrderRef={merchantOrderRef}
merchantOrderRef, in exactly the same response shape as above. Use it to track orders by your own reference, or when you didn’t get the orderId back, for example after a timeout. Authentication works the same as for the lookup by ID: API key only, no signature.
string
Your
merchantOrderRef from order creation. URL-encode it.string
C2C’s
orderReference (ORD-…). Accepted here too, as an alternative to the path form above.cURL
curl --request GET \
--url "https://api.c2cpayment.net/api/merchant/orders/status?merchantOrderRef=INV-10045" \
--header "C2C-API-Key: $C2C_API_KEY"
Node.js
const order = await getOrderStatus({ merchantOrderRef: 'INV-10045' }); // helper from the examples above
| Status | When | Body |
|---|---|---|
400 | Neither parameter sent, or both empty | {"error": "Provide an orderId, an orderReference or a merchantOrderRef."} |
400 | Both merchantOrderRef and orderReference sent | {"error": "Provide either an orderReference or a merchantOrderRef, not both."} |
401 | API key missing, invalid or revoked | Empty body |
404 | No order with this reference for your merchant account | {"error": "Order not found."} |
A
merchantOrderRef can belong to several orders only when the earlier ones failed (see merchantOrderRef rules). This endpoint always returns the most recent one; use the orderId or orderReference to query an older order.Next steps
Order status guide
Lifecycle diagrams for deposits and withdrawals
Webhooks
Get pushed updates instead of polling