{"openapi":"3.1.0","info":{"title":"mCards Controlled Funding API","version":"0.1.0","description":"Sponsor-controlled, commitment/just-in-time-pull funding platform. Sponsors link a real payment instrument and define funding commitments; funds are pulled at authorization only on a compliant, coverable transaction."},"servers":[{"url":"https://secondary.mcards.com","description":"production"},{"url":"http://localhost:3000","description":"local"}],"tags":[{"name":"Parties"},{"name":"Linked Payment Sources"},{"name":"Commitments"},{"name":"Budget Caps"},{"name":"Cards"},{"name":"Policies"},{"name":"Authorizations"},{"name":"System"}],"components":{"parameters":{"Limit":{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"description":"Maximum items to return."},"Cursor":{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from a previous response's next_cursor."},"SponsorScope":{"name":"x-sponsor-party-id","in":"header","required":false,"schema":{"type":"string"},"description":"Cross-sponsor privacy scope (§13.1). When set, authorization reads return ONLY this sponsor's own funded slices — never another sponsor's instruments, commitments, or amounts. Read-only: mutations and endpoints that do not implement the narrowing respond 403. Caller-asserted placeholder until scope-bearing tokens land, so it is accepted only where ALLOW_HEADER_SPONSOR_SCOPE=true; elsewhere it is rejected with 403. Scoped responses carry a scope-specific ETag and Vary: x-sponsor-party-id."}},"headers":{"IdempotencyKey":{"description":"Client-generated key to make POST requests idempotent.","schema":{"type":"string","maxLength":255}},"ETag":{"description":"Strong validator for optimistic concurrency (If-Match).","schema":{"type":"string"}},"CorrelationId":{"description":"Correlation id echoed on every response.","schema":{"type":"string"}}},"schemas":{"Money":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"integer","description":"Integer minor units (e.g. cents). Never a float."},"currency":{"type":"string","pattern":"^[A-Z]{3}$"}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","correlation_id"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"issue":{"type":"string"}}}},"correlation_id":{"type":"string"}}}}},"Party":{"type":"object","properties":{"id":{"type":"string"},"object":{"const":"party"},"type":{"enum":["person","business","organization"]},"display_name":{"type":"string"},"email":{"type":["string","null"]},"mcards_ref":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":true},"version":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"LinkedPaymentSource":{"type":"object","properties":{"id":{"type":"string"},"object":{"const":"linked_payment_source"},"owner_party_id":{"type":"string"},"type":{"enum":["bank_account","card","credit_line"]},"status":{"enum":["pending","active","suspended","unlinked"]},"display_name":{"type":"string"},"currency":{"type":"string","pattern":"^[A-Z]{3}$"},"instrument_descriptor":{"type":["string","null"]},"mcards_funding_source_ref":{"type":["string","null"]},"supports_balance_check":{"type":"boolean"},"version":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"Commitment":{"type":"object","properties":{"id":{"type":"string"},"object":{"const":"commitment"},"sponsor_party_id":{"type":"string"},"recipient_party_id":{"type":"string"},"linked_payment_source_id":{"type":"string"},"status":{"enum":["draft","invited","accepted","rejected","active","suspended","revoked","expired"]},"display_name":{"type":"string"},"priority":{"type":"integer","description":"Routing preference across a recipient's concurrent commitments; lower = preferred. Ties break by created_at, id. Default 100."},"effective_at":{"type":["string","null"],"format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"},"accepted_at":{"type":["string","null"],"format":"date-time"},"revoked_at":{"type":["string","null"],"format":"date-time"},"version":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"AuthorizationAllocation":{"type":"object","description":"One funded slice of an authorization. A single-sponsor authorization has exactly one; a split has several, each pulling from its own sponsor's instrument. A `personal` slice is the recipient's own consented fallback source and carries no commitment, policy or cap.","properties":{"id":{"type":"string"},"object":{"const":"authorization_allocation"},"authorization_id":{"type":"string"},"kind":{"enum":["sponsor","personal"]},"commitment_id":{"type":["string","null"]},"sponsor_party_id":{"type":"string","description":"Party whose instrument was pulled: the sponsor, or the recipient for a personal slice."},"budget_cap_id":{"type":["string","null"]},"linked_payment_source_id":{"type":"string"},"sequence":{"type":"integer"},"amount":{"$ref":"#/components/schemas/Money"},"refunded_amount":{"$ref":"#/components/schemas/Money"},"policy_id":{"type":["string","null"]},"policy_version_number":{"type":["integer","null"]},"created_at":{"type":"string","format":"date-time"}}},"PolicyExpr":{"description":"Boolean expression tree: a leaf predicate or an and/or/not node.","oneOf":[{"type":"object","description":"Leaf predicate (discriminated by `predicate`).","required":["id","predicate"],"properties":{"id":{"type":"string"},"predicate":{"enum":["amount_max","amount_min","time_window","mcc_in","mcc_not_in","merchant_in","merchant_not_in","channel_in","country_in","cap_remaining","context_required"]}},"additionalProperties":true},{"type":"object","required":["op","rules"],"properties":{"op":{"enum":["and","or"]},"rules":{"type":"array","items":{"$ref":"#/components/schemas/PolicyExpr"}}}},{"type":"object","required":["op","rule"],"properties":{"op":{"const":"not"},"rule":{"$ref":"#/components/schemas/PolicyExpr"}}}]},"Policy":{"type":"object","properties":{"id":{"type":"string"},"object":{"const":"policy"},"scope_type":{"enum":["commitment","budget_cap","card","sponsor","platform"]},"scope_id":{"type":["string","null"]},"display_name":{"type":"string"},"status":{"enum":["draft","active","scheduled","retired"]},"active_version":{"type":["integer","null"]},"metadata":{"type":"object","additionalProperties":true},"version":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"PolicyVersion":{"type":"object","properties":{"id":{"type":"string"},"object":{"const":"policy_version"},"policy_id":{"type":"string"},"version_number":{"type":"integer"},"timezone":{"type":"string"},"when":{"$ref":"#/components/schemas/PolicyExpr"},"effect":{"enum":["ALLOW","DENY"]},"missing_data":{"enum":["DENY","ALLOW"]},"effective_at":{"type":["string","null"],"format":"date-time"},"retired_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"PolicyDecision":{"type":"object","properties":{"object":{"enum":["policy_decision","policy_simulation"]},"decision":{"enum":["ALLOW","DENY"]},"gate":{"const":"POLICY"},"gate_failed":{"enum":["POLICY",null]},"reasons":{"type":"array","items":{"type":"string"}},"evaluated":{"type":"array","items":{"type":"object","properties":{"rule_id":{"type":"string"},"predicate":{"type":"string"},"result":{"enum":["pass","fail","unknown"]},"passed":{"type":"boolean"},"reason_code":{"type":["string","null"]}}}}}},"BudgetCap":{"type":"object","properties":{"id":{"type":"string"},"object":{"const":"budget_cap"},"commitment_id":{"type":"string"},"display_name":{"type":"string"},"cap_amount":{"type":"integer","description":"Limit in minor units."},"used_amount":{"type":"integer"},"remaining_amount":{"type":"integer"},"currency":{"type":"string","pattern":"^[A-Z]{3}$"},"period":{"enum":["none","daily","weekly","monthly","lifetime"]},"rollover":{"type":"boolean"},"version":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"Card":{"type":"object","properties":{"id":{"type":"string"},"object":{"const":"card"},"recipient_party_id":{"type":"string"},"status":{"enum":["active","suspended","closed"]},"display_name":{"type":"string"},"currency":{"type":"string","pattern":"^[A-Z]{3}$"},"mcards_card_ref":{"type":["string","null"]},"personal_funding":{"type":["object","null"],"description":"Recipient's own funding source, used only after every eligible sponsor commitment and only while consent is on record (FCM-008).","properties":{"linked_payment_source_id":{"type":"string"},"consented_at":{"type":"string","format":"date-time"},"consented_by_party_id":{"type":"string"}}},"version":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"PullTransaction":{"type":"object","properties":{"id":{"type":"string"},"object":{"const":"pull_transaction"},"authorization_id":{"type":"string"},"linked_payment_source_id":{"type":"string"},"allocation_id":{"type":["string","null"]},"kind":{"enum":["initial","differential","refund"]},"status":{"enum":["settled","declined","reversed"]},"amount":{"$ref":"#/components/schemas/Money"},"provider":{"type":"string"},"provider_ref":{"type":["string","null"]},"decline_reason":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"}}},"LedgerEntry":{"type":"object","properties":{"id":{"type":"string"},"object":{"const":"ledger_entry"},"authorization_id":{"type":"string"},"pull_id":{"type":["string","null"]},"allocation_id":{"type":["string","null"]},"account":{"enum":["operating_float","sponsor_settlement","recipient_card"]},"direction":{"enum":["debit","credit"]},"amount":{"$ref":"#/components/schemas/Money"},"memo":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"}}},"Authorization":{"type":"object","description":"Two-gate authorization decision. gate_failed distinguishes a policy-gate decline (POLICY) from a sponsor-instrument decline (FUNDING). A funding decline never consumes the budget cap.","properties":{"id":{"type":"string"},"object":{"const":"authorization"},"card_id":{"type":"string"},"commitment_id":{"type":["string","null"],"description":"Primary commitment (sequence 0). For a split authorization see `allocations` for every sponsor slice."},"budget_cap_id":{"type":["string","null"]},"linked_payment_source_id":{"type":["string","null"]},"amount":{"$ref":"#/components/schemas/Money"},"approved_amount":{"oneOf":[{"$ref":"#/components/schemas/Money"},{"type":"null"}]},"captured_amount":{"$ref":"#/components/schemas/Money"},"allocations":{"type":"array","description":"Per-sponsor funded slices (multi-sponsor orchestration). Present on the authorization detail response.","items":{"$ref":"#/components/schemas/AuthorizationAllocation"}},"mcc":{"type":["string","null"]},"merchant_id":{"type":["string","null"]},"merchant_name":{"type":["string","null"]},"channel":{"type":["string","null"]},"country":{"type":["string","null"]},"decision":{"enum":["approved","declined"]},"status":{"enum":["declined","approved","captured","reversed","refunded"]},"gate_failed":{"enum":["POLICY","FUNDING",null]},"reason_code":{"type":["string","null"]},"policy_id":{"type":["string","null"]},"policy_version_number":{"type":["integer","null"]},"decision_detail":{"type":"object","additionalProperties":true},"expires_at":{"type":["string","null"],"format":"date-time"},"version":{"type":"integer"},"created_at":{"type":"string","format":"date-time"}}}},"responses":{"ErrorResponse":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/health":{"get":{"tags":["System"],"summary":"Liveness check","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"const":"ok"}}}}}}}}},"/api/v1/parties":{"post":{"tags":["Parties"],"summary":"Create a party","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["type","display_name"],"properties":{"type":{"enum":["person","business","organization"]},"display_name":{"type":"string"},"email":{"type":"string","format":"email"},"mcards_ref":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Party"}}}},"422":{"$ref":"#/components/responses/ErrorResponse"}}},"get":{"tags":["Parties"],"summary":"List parties","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A page of parties"}}}},"/api/v1/parties/{id}":{"get":{"tags":["Parties"],"summary":"Get a party","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Party"}}}},"404":{"$ref":"#/components/responses/ErrorResponse"}}},"patch":{"tags":["Parties"],"summary":"Update a party (optimistic concurrency via If-Match)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"If-Match","in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"Updated"},"409":{"$ref":"#/components/responses/ErrorResponse"}}}},"/api/v1/linked_payment_sources":{"post":{"tags":["Linked Payment Sources"],"summary":"Link a sponsor payment source (pulled at authorization)","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["owner_party_id","type","display_name","currency"],"properties":{"owner_party_id":{"type":"string"},"type":{"enum":["bank_account","card","credit_line"]},"display_name":{"type":"string"},"currency":{"type":"string","pattern":"^[A-Z]{3}$"},"instrument_descriptor":{"type":"string"},"mcards_funding_source_ref":{"type":"string"},"supports_balance_check":{"type":"boolean"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedPaymentSource"}}}}}},"get":{"tags":["Linked Payment Sources"],"summary":"List linked payment sources","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"owner_party_id","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of linked payment sources"}}}},"/api/v1/commitments":{"post":{"tags":["Commitments"],"summary":"Create a funding commitment","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sponsor_party_id","recipient_party_id","linked_payment_source_id","display_name"],"properties":{"sponsor_party_id":{"type":"string"},"recipient_party_id":{"type":"string"},"linked_payment_source_id":{"type":"string"},"display_name":{"type":"string"},"priority":{"type":"integer","minimum":0,"maximum":100000,"description":"Routing preference across concurrent commitments (lower = preferred). Default 100."},"effective_at":{"type":"string","format":"date-time"},"expires_at":{"type":"string","format":"date-time"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Commitment"}}}}}},"get":{"tags":["Commitments"],"summary":"List commitments","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"sponsor_party_id","in":"query","schema":{"type":"string"}},{"name":"recipient_party_id","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of commitments"}}}},"/api/v1/commitments/{id}":{"get":{"tags":["Commitments"],"summary":"Get a commitment","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Commitment"}}}}}}},"/api/v1/commitments/{id}/actions":{"post":{"tags":["Commitments"],"summary":"Transition a commitment (invite/accept/reject/activate/suspend/revoke/expire) or set its routing priority","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}},{"name":"If-Match","in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["action"],"properties":{"action":{"enum":["invite","accept","reject","activate","suspend","revoke","expire","set_priority"]},"priority":{"type":"integer","minimum":0,"maximum":100000,"description":"Routing preference across the recipient's concurrent commitments; lower wins. Required for set_priority (FCM SET_PRIORITY)."}}}}}},"responses":{"200":{"description":"Transitioned. For revoke/suspend/expire the body also carries `in_flight`: the authorizations this commitment still funds and their outstanding amount. Revocation is prospective (FCM-007) — those authorizations still capture and remain refundable to the sponsor's instrument, but no new pull (including a clearing differential) will be made.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Commitment"},{"type":"object","properties":{"in_flight":{"type":"object","properties":{"authorization_ids":{"type":"array","items":{"type":"string"}},"outstanding_amount":{"$ref":"#/components/schemas/Money"}}}}}]}}}},"422":{"$ref":"#/components/responses/ErrorResponse"}}}},"/api/v1/policies":{"post":{"tags":["Policies"],"summary":"Create a policy (starts in draft with no versions)","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["scope_type","display_name"],"properties":{"scope_type":{"enum":["commitment","budget_cap","card","sponsor","platform"]},"scope_id":{"type":"string"},"display_name":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Policy"}}}}}},"get":{"tags":["Policies"],"summary":"List policies","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"scope_type","in":"query","schema":{"type":"string"}},{"name":"scope_id","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of policies"}}}},"/api/v1/policies/{id}":{"get":{"tags":["Policies"],"summary":"Get a policy","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Policy"}}}},"404":{"$ref":"#/components/responses/ErrorResponse"}}}},"/api/v1/policies/{id}/versions":{"post":{"tags":["Policies"],"summary":"Create an immutable policy version","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["when"],"properties":{"timezone":{"type":"string","default":"UTC"},"when":{"$ref":"#/components/schemas/PolicyExpr"},"effect":{"enum":["ALLOW","DENY"],"default":"ALLOW"},"missing_data":{"enum":["DENY","ALLOW"],"default":"DENY"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyVersion"}}}},"422":{"$ref":"#/components/responses/ErrorResponse"}}},"get":{"tags":["Policies"],"summary":"List a policy's versions","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The policy's versions"}}}},"/api/v1/policies/{id}/versions/{version}":{"get":{"tags":["Policies"],"summary":"Get a specific immutable policy version","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"version","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyVersion"}}}},"404":{"$ref":"#/components/responses/ErrorResponse"}}}},"/api/v1/policies/{id}/actions":{"post":{"tags":["Policies"],"summary":"Activate a version or retire the policy (If-Match)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}},{"name":"If-Match","in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["action","version_number"],"properties":{"action":{"const":"activate"},"version_number":{"type":"integer","minimum":1}}},{"type":"object","required":["action"],"properties":{"action":{"const":"retire"}}}]}}}},"responses":{"200":{"description":"Updated"},"409":{"$ref":"#/components/responses/ErrorResponse"},"422":{"$ref":"#/components/responses/ErrorResponse"}}}},"/api/v1/policies/{id}/simulate":{"post":{"tags":["Policies"],"summary":"Simulate a transaction against a policy version (no funds move, no pull)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["transaction"],"properties":{"version_number":{"type":"integer","minimum":1},"transaction":{"type":"object","required":["amount"],"properties":{"amount":{"$ref":"#/components/schemas/Money"},"timestamp":{"type":"string","format":"date-time"},"mcc":{"type":"string"},"merchant_id":{"type":"string"},"channel":{"type":"string"},"country":{"type":"string"},"cap_remaining":{"$ref":"#/components/schemas/Money"},"context":{"type":"object","additionalProperties":true}}}}}}}},"responses":{"200":{"description":"Decision","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyDecision"}}}},"422":{"$ref":"#/components/responses/ErrorResponse"}}}},"/api/v1/cards":{"post":{"tags":["Cards"],"summary":"Issue a recipient card","parameters":[{"$ref":"#/components/parameters/Cursor"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["recipient_party_id","display_name","currency"],"properties":{"recipient_party_id":{"type":"string"},"display_name":{"type":"string"},"currency":{"type":"string","pattern":"^[A-Z]{3}$"},"mcards_card_ref":{"type":"string"}}}}}},"responses":{"201":{"description":"Card","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Card"}}}},"422":{"$ref":"#/components/responses/ErrorResponse"}}},"get":{"tags":["Cards"],"summary":"List cards","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"List of cards"}}}},"/api/v1/cards/{id}":{"get":{"tags":["Cards"],"summary":"Get a card","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Card","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Card"}}}},"404":{"$ref":"#/components/responses/ErrorResponse"}}}},"/api/v1/cards/{id}/actions":{"post":{"tags":["Cards"],"summary":"Record or withdraw the recipient's consent to fall back to their own funds","description":"Personal funds are a last-resort source (FCM-008/FCM-009): they are drawn only after every eligible sponsor commitment, never in place of one. The nominated source must be owned by the card holder and denominated in the card currency. Withdrawing consent removes it from routing immediately.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}},{"name":"If-Match","in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["action"],"properties":{"action":{"enum":["set_personal_funding","clear_personal_funding"]},"personal_funding":{"type":"object","required":["linked_payment_source_id","consented_by_party_id"],"description":"Required for set_personal_funding.","properties":{"linked_payment_source_id":{"type":"string"},"consented_by_party_id":{"type":"string"}}}}}}}},"responses":{"200":{"description":"Card","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Card"}}}},"404":{"$ref":"#/components/responses/ErrorResponse"},"422":{"$ref":"#/components/responses/ErrorResponse"}}}},"/api/v1/budget_caps":{"post":{"tags":["Budget Caps"],"summary":"Create a budget cap for a commitment (a limit, not stored value)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["commitment_id","display_name","cap_amount","currency"],"properties":{"commitment_id":{"type":"string"},"display_name":{"type":"string"},"cap_amount":{"type":"integer"},"currency":{"type":"string","pattern":"^[A-Z]{3}$"},"period":{"enum":["none","daily","weekly","monthly","lifetime"]},"rollover":{"type":"boolean"}}}}}},"responses":{"201":{"description":"Budget cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BudgetCap"}}}},"422":{"$ref":"#/components/responses/ErrorResponse"}}},"get":{"tags":["Budget Caps"],"summary":"List budget caps","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"List of budget caps"}}}},"/api/v1/budget_caps/{id}":{"get":{"tags":["Budget Caps"],"summary":"Get a budget cap","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Budget cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BudgetCap"}}}},"404":{"$ref":"#/components/responses/ErrorResponse"}}}},"/api/v1/authorizations":{"post":{"tags":["Authorizations"],"summary":"Authorize a card transaction through the two gates","description":"Gate 1 evaluates policy + budget cap; Gate 2 runs the buffered sufficiency check and an immediate authorize+settle pull against the sponsor's linked instrument. When commitment_id is omitted and the card holder has multiple active commitments, they are ranked by priority and the amount is split waterfall-style across sponsor instruments (each slice pulls from its own sponsor's instrument). Declines are returned as an authorization resource (HTTP 201) with decision=declined and gate_failed set. Requires an Idempotency-Key header.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["card_id","amount"],"properties":{"card_id":{"type":"string"},"commitment_id":{"type":"string","description":"Optional; auto-selected when omitted."},"amount":{"$ref":"#/components/schemas/Money"},"mcc":{"type":"string"},"merchant_id":{"type":"string"},"merchant_name":{"type":"string"},"channel":{"type":"string"},"country":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"context":{"type":"object","additionalProperties":true},"expires_in_seconds":{"type":"integer"}}}}}},"responses":{"201":{"description":"Authorization decision (approved or declined)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Authorization"}}}},"422":{"$ref":"#/components/responses/ErrorResponse"}}},"get":{"tags":["Authorizations"],"summary":"List authorizations","description":"With x-sponsor-party-id set, returns only authorizations this sponsor funded, each carrying only that sponsor's own allocations (§13.1).","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/SponsorScope"}],"responses":{"200":{"description":"List of authorizations"}}}},"/api/v1/authorizations/{id}":{"get":{"tags":["Authorizations"],"summary":"Get an authorization with its allocations, pulls and ledger entries","description":"With x-sponsor-party-id set, returns the cross-sponsor privacy view: only this sponsor's own allocations and funded amount, with no other sponsor's data (§13.1).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/SponsorScope"}],"responses":{"200":{"description":"Authorization detail","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Authorization"},{"type":"object","properties":{"allocations":{"type":"array","items":{"$ref":"#/components/schemas/AuthorizationAllocation"}},"pulls":{"type":"array","items":{"$ref":"#/components/schemas/PullTransaction"}},"ledger_entries":{"type":"array","items":{"$ref":"#/components/schemas/LedgerEntry"}}}}]}}}},"404":{"$ref":"#/components/responses/ErrorResponse"}}}},"/api/v1/authorizations/{id}/actions":{"post":{"tags":["Authorizations"],"summary":"Capture, reverse, or refund an approved authorization","description":"capture(final_amount) settles the final cleared amount — a higher amount pulls a SEPARATE differential; refund(amount) partially refunds; reverse fully reverses. Releases/consumes budget cap accordingly. Requires If-Match and Idempotency-Key.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["action"],"properties":{"action":{"enum":["capture","reverse","refund"]},"final_amount":{"type":"integer"},"amount":{"type":"integer"}}}}}},"responses":{"200":{"description":"Updated authorization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Authorization"}}}},"409":{"$ref":"#/components/responses/ErrorResponse"},"422":{"$ref":"#/components/responses/ErrorResponse"}}}}}}