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 or GET /md/api/Allocations: use associatedId from the create response when applicable.
  • The spend permission’s AllocatableType must support merchant selection (supportsMerchants on 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/Edit access for the allocation owner). See Authentication.

Endpoint and headers

POST /md/api/Allocations/controlledSave
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.
Other controlled-save fields: The same endpoint accepts other activity updates (dates, purpose, keywords, card binding, limits, and more). This guide only covers 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.