Spend Controls
A Spend Control is a named bundle of rules you can assign to a card, cardholder, account, or your whole business. One spend control can be shared across many objects: assign the same spend_control_id to ten cards, and updating the control updates the limit for all ten at once.
Spend controls are created and managed on Penny Banking (https://sandbox.api.thepennyinc.com). Card and cardholder assignment endpoints are on Penny Issuing (https://issuing.sandbox.api.thepennyinc.com).
Rule types
Every spend control is made of one or more rules. In a request, each rule is a rule_type plus a typed configuration object whose shape depends on that type:
Use the rule guides for configuration shapes and evaluation behavior: Transaction Amount, Velocity, Merchant, Geographic, Currency, Processing, and Live Decisioning. See Missing Transaction Details for how checks behave when a required value is unavailable. Fetch the current schema and an example for every rule type before building a request:
Allowlists and denylists
The merchant, geographic, currency, and processing rules use allowlist and denylist arrays. Configure one list per block:
- Allowlist only: only the listed values pass.
- Denylist only: every value passes except the listed ones.
A value can’t appear in both lists; the request is rejected. If you set both lists on the same block, the denylist governs: a value passes when it is on the allowlist or absent from the denylist, so the allowlist doesn’t narrow anything further. Merchant category codes (merchant_category_codes_rules) are the exception: when that block has an allowlist, only the allowlist is checked and the denylist is ignored.
Creating a spend control
Each rule must explicitly list its applicable_transaction_authorizations and applicable_card_issuance_modes. See Rule Applicability for the supported values. Each rule_type can appear at most once in a spend control.
The spend control response
Responses return the control’s rules in a rules array. Each rule has its own rule_id, version, and version_time, and its configuration fields appear directly on the rule object rather than inside a configuration wrapper. Field names differ by rule type. A transaction_amount rule returns its limits as currency_amount_limits, and a velocity rule returns each window’s current usage and balance:
status is one of active, deactivated, deleting, or deleted. Read-back field names for the other rule types:
Managing a spend control
All of these endpoints are on Penny Banking:
PATCH /spend_controls/{spend_control_id} replaces each rule you send with the same rule_type and leaves the other rules unchanged.
Deactivating a control pauses enforcement of its rules; resume enforcement with activate. Deleting a control removes it from every object it is assigned to. The delete response returns the control with status: "deleting" while removal is in progress; it then moves to deleted and is kept for historical reference.
Assigning it
A spend control applies once it is assigned to the object you want it to govern. Each object has at most one spend control; assigning another replaces it.
Each of these accepts a body of { "spend_control_id": "spend_control_019379d9-a170-796b-867a-a17096b67a21" }. Remove an assignment with the matching DELETE on the same path.
Associations
The associations endpoints on Penny Banking let you look up assignments from either side:
The list endpoint is paginated with page_size and next_page_token. Each item has spend_control_id, associated_object_id, and associated_object_type (business, business_entity, program, account, cardholder, or card). GET /spend_controls/associations/{associated_object_id} returns the full spend control. The DELETE returns 204 No Content.
Business-wide rules
To apply a rule to every card, cardholder, and account in your business, such as blocking a merchant category everywhere or restricting all spend to a set of countries, attach a spend control to the business itself:
A business-wide control is checked on every authorization, alongside any control attached to the card, cardholder, or account involved. Remove it with DELETE /businesses/spend_control.
Where a limit applies
Spend controls can attach at several levels, and more than one can apply to a single transaction, for example a card’s own limit, its cardholder’s limit, and a business-wide rule. Penny checks every attached control, from the most specific level to the broadest:
When a card uses a Control Account, its attached control is checked at the narrower Control Account level, and the funding Capital Account’s control is checked at the broader level. Both apply when both are attached. Without a Control Account, the Capital Account level still applies.
The transaction is authorized only if it passes every rule in every applicable control. No level overrides another, so when two attached controls apply the same rule_type to the same transaction, such as a transaction_amount limit on both the card and its cardholder, each is enforced and the most restrictive one determines the outcome. A $500 per-transaction limit on a card and a $200 limit on its cardholder together decline anything over $200.
live_decisioning is the exception: it runs once per authorization, at the most specific level where a live_decisioning rule is attached. A live_decisioning rule at a broader level is skipped when a more specific level already has one. See Live Decisioning.
See Setting Spend Controls for a worked example of building and assigning one.