Create an API key
Create an ordinary model key for your account
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
AuthorizationstringheaderrequiredUse 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.
namestringbodyrequiredRequired after trimming whitespace. At most 50 UTF-8 bytes.
expires_atstring | nullbodyA future RFC 3339 timestamp; fractional seconds round upward. null or omission on create means no expiry. Omission on update preserves the value.
unlimitedbooleanbodydefault: falseDefaults to false; null is rejected. With true, remaining_credits must be omitted or null; a value returns 400.
remaining_creditsstringbodydefault: 0Initial remaining quota in credits. Defaults to the string "0".
daily_limit_creditsstring | nullbodyDaily credit limit. null or the string "0" means no limit.
monthly_limit_creditsstring | nullbodyMonthly 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.keystringFull 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": []
}
}