Consume a mandate
POST /functions/v1/mandate-consume
The only call that moves the ceiling. Arithmetic happens under SELECT … FOR UPDATE, and Idempotency-Key is mandatory so a network timeout is never a double charge.
Server key. Idempotency-Key is mandatory, 8–200 characters, plus x-sidaxis-timestamp and x-sidaxis-nonce.
Body
| Field | Type | Notes |
|---|---|---|
mandate_id | uuid, required | |
scope | string, required | Matched exactly |
amount | integer | Minor unit |
currency | string | ISO-4217 |
action_ref | string | Your reference for the action being authorised |
context | object | merchant, category, country |
curl -X POST https://api.sidaxis.com/functions/v1/mandate-consume \
-H "x-sidaxis-api-key: sk_live_..." \
-H "Idempotency-Key: booking-88213-attempt-1" \
-H "x-sidaxis-timestamp: 1789564902" \
-H "x-sidaxis-nonce: 7de1a9c034" \
-H "content-type: application/json" \
-d '{
"mandate_id": "mdt_a91f3c",
"scope": "payment",
"amount": 18900,
"currency": "USD",
"action_ref": "booking-88213",
"context": { "merchant": "mrc_9f2c", "category": "travel", "country": "US" }
}'Response — always 200
{
"allowed": true,
"consumption_id": "cns_5b7e21",
"idempotent_replay": false,
"remaining": 31100,
"at_limit": false,
"period_resets_at": "2026-09-17T03:00:00Z"
}{
"allowed": false,
"reason": "ceiling_exceeded",
"developer_message": "Requested 18900 exceeds the remaining daily ceiling of 12000.",
"user_message": "This is above the daily limit you set.",
"step_up_available": true
}Concurrency
All arithmetic happens inside mandate_consume_atomic(), which takes SELECT … FOR UPDATE on the mandate row before summing consumptions. Reading the balance unlocked and writing afterwards lets two agents through and blows the ceiling — that is the bug this design prevents.
Idempotency
Without the header the call is refused with reason: idempotency_key_required, because a network timeout would otherwise become a double charge. The same key replayed returns the original consumption with idempotent_replay: true and debits once. See idempotency.
Append-only
Consumptions are rows, not a decremented column. A counter loses the reason, and the reason is what an audit needs.
Two more facts
at_limit: truemeans this consumption used the last of the period; amandate.at_limitwebhook follows — see webhooks.- When a step-up mandate exists, consuming it does not touch the parent: the standing mandate keeps its balance for the operations that still fit inside it.