Merchant Restriction
Limit a spend permission to specific merchants using the allocation controlled save API
Overview
After you have an active spend permission (allocation), you can restrict card spend so it is only allowed at one or more merchants you choose. Use Master merchant search to look up master merchant ids before you post the allowlist. Post the merchant list to POST /md/api/Allocations/controlledSave. From that point on, transactions for that permission are evaluated against the allowlist: spend that does not match a listed merchant is not eligible for that activity.
This is useful when an activity should only work at approved merchants. You can add multiple merchants in a single request, the list you send is the only list of merchants allowed on the activity.
Prerequisites
- A spend permission id (
{allocationId}) from create activity orGET /md/api/Allocations: useassociatedIdfrom the create response when applicable. - The spend permission’s AllocatableType must support merchant selection (
supportsMerchantson the type). If not supported, the API returns an error such as this activity does not support specific merchants. - Your token must be allowed to edit the activity (
Activity/Editaccess for the allocation owner). See Authentication.
Endpoint and headers
| Header | Required | Description |
|---|---|---|
Authorization |
Yes | Bearer {access_token} |
x-appid |
Yes | Your application client id |
Content-Type |
Yes | application/json |
Request body
The body is a JSON object with the allocation id and a partial activity update payload. For merchant restriction only, send allocation.merchants.
| Field | Type | Required | Description |
|---|---|---|---|
allocationId |
string (UUID) | Yes | The spend permission / allocation id to update. |
allocation |
object | Yes | Fields to change on the allocation. For merchant restriction, set merchants to an array of merchant keyword objects. |
allocation.merchants |
array | Yes (for this guide) | Allowlisted merchants. One or more entries. Sending a new array replaces the previous merchant restriction for that permission. |
Merchant entry (merchants[])
Each item in merchants is a keyword object. Master-merchant restrictions (common in integrations) use type "MasterMerchant" and identify the merchant via value / extra.commonId. Merchant group restrictions use type "MerchantGroup" and set value to the merchant group id from create merchant group.
| Field | Type | Description |
|---|---|---|
value |
string | Primary identifier. For MasterMerchant, usually the master merchant commonId. For MerchantGroup, the merchant group id. |
type |
string | Merchant keyword type, for example "MasterMerchant", "Merchant", or "MerchantGroup" depending on how your program catalogs merchants. |
name |
string | Display name (for example "ORACLE UK CORPORATION"). Used for matching and UI; should match the merchant you intend to allow. |
editable |
boolean | Whether the entry can be edited in Custodia UI flows; typically true for partner-supplied lists. |
extra |
object | Optional metadata. For MasterMerchant, commonly includes commonId (master merchant id) and id (vendor-specific or record id). |
How matching works: At authorization time, the transaction is matched against the activity’s merchant rules using factors such as master merchant ID, merchant ID, merchant name, merchant groups, and related matching rules. If a merchant list is configured and is not empty, transactions from merchants outside that list will not be considered a match for the activity.
If your program uses a mix of merchant types, please confirm the matching logic with your Custodia support rep to ensure the behavior aligns with your configuration.
Example request
Master merchants
Restrict an allocation to three master merchants (illustrative ids and names only):
Using cURL:
curl -X POST https://sandbox.custodia-tech.com/md/api/Allocations/controlledSave \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "x-appid: YOUR_CLIENT_ID" \
-H "Content-Type: application/json" \
-d '{
"allocationId": "25ba8b40-6a52-4a69-ac52-d6d43ac6c5da",
"allocation": {
"merchants": [
{
"value": "16fa61de-7691-49d2-bead-113d8d41a50a",
"type": "MasterMerchant",
"name": "ORACLE UK CORPORATION",
"editable": true,
"extra": {
"commonId": "16fa61de-7691-49d2-bead-113d8d41a50a",
"id": "519d989d-89a6-4a28-b74d-029c5f5e2528"
}
},
{
"value": "846238e2-0b77-4c15-ae65-8a4f8d32a77a",
"type": "MasterMerchant",
"name": "ORACLE IRELAND",
"editable": true,
"extra": {
"commonId": "846238e2-0b77-4c15-ae65-8a4f8d32a77a",
"id": "F1eAURCZ_vzrt3sqpDNbh"
}
},
{
"value": "dadcfff2-df59-4e7c-922d-c8abed3b1600",
"type": "MasterMerchant",
"name": "LINKEDIN IRELAND UNLIM",
"editable": true,
"extra": {
"commonId": "dadcfff2-df59-4e7c-922d-c8abed3b1600",
"id": "98398b66-82c4-499c-84e4-f9e060dbf628"
}
}
]
}
}'
Using JavaScript (fetch):
const allocationId = '25ba8b40-6a52-4a69-ac52-d6d43ac6c5da';
const merchants = [
{
value: '16fa61de-7691-49d2-bead-113d8d41a50a',
type: 'MasterMerchant',
name: 'ORACLE UK CORPORATION',
editable: true,
extra: {
commonId: '16fa61de-7691-49d2-bead-113d8d41a50a',
id: '519d989d-89a6-4a28-b74d-029c5f5e2528'
}
},
{
value: '846238e2-0b77-4c15-ae65-8a4f8d32a77a',
type: 'MasterMerchant',
name: 'ORACLE IRELAND',
editable: true,
extra: {
commonId: '846238e2-0b77-4c15-ae65-8a4f8d32a77a',
id: 'F1eAURCZ_vzrt3sqpDNbh'
}
},
{
value: 'dadcfff2-df59-4e7c-922d-c8abed3b1600',
type: 'MasterMerchant',
name: 'LINKEDIN IRELAND UNLIM',
editable: true,
extra: {
commonId: 'dadcfff2-df59-4e7c-922d-c8abed3b1600',
id: '98398b66-82c4-499c-84e4-f9e060dbf628'
}
}
];
const response = await fetch('https://sandbox.custodia-tech.com/md/api/Allocations/controlledSave', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'x-appid': clientId,
'Content-Type': 'application/json'
},
body: JSON.stringify({
allocationId,
allocation: { merchants }
})
});
const allocation = await response.json();
Merchant group
Restrict an allocation to a tenant-defined merchant group. Only type and value are required on each entry; the group must already exist and have active members. See merchant groups.
Request body:
{
"allocationId": "1640adda-9362-4349-b2e6-694c8b4393f8",
"allocation": {
"merchants": [
{
"type": "MerchantGroup",
"value": "ea352739-cf0e-457c-b063-a3885e518e0d"
}
]
}
}
Using cURL:
curl -X POST https://sandbox.custodia-tech.com/md/api/Allocations/controlledSave \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "x-appid: YOUR_CLIENT_ID" \
-H "Content-Type: application/json" \
-d '{
"allocationId": "1640adda-9362-4349-b2e6-694c8b4393f8",
"allocation": {
"merchants": [
{
"type": "MerchantGroup",
"value": "ea352739-cf0e-457c-b063-a3885e518e0d"
}
]
}
}'
Using JavaScript (fetch):
const response = await fetch('https://sandbox.custodia-tech.com/md/api/Allocations/controlledSave', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'x-appid': clientId,
'Content-Type': 'application/json'
},
body: JSON.stringify({
allocationId: '1640adda-9362-4349-b2e6-694c8b4393f8',
allocation: {
merchants: [
{
type: 'MerchantGroup',
value: 'ea352739-cf0e-457c-b063-a3885e518e0d'
}
]
}
})
});
const allocation = await response.json();
Response
On success, the API returns the updated allocation object (root JSON), including the persisted merchants array. Use GET /md/api/Allocations/{allocationId} to verify the restriction if needed.
Success Response (200 OK)
The response is the full allocation record. Only a subset is shown below.
{
"id": "25ba8b40-6a52-4a69-ac52-d6d43ac6c5da",
"status": "active",
"merchants": [
{
"value": "16fa61de-7691-49d2-bead-113d8d41a50a",
"type": "MasterMerchant",
"name": "ORACLE UK CORPORATION",
"editable": true,
"extra": {
"commonId": "16fa61de-7691-49d2-bead-113d8d41a50a",
"id": "519d989d-89a6-4a28-b74d-029c5f5e2528"
}
}
]
}
Constraints and errors
| Situation | Typical outcome |
|---|---|
| Allocation not found | Error indicating the allocation id does not exist. |
Allocation is archived |
Change rejected: activity cannot be modified. |
| AllocatableType does not support merchants | this activity does not support specific merchants |
Caller lacks Activity/Edit |
403 / unauthorized to save. |
Invalid or unknown fields in allocation |
INVALID-INPUT or invalid properties message. |
merchants. Combining merchant changes with budget or date changes may trigger approval workflows or recalculation rules depending on your program: confirm with Custodia before automating mixed updates.
Related documentation
- Master merchant search: find master merchants before building an allowlist
- Merchant groups: create a group and add members before restricting by
MerchantGroup - Merchant search: find issuer-specific merchant records (for example simulation
merchantId) - Spend permission: create and manage allocations
- Get spend permission by id: read back
merchantson the allocation - Authentication: obtain access tokens