Set user-defined limits (0 means unset; the product maximum applies)
x-on-behalf-of required
⚠ 0 means no limit at this layer, not that no spending is allowed. All three values are 0 for a new card; the effective limits then come from the product-level max_*. Setting 0 to 0 is a no-op. Enter a positive amount to tighten a limit.
⚠ Limits below one currency unit are always rejected; "0.5" on a USD card is rejected. The upstream's three fields are integers, where 0 means unlimited. Silently rounding down would turn an attempt to tighten the limit into removing it entirely, the opposite of the user's intention.
The three levels must be consistent: per-transaction ≤ daily ≤ monthly; 0 is excluded from comparisons. Without validation, a user could save a per-transaction limit of 5000 and a daily limit of 100, then be declined at checkout without knowing which limit caused it.
⚠ 200 means only that we have recorded the change. Limits are sent to the upstream asynchronously, and changes must only take effect in the safer direction: a decrease is recorded only after success; a failed increase retains the previous value. Do not interpret 200 as confirmation that the upstream limit is active.
Omitting an item preserves its previous value; it does not clear it. If limits_updatable in card details is false, returns product_not_available without changing limits or adding a retry task.
Prerequisites
- The card is not
closed/closing/expired. - Each value is no greater than the product-level
max_*.
Path Parameters
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Required | Card ID |
Request Headers
| Field | Type | Required | Description |
|---|---|---|---|
x-on-behalf-of |
string | Required | The member on whose behalf to call. |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
single |
string | Optional | Per-transaction limit, a decimal string in the card currency. Omit to keep the previous value; "0" means no limit.USD:"500.00" |
daily |
string | Optional | Daily limit. Must be ≥ single when neither is 0. |
monthly |
string | Optional | Monthly limit. Must be ≥ daily when neither is 0. |
Response
{
"id": "crd_9f2c1b7a-3d51-4a2e-9c08-6b1f0d4e77aa",
"accepted": true
}state_invalid: card closed or expired. product_not_available: product unavailable.
invalid_fields: exceeds a product maximum, inconsistent limit levels, or less than one currency unit.
⚠ Here, invalid_fields currently has no fields array, unlike other endpoints.
All three cases share this code, so you can only report Invalid limits without identifying the affected item.
⚠ An invalid amount string, such as "abc" or too many decimal places for card_scale,
currently returns 500 api_error. Validate the format before sending.not_found: the card does not exist or does not belong to this member.curl -X PATCH 'https://api.zinfra.vip/v1/cards/{id}/limits' \
-H 'x-auth-token: Bearer $TOKEN' \
-H 'x-on-behalf-of: $MEMBER_ID' \
-H 'content-type: application/json' \
-d '{
"single": "500.00",
"daily": "2000.00",
"monthly": "10000.00"
}'const res = await fetch("https://api.zinfra.vip/v1/cards/{id}/limits", {
method: "PATCH",
headers: {
"x-auth-token": "Bearer $TOKEN",
"x-on-behalf-of": "$MEMBER_ID",
"content-type": "application/json",
},
body: JSON.stringify({
"single": "500.00",
"daily": "2000.00",
"monthly": "10000.00"
}),
});
// Keep monetary amounts as strings, never numbers.
const data = await res.json();import requests
res = requests.patch(
"https://api.zinfra.vip/v1/cards/{id}/limits",
headers={
"x-auth-token": "Bearer $TOKEN",
"x-on-behalf-of": "$MEMBER_ID",
"content-type": "application/json",
},
json={
"single": "500.00",
"daily": "2000.00",
"monthly": "10000.00"
},
)
# Use Decimal(str(...)) for amounts, not float.
data = res.json()req, _ := http.NewRequest("PATCH", "https://api.zinfra.vip/v1/cards/{id}/limits",
strings.NewReader(`{
"single": "500.00",
"daily": "2000.00",
"monthly": "10000.00"
}`))
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}/limits"))
.header("x-auth-token", "Bearer $TOKEN")
.header("x-on-behalf-of", "$MEMBER_ID")
.header("content-type", "application/json")
.method("PATCH", HttpRequest.BodyPublishers.ofString("""
{
"single": "500.00",
"daily": "2000.00",
"monthly": "10000.00"
}
"""))
.build();
// Use String / BigDecimal for amounts, not double.$ch = curl_init('https://api.zinfra.vip/v1/cards/{id}/limits');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'x-auth-token: Bearer $TOKEN',
'x-on-behalf-of: $MEMBER_ID',
'content-type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{
"single": "500.00",
"daily": "2000.00",
"monthly": "10000.00"
}
JSON,
]);
$res = curl_exec($ch);
// Use bcmath / strings for amounts, not floatval.
{
"id": "crd_9f2c1b7a-3d51-4a2e-9c08-6b1f0d4e77aa",
"accepted": true
}