ToAPIsToAPIs
API Keys

Create an API key

Create an ordinary model key for your account

POST
/api/v1/api-keys

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

Creates a new model key for calling generation endpoints. On success it returns HTTP 201 and the full secret: the secret appears only in this response, later GETs never return it, so save it immediately. The new key uses the account's base group.

You cannot choose a group, cross-group retry, or webhook configuration. The initial credit is the key's call limit and is not debited from the account balance.

Amount fields accept only nonnegative decimal strings that convert exactly to the integer quota units used internally. Fractional values are not truncated automatically. Each account can keep at most 10000 undeleted keys, and exceeding this returns 409 (code=13004).

Create is not idempotent: if the response is lost, check the key list before retrying instead of resending. If the key was created but the secret was not saved, rotate it to obtain a new one.

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

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.

namestringbodyrequired

Required after trimming whitespace. At most 50 UTF-8 bytes.

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.

unlimitedbooleanbodydefault: false

Defaults to false; null is rejected. With true, remaining_credits must be omitted or null; a value returns 400.

remaining_creditsstringbodydefault: 0

Initial remaining quota in credits. Defaults to the string "0".

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.

model_limitsarraybodydefault:

Model ID array, default []. Nonempty enables model limits. Entries are trimmed, must be nonempty without commas, and are deduplicated in first-seen order; joined length is at most 1024 UTF-8 bytes.

allow_ipsarraybodydefault:

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.

Request examples

requestExample

curl --request POST \
  --url 'https://api.toapis.com/api/v1/api-keys' \
  --header 'Authorization: Bearer YOUR_SYSTEM_ACCESS_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{"name": "Example Key", "expires_at": "2027-01-01T00:00:00Z", "unlimited": false, "remaining_credits": "500", "daily_limit_credits": null, "monthly_limit_credits": null, "model_limits": ["example-image-model"]}'
import requests

response = requests.post(
    "https://api.toapis.com/api/v1/api-keys",
    headers={"Authorization": "Bearer YOUR_SYSTEM_ACCESS_TOKEN"},
    json={'name': 'Example Key', 'expires_at': '2027-01-01T00:00:00Z', 'unlimited': False, 'remaining_credits': '500', 'daily_limit_credits': None, 'monthly_limit_credits': None, 'model_limits': ['example-image-model']},
    timeout=30,
)
response.raise_for_status()
print(response.json())
const response = await fetch("https://api.toapis.com/api/v1/api-keys", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_SYSTEM_ACCESS_TOKEN", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "Example Key", "expires_at": "2027-01-01T00:00:00Z", "unlimited": false, "remaining_credits": "500", "daily_limit_credits": null, "monthly_limit_credits": null, "model_limits": ["example-image-model"]}),
  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.

data.keystring

Full secret including the sk- prefix, returned only by this create or rotate response.

Response examples

responseExample

{
  "code": 0,
  "message": "",
  "data": {
    "id": "43",
    "name": "Example Key",
    "key_hint": "****xyz9",
    "status": "enabled",
    "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,
    "key": "sk-example00000000000000000000000000000000000000xyz9",
    "model_limits": [
      "example-image-model"
    ],
    "allow_ips": []
  }
}