Authentication
Every request carries an API key as a bearer token:
curl https://api.moan.hot/v1/account \ -H "Authorization: Bearer mh_live_4Hk2pQ9..."Keys are server secrets. Never ship one in a mobile app, a browser bundle or a public repository. Your own backend calls the API on behalf of your users.
Key format
Section titled “Key format”A key is mh_live_ or mh_test_ followed by 32 random characters. The first 12 characters (for example mh_live_4Hk2) are the prefix: the dashboard shows it, and every generation records the api_key_prefix that created it, so you can tell keys apart without seeing the secret.
We store only a keyed hash of each key. The full key is shown once, when you create it. If you lose it, create a new one.
Test and live
Section titled “Test and live”The prefix selects the mode, and the two modes never see each other’s data.
mh_test_ |
mh_live_ |
|
|---|---|---|
| Charges | Never | The variant price, on success |
| Outputs | Sample files on a simulated timeline | The real effect on your input |
| Webhooks | Real, signed with the test secret | Real, signed with the live secret |
| Works while your account is in review | Yes | Reads only; creates answer account_pending_review |
See Test mode for how to force failures and timeouts.
Scopes
Section titled “Scopes”A key carries one or more scopes. A call without the right scope answers 403 insufficient_scope.
| Scope | Allows |
|---|---|
generations:write |
POST /files, POST /generations, POST /generations/{id}/cancel |
generations:read |
GET on generations, files, effects, prices and usage |
account:read |
GET /account, GET /usage |
Give each service the narrowest set it needs. A worker that only reads results needs generations:read.
Expiry and rotation
Section titled “Expiry and rotation”A key can have an optional expiry date. After it passes, the key answers 401 api_key_expired. To rotate without downtime:
- Create the new key.
- Deploy it everywhere the old one runs.
- Revoke the old key once its “last used” time in the dashboard stops moving.
Revocation
Section titled “Revocation”Revoking a key in the dashboard takes effect within seconds on every server. A revoked key answers 401 api_key_revoked. Revocation cannot be undone.
Disabling and deleting
Section titled “Disabling and deleting”Disabling a key in the dashboard stops it on the next request; calls with it answer 403 api_key_disabled until you enable it again. Deleting a key revokes it first if it still works, then removes it from the dashboard list. A deleted key cannot be restored.
You can also rename a key or change its scopes. The change applies to the next request; the mode and expiry of a key stay as created. A revoked or expired key can be deleted but not edited, and while the account is suspended an edit can only take access away.
IP allowlist
Section titled “IP allowlist”Optionally, restrict a key to a list of IP addresses or ranges in the dashboard. Calls from anywhere else are refused with a 401.
Errors
Section titled “Errors”| Code | Status | Meaning |
|---|---|---|
invalid_api_key |
401 | No Authorization header, a malformed key, or an unknown key |
api_key_expired |
401 | The key’s expiry date has passed |
api_key_revoked |
401 | The key was revoked |
api_key_disabled |
403 | The key is disabled in the dashboard |
insufficient_scope |
403 | The key lacks the scope this route needs |
account_pending_review |
403 | A live create while your account is still in review |
account_suspended |
403 | The account is suspended; only GET /account still answers |
Full list on the Errors page.