ToAPIsToAPIs
API Keys

Update an API key

Update supplied key configuration fields and preserve omitted fields

PATCH
/api/v1/api-keys/{api_key_id}

Note for users in mainland China: Please use https://api.toapis.cn as the API endpoint (Base URL). Replace https://api.toapis.com with https://api.toapis.cn in the examples in this document.

Behavior

Updates a given key's configuration, for example to adjust its name, limits, status, or expiry. The body must contain at least one field.

Name, model allowlist, daily/monthly limits, unlimited, remaining credits, status, and expiry are supported, and omitted fields keep their current values.

Enablement and status

  • Changing configuration alone does not re-enable the key.
  • When the same request explicitly sets status=enabled, the updated expiry, unlimited, and credits are validated together: an expired key or a limited key whose credits are exhausted cannot be enabled and returns 409.
  • A revoked key returns 404.
  • Omitting status leaves the persisted status unchanged: disabled/expired/exhausted keys do not recover from other field updates; a persisted enabled key derives its read status from credits and expiry and may return to enabled after the update.

Validation and writes

  • Amount fields follow the same validation as create: JSON numbers and values that cannot be converted exactly are rejected.
  • model_limits as [] clears model restrictions; daily/monthly limits set to null or "0" clear the limit without resetting the used counters.
  • Setting remaining_credits overwrites the remaining quota stored in the database, and later charges and refunds continue from the new value; batched charges already incurred but not yet persisted still apply afterwards.
  • Updates do not change accumulated usage or the account balance.
  • If any field fails validation, the whole request is rejected without partial writes; the update runs in a transaction that validates the final configuration and writes only explicitly provided fields.
  • Cache invalidation and in-flight request boundaries behave as before.

Authentication

Authorizationstringheaderrequired

Use Bearer YOUR_SYSTEM_ACCESS_TOKEN. Model keys are not accepted and X-User-Id is not required. See access rules.

Request parameters

api_key_idstringpathrequired

Decimal string ID of your ordinary model key, not the sk- secret.

A nonempty body requires Content-Type: application/json and is limited to 16384 bytes. It must be a JSON object. Unknown or duplicate fields and query parameters are rejected. Write bodies have a 10-second read deadline.

statusstringbody

Only enabled or disabled. expired, exhausted, and deleted are read-only states.

expires_atstring | nullbody

A future RFC 3339 timestamp; fractional seconds round upward. null or omission on create means no expiry. Omission on update preserves the value.

namestringbody

Optional name; when supplied, trim whitespace and require a nonempty value of at most 50 UTF-8 bytes.

model_limitsarraybody

Replace the entire model allowlist. [] clears restrictions; null is rejected. Trim each item, reject empty items and commas, and deduplicate in first-seen order. The comma-joined value is limited to 1024 UTF-8 bytes.

daily_limit_creditsstring | nullbody

Daily credit limit. null or the string "0" means no limit.

monthly_limit_creditsstring | nullbody

Monthly credit limit. null or the string "0" means no limit.

unlimitedbooleanbody

Boolean; null is rejected. Switching to false while omitting remaining_credits preserves the stored quota snapshot, which may be exhausted. Does not automatically enable the key.

remaining_creditsstring | nullbody

Set absolute remaining credits, not an increment. With final unlimited=false, only a nonnegative decimal string is accepted; with true, only omission or null is allowed. Omission keeps the stored quota unchanged; null does not clear the quota stored on an unlimited key.

allow_ipsarraybody

Source IP allowlist for this model API key only. A string array of individual IPv4/IPv6 addresses, trimmed, normalized, and deduplicated. [] clears restrictions; null or invalid addresses return 400. CIDR, hostnames, ports, and IPv6 zones are not supported. Omission on PATCH preserves the current value.

Request examples

requestExample

curl --request PATCH \
  --url 'https://api.toapis.com/api/v1/api-keys/43' \
  --header 'Authorization: Bearer YOUR_SYSTEM_ACCESS_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{"status": "disabled"}'
import requests

response = requests.patch(
    "https://api.toapis.com/api/v1/api-keys/43",
    headers={"Authorization": "Bearer YOUR_SYSTEM_ACCESS_TOKEN"},
    json={'status': 'disabled'},
    timeout=30,
)
response.raise_for_status()
print(response.json())
const response = await fetch("https://api.toapis.com/api/v1/api-keys/43", {
  method: "PATCH",
  headers: { Authorization: "Bearer YOUR_SYSTEM_ACCESS_TOKEN", "Content-Type": "application/json" },
  body: JSON.stringify({"status": "disabled"}),
  signal: AbortSignal.timeout(30_000),
});
if (!response.ok) {
  throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
console.log(await response.json());

Response fields

Examples use fictitious data. See Get API key for key metadata and Access for the shared response and error contract.

Response examples

responseExample

{
  "code": 0,
  "message": "",
  "data": {
    "id": "43",
    "name": "Example Key",
    "key_hint": "****xyz9",
    "status": "disabled",
    "created_at": "2026-11-01T08:00:00Z",
    "expires_at": "2027-01-01T00:00:00Z",
    "unlimited": false,
    "remaining_credits": "500",
    "daily_limit_credits": null,
    "monthly_limit_credits": null,
    "model_limits": [],
    "allow_ips": []
  }
}