# "signature" is computed as described in the Signature Generation Guide.
# This value is the guide's worked example (example signing secret).
curl --request POST \
--url https://api.c2cpayment.net/api/merchant/orders \
--header "C2C-API-Key: $C2C_API_KEY" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: PAYOUT-20017" \
--data '{"orderType":"Withdrawal","amount":2000,"currency":"PKR","walletType":"Easypaisa","merchantOrderRef":"PAYOUT-20017","customerReference":"player_12345","customerAccountNumber":"03001234567","callbackUrl":"https://merchant.example.com/webhooks/c2c","signature":"8dddc4abc8aa78744bb29624ac583434"}'
// signBody(): see the Signature Generation Guide
const payload = {
orderType: 'Withdrawal',
amount: 2000,
currency: 'PKR',
walletType: 'Easypaisa',
merchantOrderRef: 'PAYOUT-20017',
customerReference: 'player_12345',
customerAccountNumber: '03001234567',
callbackUrl: 'https://merchant.example.com/webhooks/c2c',
};
const response = await fetch(
'https://api.c2cpayment.net/api/merchant/orders',
{
method: 'POST',
headers: {
'C2C-API-Key': process.env.C2C_API_KEY,
'Content-Type': 'application/json',
'Idempotency-Key': 'PAYOUT-20017',
},
body: JSON.stringify({ ...payload, signature: signBody(payload, process.env.C2C_SIGNING_SECRET) }),
}
);
const { data } = await response.json();
// Persist data.orderId; await the webhook or poll the status
import os, requests
# sign_body(): see the Signature Generation Guide
payload = {
"orderType": "Withdrawal",
"amount": 2000,
"currency": "PKR",
"walletType": "Easypaisa",
"merchantOrderRef": "PAYOUT-20017",
"customerReference": "player_12345",
"customerAccountNumber": "03001234567",
"callbackUrl": "https://merchant.example.com/webhooks/c2c",
}
response = requests.post(
"https://api.c2cpayment.net/api/merchant/orders",
json={**payload, "signature": sign_body(payload, os.environ["C2C_SIGNING_SECRET"])},
headers={
"C2C-API-Key": os.environ["C2C_API_KEY"],
"Idempotency-Key": "PAYOUT-20017",
},
)
order_id = response.json()["data"]["orderId"]
{
"data": {
"orderId": "d1926af5-053d-4b39-a73b-c82f0d9af656",
"paymentPageUrl": "https://<payment-page-host>/pay?order_id=d1926af5-053d-4b39-a73b-c82f0d9af656&expires=1791462081&signature=Pq7...",
"status": "AwaitingMemberPayout",
"orderReference": "ORD-20261008120621-a7b8",
"expiresAt": "2026-10-08T12:21:21.717975Z",
"stage": "Assigned",
"merchantOrderRef": "PAYOUT-20017"
}
}
{
"data": {
"orderId": "d1926af5-053d-4b39-a73b-c82f0d9af656",
"paymentPageUrl": "https://<payment-page-host>/pay?order_id=d1926af5-053d-4b39-a73b-c82f0d9af656&expires=1791462081&signature=Pq7...",
"status": "Awaiting",
"orderReference": "ORD-20261008120621-a7b8",
"expiresAt": "2026-10-08T12:21:21.717975Z",
"stage": "Awaiting",
"merchantOrderRef": "PAYOUT-20017"
}
}
{
"data": {
"orderId": "d1926af5-053d-4b39-a73b-c82f0d9af656",
"paymentPageUrl": "https://<payment-page-host>/pay?order_id=d1926af5-053d-4b39-a73b-c82f0d9af656&expires=1791462081&signature=Pq7...",
"status": "Awaiting",
"orderReference": "ORD-20261008120621-a7b8",
"expiresAt": "2026-10-08T12:21:21.717975Z",
"stage": "Awaiting",
"merchantOrderRef": "PAYOUT-20017"
}
}
{
"error": "CustomerAccountName can only be sent together with CustomerAccountNumber."
}
{
"error": "JazzCashQR is a deposit-only payment method. A withdrawal's walletType must be one of: JazzCash, Easypaisa, TillID, BankAccount."
}
{
"success": false,
"error": "The request body must include a 'signature' field.",
"code": "SIGNATURE_REQUIRED",
"traceId": "b7e7de9cb3606f164c88c36419ed8e7b"
}
{
"error": "Insufficient merchant balance: 510.00 PKR available, 1010.00 PKR required for this withdrawal (amount + fee). 1990.00 PKR is reserved for withdrawals in progress."
}
{
"error": "Easypaisa withdrawals are disabled for this merchant."
}
{
"error": "merchantOrderRef 'PAYOUT-20017' is already used by order ORD-20261008120621-a7b8. Reuse the same Idempotency-Key to retry a request, or use a new reference for a new payment."
}
Withdrawal
Create Withdrawal Order
Create a withdrawal order that pays your customer out to their own mobile wallet or account.
POST
/
api
/
merchant
/
orders
# "signature" is computed as described in the Signature Generation Guide.
# This value is the guide's worked example (example signing secret).
curl --request POST \
--url https://api.c2cpayment.net/api/merchant/orders \
--header "C2C-API-Key: $C2C_API_KEY" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: PAYOUT-20017" \
--data '{"orderType":"Withdrawal","amount":2000,"currency":"PKR","walletType":"Easypaisa","merchantOrderRef":"PAYOUT-20017","customerReference":"player_12345","customerAccountNumber":"03001234567","callbackUrl":"https://merchant.example.com/webhooks/c2c","signature":"8dddc4abc8aa78744bb29624ac583434"}'
// signBody(): see the Signature Generation Guide
const payload = {
orderType: 'Withdrawal',
amount: 2000,
currency: 'PKR',
walletType: 'Easypaisa',
merchantOrderRef: 'PAYOUT-20017',
customerReference: 'player_12345',
customerAccountNumber: '03001234567',
callbackUrl: 'https://merchant.example.com/webhooks/c2c',
};
const response = await fetch(
'https://api.c2cpayment.net/api/merchant/orders',
{
method: 'POST',
headers: {
'C2C-API-Key': process.env.C2C_API_KEY,
'Content-Type': 'application/json',
'Idempotency-Key': 'PAYOUT-20017',
},
body: JSON.stringify({ ...payload, signature: signBody(payload, process.env.C2C_SIGNING_SECRET) }),
}
);
const { data } = await response.json();
// Persist data.orderId; await the webhook or poll the status
import os, requests
# sign_body(): see the Signature Generation Guide
payload = {
"orderType": "Withdrawal",
"amount": 2000,
"currency": "PKR",
"walletType": "Easypaisa",
"merchantOrderRef": "PAYOUT-20017",
"customerReference": "player_12345",
"customerAccountNumber": "03001234567",
"callbackUrl": "https://merchant.example.com/webhooks/c2c",
}
response = requests.post(
"https://api.c2cpayment.net/api/merchant/orders",
json={**payload, "signature": sign_body(payload, os.environ["C2C_SIGNING_SECRET"])},
headers={
"C2C-API-Key": os.environ["C2C_API_KEY"],
"Idempotency-Key": "PAYOUT-20017",
},
)
order_id = response.json()["data"]["orderId"]
{
"data": {
"orderId": "d1926af5-053d-4b39-a73b-c82f0d9af656",
"paymentPageUrl": "https://<payment-page-host>/pay?order_id=d1926af5-053d-4b39-a73b-c82f0d9af656&expires=1791462081&signature=Pq7...",
"status": "AwaitingMemberPayout",
"orderReference": "ORD-20261008120621-a7b8",
"expiresAt": "2026-10-08T12:21:21.717975Z",
"stage": "Assigned",
"merchantOrderRef": "PAYOUT-20017"
}
}
{
"data": {
"orderId": "d1926af5-053d-4b39-a73b-c82f0d9af656",
"paymentPageUrl": "https://<payment-page-host>/pay?order_id=d1926af5-053d-4b39-a73b-c82f0d9af656&expires=1791462081&signature=Pq7...",
"status": "Awaiting",
"orderReference": "ORD-20261008120621-a7b8",
"expiresAt": "2026-10-08T12:21:21.717975Z",
"stage": "Awaiting",
"merchantOrderRef": "PAYOUT-20017"
}
}
{
"data": {
"orderId": "d1926af5-053d-4b39-a73b-c82f0d9af656",
"paymentPageUrl": "https://<payment-page-host>/pay?order_id=d1926af5-053d-4b39-a73b-c82f0d9af656&expires=1791462081&signature=Pq7...",
"status": "Awaiting",
"orderReference": "ORD-20261008120621-a7b8",
"expiresAt": "2026-10-08T12:21:21.717975Z",
"stage": "Awaiting",
"merchantOrderRef": "PAYOUT-20017"
}
}
{
"error": "CustomerAccountName can only be sent together with CustomerAccountNumber."
}
{
"error": "JazzCashQR is a deposit-only payment method. A withdrawal's walletType must be one of: JazzCash, Easypaisa, TillID, BankAccount."
}
{
"success": false,
"error": "The request body must include a 'signature' field.",
"code": "SIGNATURE_REQUIRED",
"traceId": "b7e7de9cb3606f164c88c36419ed8e7b"
}
{
"error": "Insufficient merchant balance: 510.00 PKR available, 1010.00 PKR required for this withdrawal (amount + fee). 1990.00 PKR is reserved for withdrawals in progress."
}
{
"error": "Easypaisa withdrawals are disabled for this merchant."
}
{
"error": "merchantOrderRef 'PAYOUT-20017' is already used by order ORD-20261008120621-a7b8. Reuse the same Idempotency-Key to retry a request, or use a new reference for a new payment."
}
Overview
Creates a withdrawal: a C2C member sends money from their own account to your customer’s account. When the member confirms the payout, the amount plus fees is debited from your merchant wallet. Before creating the order, C2C checks that your merchant wallet can fund it (see Funding check). If a member is available, they’re assigned immediately and the order starts inAwaitingMemberPayout. Otherwise the order is still accepted with status Awaiting and assigned automatically as soon as a member becomes available (see Awaiting withdrawals). See the Withdrawal flow for the full lifecycle.
You can give the customer’s receiving account in two ways:
| You send | What happens |
|---|---|
customerAccountNumber (and optionally customerAccountName) | The account is part of the signed request. A member is assigned straight away; you don’t need to redirect the customer anywhere. |
No customerAccountNumber | The order is accepted as Awaiting and no member is assigned yet. Redirect the customer to paymentPageUrl: the hosted page asks them for their wallet account number and account holder name. A member is assigned as soon as they submit it. See Collecting the account on the hosted page. |
| API key | Required |
| Signature | Required, in the body’s signature field. See the Signature Generation Guide |
| Idempotency-Key | Required |
Deposits and withdrawals use the same endpoint. Set
orderType to "Withdrawal".Headers
string
required
mk_live_..., your merchant API key. Authorization: Bearer mk_live_... is also accepted.string
required
Your unique key for this payout attempt, up to 100 characters. Critical for payouts: retrying with the same key never creates a second payout. See Idempotency.
string
required
application/jsonRequest body
string
required
Must be
"Withdrawal".number
required
Amount the customer receives, in
currency. Must be greater than 0, have at most 4 decimal places and be less than 100,000,000,000,000.Example: 2000string
required
The type of the customer’s receiving account. C2C assigns a member who can pay out to it: a payout is sent within one provider, so a JazzCash customer is paid by a member with a JazzCash account and an Easypaisa customer by a member with an Easypaisa account. The wallet type is fixed by the order: on the hosted page the customer enters an account of this type and cannot choose another.One of
JazzCash, Easypaisa, TillID, BankAccount.JazzCashTillID, JazzCashQR and EasypaisaQR are deposit-only payment methods: a withdrawal on one of them is rejected with 400.string
The customer’s receiving account: a mobile wallet number such as
03001234567, a Till ID or a bank account number. Up to 50 characters. Shown to the assigned member, who sends the payout to it. Once the order is created it cannot be changed.Optional. Leave it out to have the customer enter their account on the hosted page instead.C2C doesn’t verify that the account exists or belongs to your customer. Validate it on your side before you submit. A payout sent to a wrong account can’t be reversed by C2C.
string
The name the customer’s account is held in. Up to 200 characters. Shown to the assigned member so they can check it against the name their wallet app shows before sending. Only accepted together with
customerAccountNumber; sending it alone is rejected with 400.string
default:"PKR"
ISO currency code:
PKR, INR or BDT. Defaults to PKR.string
Your own reference for this payout. Up to 200 characters. It is echoed in webhooks, and you can query the order by it.One live order per reference: if a payout that is in progress or completed already uses this
merchantOrderRef, the request is rejected with 409. A reference whose earlier order failed can be reused. See merchantOrderRef rules.string
Your identifier for the customer being paid. Up to 200 characters.
string
Absolute
http(s) URL for this order’s webhooks, up to 500 characters. Defaults to the callback URL in Merchant Portal → Settings. It must resolve to a public internet address: loopback, private and link-local addresses are refused at delivery time, and redirects aren’t followed.integer
default:"3"
0 to 10. If the assigned member doesn’t pay out within the payout window (60 minutes by default), C2C reassigns the withdrawal to another available member, up to this many times. After that, the order moves to ManualReview.string
Free-form string stored with the order, up to 1000 characters. It isn’t returned in responses or webhooks.
string
Absolute
http(s) URL. If the customer has the hosted page open when the payout completes, the page sends them here. See Returning the customer to your site.string
Absolute
http(s) URL. The hosted page sends the customer here when the withdrawal is rejected, cancelled or expires.integer
default:"4"
Accepted (
4 to 8), but it has no effect on a withdrawal. It is only used by the deposit payment page, for the account number and Till ID methods.string
required
32-character lowercase hex MD5 of the other top-level fields (lowercased keys in ASCII order,
key=value joined with &, null and empty values skipped) followed directly by your signing secret. See the Signature Generation Guide.amount, customerAccountNumber, customerAccountName and every other field you send are signed, so the payout can’t be changed in transit.Example: 5db94b5eaf95dba367d124c28cb019f0Response
object
Hide properties
Hide properties
uuid
C2C’s unique order ID. Store it for status queries and webhook matching.
string
Initial status:
AwaitingMemberPayout when a member was assigned, or Awaiting when no eligible member was available yet or the customer still has to enter their account on the hosted page.string
Lifecycle stage:
Assigned or Awaiting for a new withdrawal. See Lifecycle stages.string | null
Your
merchantOrderRef, or null if you didn’t send one.string
C2C’s human-readable reference, for example
ORD-20261008120621-a7b8.string
The hosted page for this withdrawal. Required when you didn’t send
customerAccountNumber: the customer enters their account there. Otherwise optional: it shows the customer the progress of their payout.string
Expiry of
paymentPageUrl, 15 minutes after creation. It isn’t the payout deadline. A withdrawal created without customerAccountNumber ends CancelledTimeout if the customer hasn’t entered their account by then.# "signature" is computed as described in the Signature Generation Guide.
# This value is the guide's worked example (example signing secret).
curl --request POST \
--url https://api.c2cpayment.net/api/merchant/orders \
--header "C2C-API-Key: $C2C_API_KEY" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: PAYOUT-20017" \
--data '{"orderType":"Withdrawal","amount":2000,"currency":"PKR","walletType":"Easypaisa","merchantOrderRef":"PAYOUT-20017","customerReference":"player_12345","customerAccountNumber":"03001234567","callbackUrl":"https://merchant.example.com/webhooks/c2c","signature":"8dddc4abc8aa78744bb29624ac583434"}'
// signBody(): see the Signature Generation Guide
const payload = {
orderType: 'Withdrawal',
amount: 2000,
currency: 'PKR',
walletType: 'Easypaisa',
merchantOrderRef: 'PAYOUT-20017',
customerReference: 'player_12345',
customerAccountNumber: '03001234567',
callbackUrl: 'https://merchant.example.com/webhooks/c2c',
};
const response = await fetch(
'https://api.c2cpayment.net/api/merchant/orders',
{
method: 'POST',
headers: {
'C2C-API-Key': process.env.C2C_API_KEY,
'Content-Type': 'application/json',
'Idempotency-Key': 'PAYOUT-20017',
},
body: JSON.stringify({ ...payload, signature: signBody(payload, process.env.C2C_SIGNING_SECRET) }),
}
);
const { data } = await response.json();
// Persist data.orderId; await the webhook or poll the status
import os, requests
# sign_body(): see the Signature Generation Guide
payload = {
"orderType": "Withdrawal",
"amount": 2000,
"currency": "PKR",
"walletType": "Easypaisa",
"merchantOrderRef": "PAYOUT-20017",
"customerReference": "player_12345",
"customerAccountNumber": "03001234567",
"callbackUrl": "https://merchant.example.com/webhooks/c2c",
}
response = requests.post(
"https://api.c2cpayment.net/api/merchant/orders",
json={**payload, "signature": sign_body(payload, os.environ["C2C_SIGNING_SECRET"])},
headers={
"C2C-API-Key": os.environ["C2C_API_KEY"],
"Idempotency-Key": "PAYOUT-20017",
},
)
order_id = response.json()["data"]["orderId"]
{
"data": {
"orderId": "d1926af5-053d-4b39-a73b-c82f0d9af656",
"paymentPageUrl": "https://<payment-page-host>/pay?order_id=d1926af5-053d-4b39-a73b-c82f0d9af656&expires=1791462081&signature=Pq7...",
"status": "AwaitingMemberPayout",
"orderReference": "ORD-20261008120621-a7b8",
"expiresAt": "2026-10-08T12:21:21.717975Z",
"stage": "Assigned",
"merchantOrderRef": "PAYOUT-20017"
}
}
{
"data": {
"orderId": "d1926af5-053d-4b39-a73b-c82f0d9af656",
"paymentPageUrl": "https://<payment-page-host>/pay?order_id=d1926af5-053d-4b39-a73b-c82f0d9af656&expires=1791462081&signature=Pq7...",
"status": "Awaiting",
"orderReference": "ORD-20261008120621-a7b8",
"expiresAt": "2026-10-08T12:21:21.717975Z",
"stage": "Awaiting",
"merchantOrderRef": "PAYOUT-20017"
}
}
{
"data": {
"orderId": "d1926af5-053d-4b39-a73b-c82f0d9af656",
"paymentPageUrl": "https://<payment-page-host>/pay?order_id=d1926af5-053d-4b39-a73b-c82f0d9af656&expires=1791462081&signature=Pq7...",
"status": "Awaiting",
"orderReference": "ORD-20261008120621-a7b8",
"expiresAt": "2026-10-08T12:21:21.717975Z",
"stage": "Awaiting",
"merchantOrderRef": "PAYOUT-20017"
}
}
{
"error": "CustomerAccountName can only be sent together with CustomerAccountNumber."
}
{
"error": "JazzCashQR is a deposit-only payment method. A withdrawal's walletType must be one of: JazzCash, Easypaisa, TillID, BankAccount."
}
{
"success": false,
"error": "The request body must include a 'signature' field.",
"code": "SIGNATURE_REQUIRED",
"traceId": "b7e7de9cb3606f164c88c36419ed8e7b"
}
{
"error": "Insufficient merchant balance: 510.00 PKR available, 1010.00 PKR required for this withdrawal (amount + fee). 1990.00 PKR is reserved for withdrawals in progress."
}
{
"error": "Easypaisa withdrawals are disabled for this merchant."
}
{
"error": "merchantOrderRef 'PAYOUT-20017' is already used by order ORD-20261008120621-a7b8. Reuse the same Idempotency-Key to retry a request, or use a new reference for a new payment."
}
Error responses
| Status | When | Body |
|---|---|---|
400 | Validation failed, for example customerAccountNumber too long, customerAccountName sent without an account number, amount ≤ 0, an amount with more than 4 decimal places or too large, or an unknown currency | {"error": "..."} |
400 | walletType is JazzCashTillID, JazzCashQR or EasypaisaQR, which are deposit-only | {"error": "JazzCashQR is a deposit-only payment method. A withdrawal's walletType must be one of: JazzCash, Easypaisa, TillID, BankAccount."} |
400 | Idempotency-Key missing, malformed JSON, or an unknown enum value | application/problem+json |
401 | API key missing, invalid or revoked | Empty body |
401 | signature missing, malformed, invalid, or replayed under a different Idempotency-Key | {"success": false, "error", "code", "traceId"} |
403 | Merchant account not active, or caller IP not whitelisted | {"error": "..."} |
413 | Body larger than 64 KB | {"code": "PAYLOAD_TOO_LARGE", ...} |
409 | merchantOrderRef is already used by a payout that is in progress or completed | {"error": "merchantOrderRef '...' is already used by order ORD-…. ..."} |
422 | Your available balance can’t cover this payout plus its fee | {"error": "Insufficient merchant balance: ..."} |
422 | The payment method (walletType) is disabled for withdrawals on your account | {"error": "..."} |
422 | The Idempotency-Key was already used with different order terms | {"error": "This Idempotency-Key was already used for a different order request."} |
Funding check
A withdrawal is accepted only if your available balance covers this payout’s amount + its fee. From the moment a withdrawal is accepted until it is confirmed or fails, its amount + fee is reserved: it is taken out ofavailableBalance and reported as reservedBalance by Query wallet balance, so one balance cannot fund two payouts.
availableBalance = wallet balance − reservedBalance
reservedBalance = amount + fee of every withdrawal that has not yet completed or failed
| The withdrawal… | Its reserved amount + fee… |
|---|---|
is accepted (Awaiting, AwaitingMemberPayout) or under review (ManualReview) | stays in reservedBalance |
completes (Completed) | is debited from your wallet: it leaves reservedBalance and availableBalance does not change |
fails (Rejected, Cancelled, CancelledTimeout, Expired) | is returned: it leaves reservedBalance and goes back to availableBalance |
422 Insufficient merchant balance: …, and no order is created. When other withdrawals are in progress the message also says how much they reserve. Top up your wallet, or wait for in-progress payouts to finish, then retry. You can reuse the same Idempotency-Key, because rejected requests don’t consume it.
Fees come from the fee rules C2C configures for your account. The fee is fixed when the order is accepted; later fee-rule changes apply to new orders only. The amount + fee is debited when the member confirms the payout, and returns to your available balance if the payout fails. Check balances with Query wallet balance.
Awaiting withdrawals
When no eligible member is available, the withdrawal is accepted with statusAwaiting (stage Awaiting). It’s assigned automatically as soon as a member becomes available: a member comes online, a member frees capacity, or C2C’s once-a-minute background check finds one. It then continues as AwaitingMemberPayout.
- While
Awaiting, its amount + fee stays reserved against your balance: it counts as in progress for the funding check and for the Pending amount on your dashboard. - If no member becomes available within 120 minutes (a platform setting), the order ends
CancelledTimeoutand you receive anorder.failedwebhook (reason:No eligible member became available in time). Nothing is debited.
Collecting the account on the hosted page
When you create a withdrawal withoutcustomerAccountNumber:
- The order is accepted as
Awaiting. Its amount + fee is reserved against your balance like any other withdrawal, but no member is assigned yet. - Redirect the customer to
paymentPageUrl. The page shows the amount and your name, and asks for the wallet account number and the account holder name. The wallet type is thewalletTypeof the order; the amount cannot be changed. - When the customer submits, C2C stores the account and assigns a member (
AwaitingMemberPayout), or keeps the orderAwaitinguntil a member is available (the 120-minute window starts then). - The submitted account is final: it cannot be changed from the page afterwards. Submitting the same details twice has no further effect.
expiresAt (15 minutes), the order ends CancelledTimeout, the reservation is released and you receive an order.failed webhook (reason: The customer did not provide their withdrawal account in time). Create a new order to try again.
Payout lifecycle
Awaiting (no account yet) ──customer submits account──▶ AwaitingMemberPayout, or Awaiting a member
└──not submitted within 15 min──▶ CancelledTimeout (order.failed webhook)
Awaiting ──member available──▶ AwaitingMemberPayout
└──no member within 120 min──▶ CancelledTimeout (order.failed webhook)
AwaitingMemberPayout ──member confirms payout──▶ Completed (order.completed webhook)
│
├──member rejects────────────────────────▶ Rejected (order.failed webhook)
│
├──member reports an abnormal payment───▶ ManualReview (no webhook until C2C resolves it)
│
└──payout window passes (60 min default)
├── retries left → reassigned to another member (stays AwaitingMemberPayout)
└── no retries left → ManualReview (no webhook until C2C resolves it)
Treat a withdrawal as paid only when its status is
Completed. An order in ManualReview is being handled by C2C operations — for example the member reported that the payout could not be completed normally or that they cannot tell whether it went through. Don’t resubmit the payout with a new Idempotency-Key while it is unresolved, or the customer could be paid twice.Next steps
Withdrawal flow
End-to-end payout process
Query order status
Track the payout
Wallet balance
Make sure you can fund payouts
Webhooks
Get notified on completion