Skip to main content

API Overview

The Token Management API lets you handle the full lifecycle of your API keys in code, instead of clicking through the console one key at a time. The most common use case is batch issuance: giving each team member, downstream customer, or project its own key, each with its own limits on how much it can spend, which models it can call, and how long it stays valid. Combined with a scheduled job, you can also give each key a daily budget that resets automatically.

Quota limit

remain_quota caps how much this key can spend in total

Model limit

models sets an allowlist; calls to anything outside it are rejected

Expiry limit

expired_time sets an expiry timestamp, after which the key stops working
If you only need one or two keys, the console is faster — see How to create an API key. This API is aimed at automated issuance, scheduled rotation, or integrating key management into your own systems.

How to Get a Personal Access Token

The Token Management API authenticates with a personal access token (starting with nap_), which is not the same thing as an API key.
1

Open Personal Access Tokens

Go to your profile page at api.apiyi.com/account/profile. Under Account Options, click Personal Access Tokens → Create Token.
2

Select the Model keys permissions you need

The three permissions are independent. Select only the ones you use:A bulk-issuance script needs all three. A usage-monitoring script only needs Read.
3

Set the expiry and IP allowlist

The default expiry is 30 days, so we recommend a longer period. If your issuance script runs on a server with a fixed IP, we strongly recommend an IP allowlist. The allowlist can’t be edited after creation, so get the script working without one first, then create a separate production token with an allowlist.
Create a personal access token: name, expiry, IP allowlist and permissions
A token with Write and Reveal secret can create API keys that call models. Treat it like your account password.A personal access token cannot call models itself, but it can issue keys that can. Give this kind of token an IP allowlist, store it in a secret manager rather than in code, never commit it to a repository, and replace it before it expires.
Legacy system tokens are scheduled to retire on 2026-11-11 (UTC+8). AccessTokens generated under “Account Options - System Token” keep working until then. After that date they return 401 ACCESS_TOKEN_LEGACY_RETIRED. We will review usage and may extend the date, but we recommend switching to a personal access token now. When you switch, also check your scripts: the create endpoint now returns a masked key. To get the plaintext, call POST /api/token/{id}/key as described below. See What Is a Personal Access Token?

Endpoints

All endpoints authenticate the same way: put the personal access token in the Authorization header. The Bearer prefix is optional. The base URL is https://api.apiyi.com.

Creating a Token

Request Example

Request Fields

unlimited_quota defaults to false and remain_quota defaults to 0 — omitting both produces a token with zero quota that cannot be used. Either set remain_quota explicitly or set unlimited_quota to true.
Use the models field for the model allowlist.The response structure also contains model_limits, model_limits_enabled, and allow_ips. Passing these does not raise an error — the endpoint still returns 200 — but they currently have no effect, and reading the token back shows them unset. Use models to restrict available models. Source-IP restrictions need to be implemented on your own side for now.

Response Example

The key in the response is masked and can’t be used directly. To get the plaintext, call the retrieve-plaintext endpoint with the id from the response.

Retrieve the Key Plaintext

  • The personal access token needs Model keys · Reveal secret, otherwise you get 403 ACCESS_TOKEN_SCOPE_DENIED.
  • The returned key does not include the sk- prefix. Prepend it yourself. In the example above, the actual API key is sk-K1RPzapu….
  • Save it right away and distribute it over a secure channel. Don’t leave the response body in log files.

Batch Creation

There is no server-side batch endpoint — passing something like count in the request body has no effect and still creates a single token. Batch issuance is done by looping on the client.
A single user can hold at most 1,000 tokens. This is an account-wide cap and it counts tokens that are disabled but not deleted. Once you hit it, the create endpoint fails — delete tokens you no longer use to free up slots.Before a batch run, page through GET /api/token/?p=0&page_size=100 to count what you already have. When rotating keys, actually finish the last step of “create new key → shift traffic → disable old key → delete once no calls remain”. Disabling without deleting keeps the slot occupied, so a few rotation cycles will run you into the cap.

Using the Three Limits

Quota limit

remain_quota caps what the token can spend. The conversion matches the Balance Query API:

Conversion Rule

500,000 quota = $1.00 USD
For example, to issue a downstream customer a key capped at $10, set remain_quota to 5000000 with unlimited_quota set to false. Consumption so far is readable from the token’s used_quota field. remain_quota is a one-off total and does not refill on its own. For a daily budget, see Scenario: Daily Per-Key Limits That Reset Automatically below.

Model limit

models is a comma-separated allowlist. Once set, calling a model outside the list is rejected:
The response is HTTP 403 and no charge is incurred. Omitting models means no restriction.

Expiry limit

expired_time is a Unix-seconds timestamp, with -1 meaning never. For example, a key that expires in 30 days:

Listing Tokens

Key fields:

Updating a Token

The update endpoint requires the complete object — it is not a patch.The correct flow is: GET the full token object, modify the fields you want to change, then PUT the whole object back. Sending only the changed fields will clear the rest.

Scenario: Daily Per-Key Limits That Reset Automatically

When a company hands keys to workflows, team members, or downstream projects, a common requirement is “each key may spend at most $5 a day, and the limit comes back the next day”. If a workflow runs away, the damage is capped at one day’s budget. The platform has no built-in “daily quota” field yet, but the update endpoint above plus a scheduled job that runs once at midnight does the job: every day it sets remain_quota on those keys back to the daily cap. The keys themselves never change, so team members keep using the same key. Once a key’s budget is used up for the day, calls are rejected (and not charged); after the midnight reset they work again.
1

Prepare a personal access token

Grant Model keys · Read and Model keys · Write; Reveal secret is not needed. If the script runs on a server with a fixed IP, set an IP allowlist on the token.
2

List the keys to limit and their daily caps

Look up each key’s id with the listing endpoint and fill them into DAILY_BUDGET_USD in the script below.
3

Run the script once a day at 00:00 (UTC+8)

cron, a cloud-function timer, or any scheduler will do — see below.

Reset script

The script does three extra things:
  • No double resets: if it fires twice in one day (a scheduler catch-up run, a manual rerun), it does not hand out another day’s budget
  • Carries overspend forward: the quota is a soft cap (see below), so whatever went over yesterday is deducted today, keeping the daily average within the cap over time. Set CARRY_OVERDRAFT to False if you don’t want this
  • Prints yesterday’s spend: each run logs how much every key spent in the previous period, so the log doubles as a simple daily report

Scheduling

Put the token in an environment file only you can read, then trigger the script daily with cron:
To define “a day” in another time zone, change both the cron time and TZ in the script.

Things to know before you rely on it

The quota is a soft cap, not a precise brake. The quota check happens when a request starts, so several concurrent requests can pass it at the same time, and a single expensive request (video, 4K images, very long context) can cross the cap in one go, pushing the balance negative. The higher the concurrency and unit price, the bigger the overshoot. The script’s overspend carry-forward deducts it the next day; if some keys must never overshoot, control their concurrency on your own side or use the models allowlist to exclude expensive models.
  • A reset overwrites, it doesn’t add: unused budget does not roll over to the next day. Any manual change you make to these keys’ quota in the console is also overwritten at the next reset
  • Requests in flight around midnight: a request sent before midnight that finishes after it may be billed against the new day — usually a small amount
  • If the script doesn’t run, keys stay exhausted: calls are temporarily blocked, but nothing extra is spent. Add failure alerts to the scheduled job
  • The account balance is still the master limit: if the keys’ daily caps add up to more than your account balance, the balance runs out first and every key stops
  • Need to give one key a bit more today? Raise that key’s remain_quota with the update endpoint; it resets back to the cap the next day as usual

Disabling and Deleting

Disable (keeps the record)

Once disabled, the key stops working immediately — calls with it return 401 — but the token record and its usage history are retained.

Delete (irreversible)

Batch deletion is likewise a client-side loop:
Deletion cannot be undone. If you only want to suspend a key temporarily, disable it instead — the usage history stays available for reconciliation.

FAQ

The create endpoint returns a masked key (with a run of * in the middle), so it can’t be used directly. Call POST /api/token/{id}/key with the returned id to get the plaintext (needs the Reveal secret permission), then prepend sk-. If an older script uses the key from the create response directly, add this step when you switch to a personal access token.
Most likely neither remain_quota was set nor unlimited_quota was set to true at creation. That default combination produces a token with zero quota. Recreate it with one of the two specified explicitly.
Those fields — along with model_limits_enabled — currently do not take effect. Passing them raises no error but nothing is stored. Use models to restrict available models; source-IP restrictions need to be handled on your own side for now.
There is no server-side batch endpoint, and passing something like count in the body has no effect. Loop the create call on the client instead — see the batch creation section above.
At most 1,000 per user, and tokens that are disabled but not deleted count toward that total. Once you reach the cap, creation fails until you delete tokens you no longer need. When rotating keys, remember to finish with the delete step — disabling alone keeps the slot taken.
There is no built-in daily quota field, but a scheduled job does it: at 00:00 (UTC+8) every day, call the update endpoint to set those keys’ remain_quota back to the daily cap. The keys don’t change; once a key’s budget is used up, calls are rejected and not charged, and it works again the next day. See Scenario: Daily Per-Key Limits That Reset Automatically above for the full script and caveats.
The update endpoint requires the complete object. GET the full object first, modify it, then PUT the whole thing back rather than sending only the changed fields.
Disabling (status: 2) stops the key working immediately but keeps the record and usage history, and you can set it back to 1 at any time. Deleting is irreversible and removes the record. For temporary suspension, prefer disabling.
The token’s used_quota field is that key’s cumulative spend (÷ 500,000 = USD). For a per-period breakdown or call-level detail, filter by token name on the console log page — see How to view my call records.

Important Notes

A personal access token is not an API key, and the two are not interchangeable
  • An API key (starting with sk-) is for /v1/* inference endpoints
  • A personal access token (starting with nap_) is for /api/* management endpoints and cannot call models
Error reference: 401 ACCESS_TOKEN_LEGACY_RETIRED means you are still using a retired legacy system token. 401 This access token may not be used from the current IP address. means the request came from an IP outside the token’s allowlist. 403 ACCESS_TOKEN_SCOPE_DENIED means the token lacks the permission this endpoint needs (see the Endpoints table).
Handle plaintext keys carefullyThe retrieve-plaintext endpoint returns a key that can call models directly. Therefore:
  • Do not write response bodies containing key into log files or commit them to a repository
  • Distribute keys to team members over secure channels, not group chats
  • This plaintext does not carry the sk- prefix, so common secret scanners may not detect it — do not rely on automated checks to catch it for you
Operational tips
  • When creating in bulk, add a modest delay between calls to avoid high instantaneous concurrency
  • Give each key a meaningful name (such as team-alice or prod-webhook) so you can attribute usage by token_name in the logs later
  • For rotation: create the new key, shift traffic, disable the old key, observe for a while, and only delete it once you confirm no calls remain

Related Documentation