Authentication

Authenticate
API requests

Scripts authenticate with a key. The web app uses a signed-in session. Both spend the same USD balance.

Bearer tokensScoped access
On this page
Authorization headerHTTP
Authorization: Bearer hw_live_...

Keys start with hw_live_ followed by a random string. Put the key in an environment variable. A key that is wrong or revoked returns 401.

Save your key when it is created.

We store a hash. If you lose the key, revoke it in the app and create another. An API key cannot create further keys.

Create a key in the app

Open API keys while signed in. Give the key a name and choose scopes:

ScopeUse it for
humanizeCreating, reading, and canceling runs. This is the scope a rewrite script needs.
detectStarting and reading AI-detection checks. See AI detection. Each check is charged.
billing:readReading balance, ledger, and usage. It does not spend money by itself.

A key can only call endpoints its scopes cover; anything else returns 403 insufficient_scope. New keys get humanize and detect unless you change them. Creating keys is limited to 10 per hour. The browser session that creates the key must send the site’s CSRF cookie. Scripts that already have a key do not.

GET

/v1/me

Returns the account profile, balance, and permission to start a run.

Account responseJSON
{
  "id": "usr_01J9ABCDEF",
  "email": "[email protected]",
  "name": "Alex",
  "balance": {
    "paid_usd": "12.000000",
    "bonus_usd": "1.000000",
    "held_usd": "0.050000",
    "available_usd": "12.950000",
    "bonus_expires_at": "2026-11-04T00:00:00+00:00"
  },
  "restrictions": {
    "batch_enabled": true,
    "max_chars_per_run": 35000,
    "can_run": true,
    "can_run_reason": null
  }
}

available_usd is paid plus bonus, minus anything held for a run in progress. When can_run is false, can_run_reason says why — usually an unverified email or incomplete account setup.

Read restrictions.max_chars_per_run before submitting a draft. The example shows the backend default of 35,000 characters; use the value returned for your account.

GET

/v1/api-keys

Lists keys that have not been revoked. The response includes the prefix, name, scopes, created_at, and last_used_at. It never includes the secret.

DELETE

/v1/api-keys/{id}

Revokes a key. The response is 204 with an empty body. A revoked key stops working immediately.

GET

/v1/billing/balance

The same balance figures as /v1/me, without the profile. Useful for a script that only needs to know whether it can spend.

Balance responseJSON
{
  "paid_usd": "12.000000",
  "bonus_usd": "1.000000",
  "held_usd": "0.050000",
  "available_usd": "12.950000",
  "bonus_expires_at": "2026-11-04T00:00:00+00:00"
}
GET

/v1/billing/ledger

Append-only balance history, newest first. Query limit (default 50, max 200), cursor, and type. The next page is next_cursor.

Ledger requestHTTP
GET /v1/billing/ledger?limit=50
GET

/v1/billing/usage

Usage grouped by day. days defaults to 30.