Skip to content

Record a payment made to a partner

POST /program/affiliates/{affiliate_id}/payouts
Scopeprogram:write
Customer session tokenNot accepted: call from your server with an API key
Rate limit classwrite (limits)
Idempotency keyRequired (idempotency)
MCP toolcharm_record_partner_payout

Charm never sends money: the merchant pays the partner themselves, then this records it as the admin’s Record payment does. The payable commission through through turns paid, an open payment request closes, and the partner gets a confirmation e-mail unless notify_partner: false. Call with dry_run: true for the amount, ask the merchant to confirm they already paid exactly that, then repeat with confirm_paid: true plus expected_amount and expected_currency from the preview; a balance that moved since is refused.

NameInTypeDescription
affiliate_idpathstringThe partner’s id from GET /program/affiliates/payouts/due.
FieldTypeDescription
throughstringPay commission payable through this day, YYYY-MM-DD; default today. (optional)
referencestringThe merchant’s payment reference, e.g. the bank transfer id. (optional)
notestring(optional)
notify_partnerbooleanE-mail the partner a confirmation; default true. (optional)
expected_amountnumberThe amount from the dry run. (optional)
expected_currencystringThe currency from the dry run. (optional)
confirm_paidbooleanThe merchant confirmed the money has already been paid. (optional)
dry_runbooleanPreview only: validate, resolve references and return the diff and summary, but write nothing. Costs no idempotency key and is limited as a read. Call with this first, show the merchant, then repeat without it. (optional)

Returns PartnerPayoutResult.

FieldTypeDescription
dry_runboolean
recordedboolean
payout_idstring or null(nullable)
partnerPayoutPartner
throughstring
amountnumber
currencystring or null(nullable)
commissionsinteger
notify_partnerboolean
payment_requestPartnerPaymentRequest or null(nullable)
{
"dry_run": false,
"recorded": false,
"payout_id": "payout id",
"partner": {
"id": "id",
"name": "Gold",
"email": "shopper@example.com",
"code": "code",
"status": "active"
},
"through": "through",
"amount": 1,
"currency": "EUR",
"commissions": 1,
"notify_partner": false,
"payment_request": {
"amount": 1,
"currency": "EUR",
"requested_at": "2026-10-01T09:30:00.000Z",
"payment_details": {}
}
}
Terminal window
# 1. Dry run: writes nothing and needs no Idempotency-Key. Show the merchant the result.
curl -X POST "https://charm.appfleece.app/api/v1/program/affiliates/<affiliate_id>/payouts" \
-H "Authorization: Bearer chrm_live_..." \
-H "Content-Type: application/json" \
-d '{"dry_run":true}'
# 2. After the merchant says yes: the real call with the confirmation.
curl -X POST "https://charm.appfleece.app/api/v1/program/affiliates/<affiliate_id>/payouts" \
-H "Authorization: Bearer chrm_live_..." \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"expected_amount":1,"expected_currency":"EUR","confirm_paid":true}'

unauthorized · invalid_token · insufficient_scope · access_required · not_found · validation_error · rate_limited · idempotency_conflict

Every error body carries code, message, request_id and a doc_url pointing at the matching entry in the error catalog.