Z Zise Developers 简体中文

Replace the entire merchant / MCC list (either an allowlist or a blocklist)

PUT /v1/cards/{id}/merchant-rules scope: cards:write
On behalf of a member · x-on-behalf-of required

Use this endpoint to block gambling / adult / crypto MCCs on travel cards, restrict procurement cards to selected suppliers, or restrict subscription cards to one merchant.

⚠ PUT replaces the whole rule; it does not append. The upstream supports one rule per card; an allowlist and blocklist cannot coexist. Send the complete list every time. Treating it as an append operation would replace all existing entries when you thought you were adding one.

⚠ merchant_names and mcc_list cannot both be empty. An empty allowlist would prohibit every merchant, which is almost certainly not intended. Use DELETE to remove restrictions.

⚠ 200 means the upstream confirmed receipt; the response has synced: true. With 502 upstream_error, the rule may already be active. We have stored your requested list as the baseline for subsequent changes, but have no confirmation. Retry with the same idempotency key.

merchant_names matches merchant names in clearing messages, whose formats vary by acquirer (AMAZON / AMZN Mktp US / AMAZON.COM*2K4TY). Use merchant_name from GET /v1/cards/{id}/transactions, not the name on the brand's website.

Prerequisites

  • The card is not closed / expired / replaced.
  • The issuer supports card-level lists (the merchantRules capability flag).

Path Parameters

FieldTypeRequiredDescription
id string Required Card ID
FieldTypeRequiredDescription
x-idempotency-key string Required
x-on-behalf-of string Required The member on whose behalf to call.

Request Body

FieldTypeRequiredDescription
rule_type "white" | "black" Required white permits spending only at listed merchants; black rejects all listed merchants. A card can have only one rule type.
merchant_names string[] Optional Merchant names, maximum 200 entries. An empty array means merchant-name matching is not used.
mcc_list string[] Optional MCC list: four-digit codes under ISO 18245, maximum 200 entries.

Response

200Confirmed by the upstream
{
  "id": "crd_9f2c1b7a-3d51-4a2e-9c08-6b1f0d4e77aa",
  "rule_type": "black",
  "merchant_names": [],
  "mcc_list": [
    "7995",
    "5967",
    "6051"
  ],
  "synced": true,
  "synced_at": "2026-08-13T02:11:47.000Z"
}
400invalid_fields: an MCC is not four digits, both lists are empty, or there are more than 200 entries (includes a fields array identifying each invalid item). state_invalid: card closed or expired. product_not_available: the issuer does not support card-level lists or credentials are incomplete. invalid_request: the upstream rejected the list.
404not_found: the card does not exist or does not belong to this member.
502upstream_error: outcome unknown; the rule may already have been created. Retry with the same idempotency key. A new key does not create a second upstream rule (there is only one per card), but adds an unassociated key to your reconciliation records.
Request
curl -X PUT 'https://api.zinfra.vip/v1/cards/{id}/merchant-rules' \
  -H 'x-auth-token: Bearer $TOKEN' \
  -H 'x-on-behalf-of: $MEMBER_ID' \
  -H 'content-type: application/json' \
  -d '{
    "rule_type": "black",
    "merchant_names": [],
    "mcc_list": [
      "7995",
      "5967",
      "6051"
    ]
  }'
const res = await fetch("https://api.zinfra.vip/v1/cards/{id}/merchant-rules", {
  method: "PUT",
  headers: {
    "x-auth-token": "Bearer $TOKEN",
    "x-on-behalf-of": "$MEMBER_ID",
    "content-type": "application/json",
  },
  body: JSON.stringify({
    "rule_type": "black",
    "merchant_names": [],
    "mcc_list": [
      "7995",
      "5967",
      "6051"
    ]
  }),
});
// Keep monetary amounts as strings, never numbers.
const data = await res.json();
import requests

res = requests.put(
    "https://api.zinfra.vip/v1/cards/{id}/merchant-rules",
    headers={
        "x-auth-token": "Bearer $TOKEN",
        "x-on-behalf-of": "$MEMBER_ID",
        "content-type": "application/json",
    },
    json={
      "rule_type": "black",
      "merchant_names": [],
      "mcc_list": [
        "7995",
        "5967",
        "6051"
      ]
    },
)
# Use Decimal(str(...)) for amounts, not float.
data = res.json()
req, _ := http.NewRequest("PUT", "https://api.zinfra.vip/v1/cards/{id}/merchant-rules",
    strings.NewReader(`{
  "rule_type": "black",
  "merchant_names": [],
  "mcc_list": [
    "7995",
    "5967",
    "6051"
  ]
}`))
req.Header.Set("x-auth-token", "Bearer $TOKEN")
req.Header.Set("x-on-behalf-of", "$MEMBER_ID")
req.Header.Set("content-type", "application/json")
res, err := http.DefaultClient.Do(req)
// Decode amount fields as string, not float64.
HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://api.zinfra.vip/v1/cards/{id}/merchant-rules"))
    .header("x-auth-token", "Bearer $TOKEN")
    .header("x-on-behalf-of", "$MEMBER_ID")
    .header("content-type", "application/json")
    .method("PUT", HttpRequest.BodyPublishers.ofString("""
{
  "rule_type": "black",
  "merchant_names": [],
  "mcc_list": [
    "7995",
    "5967",
    "6051"
  ]
}
"""))
    .build();
// Use String / BigDecimal for amounts, not double.
$ch = curl_init('https://api.zinfra.vip/v1/cards/{id}/merchant-rules');
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => 'PUT',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'x-auth-token: Bearer $TOKEN',
    'x-on-behalf-of: $MEMBER_ID',
    'content-type: application/json',
  ],
  CURLOPT_POSTFIELDS => <<<'JSON'
{
  "rule_type": "black",
  "merchant_names": [],
  "mcc_list": [
    "7995",
    "5967",
    "6051"
  ]
}
JSON,
]);
$res = curl_exec($ch);
// Use bcmath / strings for amounts, not floatval.
200
{
  "id": "crd_9f2c1b7a-3d51-4a2e-9c08-6b1f0d4e77aa",
  "rule_type": "black",
  "merchant_names": [],
  "mcc_list": [
    "7995",
    "5967",
    "6051"
  ],
  "synced": true,
  "synced_at": "2026-08-13T02:11:47.000Z"
}