Authentication
Create and rotate mak_ API keys, give each one the scopes it needs, cap its spending, and let a browser poll with a pat_ token.
Every request sends one credential as Authorization: Bearer <credential> to
https://api.mynth.io. There is no /v1 prefix. Which credential you send
depends on where the code runs:
| Where the code runs | Credential | Reaches |
|---|---|---|
| Your server | mak_... | Every endpoint the key's scopes allow |
| A browser | pat_... | GET /tasks/{id}/status and /result for one task |
| mynth.io | OAuth | The dashboard and playground. Your code never sends this. |
The API key is the only credential you create and store. The pat_ token is
issued with each task. The API reference
has the header rules, the scope each endpoint needs, CORS, and every
authentication error.
Create a key#
npx @mynthio/cli auth login
npx @mynthio/cli api-key create my-appPOST /api-key needs a key with the keys scope. In the
dashboard, the new key appears once in a dialog, next to
a ready-made MYNTH_API_KEY=mak_... line.
The key is shown once. The create response carries it at data.raw, and no
endpoint returns it again. Mynth stores only an HMAC-SHA256 of the key, so a
lost key cannot be recovered. Lists show keyPreview, such as mak_9d4...e3f.
A key is mak_ followed by 48 hex characters. An account can hold 100 live
keys. Deleted keys do not count toward that.
The SDK and the CLI both read MYNTH_API_KEY. In the CLI it takes precedence
over the key stored by auth login.
Check a key#
GET /me accepts any key and describes it. npx @mynthio/cli whoami prints
the same thing.
curl https://api.mynth.io/me -H "Authorization: Bearer $MYNTH_API_KEY"{
"data": {
"userId": "user_01JD8G3W1R5T6Y7U8I9O0P1Q2W",
"auth": {
"method": "api-key",
"apiKey": {
"id": "ak_01KE7XWWEQ4MCGWKBQKJ1G47RP",
"name": "my-app",
"keyPreview": "mak_9d4...e3f",
"scopes": ["generate"],
"spending": { "mode": "unlimited" }
}
}
}
}Run it first when a request fails with 401 or 403.
Scopes#
A key carries one or more scopes. New keys get generate unless you ask for
more.
| Scope | Reaches |
|---|---|
generate | /image/*, /video/*, /tasks/*, /me |
manage | /webhook, /destinations, /balance, /me |
keys | /api-key, /me |
Give a key only what its job needs. A leaked generate key can spend your
balance. It cannot create keys, read your balance, or point a webhook
somewhere else.
You can change a key's scopes later, on its page in the
dashboard or with PUT /api-key/{id}. The change applies
to the next request.
An API key cannot grant manage or keys. When the caller authenticates
with an API key, POST /api-key and PUT /api-key/{id} accept only
["generate"] and answer anything wider with 403 SCOPE_ESCALATION. Create
or widen those keys in the dashboard. The key auth login creates is the
exception: it is minted through the browser approval and gets all three
scopes by default.
Rotate a key#
Create a second key, deploy it, then delete the first. Both keys work during the switch. Deleting a key revokes it immediately.
Spending limits#
A key can carry a USD cap that resets each day, week, or calendar month. Set
it on the key's page in the dashboard, or send spendingLimit and
spendingLimitPeriod to PUT /api-key/{id}. The create call does not take
one.
The cap counts each task's estimate when the task is created. Once the next
estimate would pass the cap, creating a task fails with
429 SPENDING_LIMIT_EXCEEDED until the period rolls over. A task that fails
later does not give its estimate back to the cap. GET /me reports used,
limit, and remaining for a capped key.
Browser polling#
POST /image/generate, POST /image/remove-background, and
POST /video/generate return data.access.publicAccessToken, a pat_ token
for that one task. It works only on GET /tasks/{id}/status and
GET /tasks/{id}/result for that task, and it expires one hour after it is
issued.
Create the task on your server, give the browser the task id and the token, and poll from the page. Poll for results has the code, and the reference has every rule.
Never ship a mak_ key to the browser. Only the two polling paths allow cross-origin requests, so
a key in a page cannot generate from that page, but anyone can read it from the bundle and spend
your balance from anywhere else.
Next steps#
- Authentication reference: the header, per-endpoint scopes, CORS, and error codes.
- Getting started: first key, first image.
- Webhooks: signed with their own
wbs_secret, separate from your key.