# Account

> Your account, keys, people, usage, requests and purchases. Generated from the API contract.

## GET `/v1/account`

Your balance, plan limits and caps, and who you are.

Readable with either scope, so a scraper or an MCP agent can check the
balance with its scrape key. Free.

### Answers

| status | what it means |
| -- | -- |
| `200` | The account of the key you sent. |
| `401` | bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts. |
| `429` | rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again. |
| `500` | internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id. |
| `503` | busy. A store we need did not answer, or is not configured on this server. Send the same request again after the Retry-After seconds. |


## PATCH `/v1/account`

Change your name, retention, default country, spend cap or usage alerts.

The same body and answer as PATCH /api/account, with an account key. Any member changes
their own name; only an owner changes the rest.

### Body

| field | required | type or values | what it is |
| -- | -- | -- | -- |
| `name` | no | string | No control characters. |
| `retention_days` | no | integer, 1 to 90 | How many days we keep your request records. Batch results and screenshots are kept 7 days whatever this says, so a value under 7 does not remove them sooner; DELETE /v1/batches/{id} does. |
| `default_country` | no | string or null | A country code from GET /v1/geos. Requests without country_code exit from it. null goes back to the platform default. |
| `spend_cap` | no | integer or null, 1 to 2147483647 | Credits the account may spend per UTC month. A request, batch item, monitor check or LLM step that would pass it gets a free 402 spend_cap. null removes the cap. |
| `alerts` | no | object |  |
| `found_us` | no | `search`, `ai_assistant`, `friend`, `social`, `community`, `directory`, `blog`, `other` | How you found us. The first answer is kept; a later one is accepted and ignored. |


### Answers

| status | what it means |
| -- | -- |
| `200` | The account after the change. |
| `400` | bad_parameter: a field is missing, wrong, or not one this request takes; error.field names it. bad_request: the body is not one JSON object. |
| `401` | bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts. |
| `403` | owner_only for anything but name as a member, or wrong_scope with a scrape key. |
| `413` | body_too_large. The body was larger than 4 KiB. |
| `415` | unsupported_media_type. Send Content-Type: application/json, even for an empty {} body. |
| `429` | rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again. |
| `500` | internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id. |
| `503` | busy. A store we need did not answer, or is not configured on this server. Send the same request again after the Retry-After seconds. |


## POST `/v1/account/webhook-secret/rotate`

Make a new webhook signing secret and show it once.

Owner only, with an account key or a dashboard session. The answer shows the new secret
once; we never show it again. For 24 hours the old secret also signs, so the
X-Megalania-Signature header carries two values; check that one of them matches. At most
5 rotations an hour.

### Answers

| status | what it means |
| -- | -- |
| `200` | The new secret, shown once. |
| `401` | bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts. |
| `403` | owner_only for a member, wrong_scope with a scrape key. |
| `429` | rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again. |
| `500` | internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id. |
| `503` | busy. A store we need did not answer, or is not configured on this server. Send the same request again after the Retry-After seconds. |


## POST `/v1/account/webhooks/test`

Send a signed test event to a webhook receiver.

Any member, with an account key or a dashboard session. We POST one signed test event, with
no retry, to url or, when url is left out, to alerts.webhook_url. Free. At most 5 a
minute per account.

### Body

| field | required | type or values | what it is |
| -- | -- | -- | -- |
| `url` | no | string | One https URL on a public host. Leave it out to use alerts.webhook_url. |


### Answers

| status | what it means |
| -- | -- |
| `200` | What the receiver answered. A receiver that answers 500 is still a 200 here. |
| `400` | bad_parameter: a field is missing, wrong, or not one this request takes; error.field names it. bad_request: the body is not one JSON object. |
| `401` | bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts. |
| `403` | wrong_scope with a scrape key. |
| `413` | body_too_large. The body was larger than 4 KiB. |
| `415` | unsupported_media_type. Send Content-Type: application/json, even for an empty {} body. |
| `429` | rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again. |
| `500` | internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id. |
| `503` | busy. A store we need did not answer, or is not configured on this server. Send the same request again after the Retry-After seconds. |


## GET `/v1/account/keys`

List keys.

An owner sees every key of the account. A member sees the keys they made.

### Parameters

| name | in | required | type or values | what it is |
| -- | -- | -- | -- | -- |
| `cursor` | query | no | string | The next_cursor of the previous page, unchanged. Absent means the first page. |
| `limit` | query | no | integer, 1 to 100; default `50` | Rows per page, 1 to 100. |


### Answers

| status | what it means |
| -- | -- |
| `200` | One page of keys. Never the key itself. |
| `400` | bad_parameter. error.field names the parameter; the message says which values work. An unknown query key is this 400 too. |
| `401` | bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts. |
| `403` | wrong_scope (a scrape key on a route that needs an account key, or an account key on a scraping or batches route) or owner_only (your role is member). |
| `429` | rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again. |
| `500` | internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id. |
| `503` | busy. A store we need did not answer, or is not configured on this server. Send the same request again after the Retry-After seconds. |


## POST `/v1/account/keys`

Make a new key.

The key belongs to you, the person whose account key made the call.
To give a teammate a key, add them as a member; they make their own
with a key of theirs, or an owner makes one and hands it over through
a password manager. The answer shows the key once. It works within 60
seconds.

### Body

| field | required | type or values | what it is |
| -- | -- | -- | -- |
| `name` | no | string | 1 to 64 characters, no control characters. Default is the scope word. |
| `scope` | no | `scrape`, `account`; default `scrape` |  |
| `expires_at` | yes | string | Required. RFC 3339 in UTC, in the future and at most 400 days ahead. The key stops working then. |


### Answers

| status | what it means |
| -- | -- |
| `201` | The new key, shown once, and its record. |
| `400` | bad_parameter: a field is missing, wrong, or not one this request takes; error.field names it. bad_request: the body is not one JSON object. |
| `401` | bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts. |
| `402` | over_plan. Your plan's key limit is reached. Revoke a key first. |
| `403` | wrong_scope, or notice_required (the person who made this key has not accepted the current beta notice in the dashboard). |
| `413` | body_too_large. The body was larger than 4 KiB. |
| `415` | unsupported_media_type. Send Content-Type: application/json, even for an empty {} body. |
| `429` | rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again. |
| `500` | internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id. |
| `503` | busy. A store we need did not answer, or is not configured on this server. Send the same request again after the Retry-After seconds. |


## DELETE `/v1/account/keys/{key_id}`

Revoke a key.

A member revokes their own keys; an owner revokes any. The key stops
working within 60 seconds. A key id that is not a UUID, not in this
account, or not yours as a member is the same 404.

### Parameters

| name | in | required | type or values | what it is |
| -- | -- | -- | -- | -- |
| `key_id` | path | yes | string |  |


### Answers

| status | what it means |
| -- | -- |
| `200` | The key as it was. |
| `401` | bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts. |
| `403` | wrong_scope (a scrape key on a route that needs an account key, or an account key on a scraping or batches route) or owner_only (your role is member). |
| `404` | not_found. No key with that id in this account. A member sees only their own keys. |
| `429` | rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again. |
| `500` | internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id. |
| `503` | busy. A store we need did not answer, or is not configured on this server. Send the same request again after the Retry-After seconds. |


## GET `/v1/account/members`

List the people in the account.

Any member may read it. email is filled only when the caller is an owner, and null otherwise.

### Parameters

| name | in | required | type or values | what it is |
| -- | -- | -- | -- | -- |
| `cursor` | query | no | string | The next_cursor of the previous page, unchanged. Absent means the first page. |
| `limit` | query | no | integer, 1 to 100; default `50` | Rows per page, 1 to 100. |


### Answers

| status | what it means |
| -- | -- |
| `200` | One page of members. |
| `400` | bad_parameter. error.field names the parameter; the message says which values work. An unknown query key is this 400 too. |
| `401` | bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts. |
| `403` | wrong_scope (a scrape key on a route that needs an account key, or an account key on a scraping or batches route) or owner_only (your role is member). |
| `429` | rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again. |
| `500` | internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id. |
| `503` | busy. A store we need did not answer, or is not configured on this server. Send the same request again after the Retry-After seconds. |


## POST `/v1/account/members`

Add a person to the account.

Owner only. Always makes a new, unverified person: the answer is the
same for every email, so it never tells you whether an address is
known elsewhere. We send no email.

### Body

| field | required | type or values | what it is |
| -- | -- | -- | -- |
| `email` | yes | string |  |
| `role` | no | `owner`, `member`; default `member` |  |


### Answers

| status | what it means |
| -- | -- |
| `201` | The new member. |
| `400` | bad_parameter: a field is missing, wrong, or not one this request takes; error.field names it. bad_request: the body is not one JSON object. |
| `401` | bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts. |
| `402` | over_plan. Your plan's member limit is reached. Remove a member first. |
| `403` | wrong_scope (a scrape key on a route that needs an account key, or an account key on a scraping or batches route) or owner_only (your role is member). |
| `409` | already_member. This email is already a member of this account. |
| `413` | body_too_large. The body was larger than 4 KiB. |
| `415` | unsupported_media_type. Send Content-Type: application/json, even for an empty {} body. |
| `429` | rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again. |
| `500` | internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id. |
| `503` | busy. A store we need did not answer, or is not configured on this server. Send the same request again after the Retry-After seconds. |


## DELETE `/v1/account/members/{person_id}`

Remove a person from the account.

An owner removes anyone; a member may remove themselves (leave). In
the same step every key the person made is revoked and their queued
job items are canceled. The answer
counts each.

### Parameters

| name | in | required | type or values | what it is |
| -- | -- | -- | -- | -- |
| `person_id` | path | yes | string | From GET /v1/account/members. A value that is not a UUID is 404 not_found. |


### Answers

| status | what it means |
| -- | -- |
| `200` | Removed. |
| `401` | bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts. |
| `403` | wrong_scope (a scrape key on a route that needs an account key, or an account key on a scraping or batches route) or owner_only (your role is member). |
| `404` | not_found. No member with that person_id in this account. |
| `409` | last_owner. This would leave the account with no owner. |
| `429` | rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again. |
| `500` | internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id. |
| `503` | busy. A store we need did not answer, or is not configured on this server. Send the same request again after the Retry-After seconds. |


## PATCH `/v1/account/members/{person_id}`

Change a member's role.

Owner only.

### Parameters

| name | in | required | type or values | what it is |
| -- | -- | -- | -- | -- |
| `person_id` | path | yes | string | From GET /v1/account/members. A value that is not a UUID is 404 not_found. |


### Body

| field | required | type or values | what it is |
| -- | -- | -- | -- |
| `role` | yes | `owner`, `member`; default `member` |  |


### Answers

| status | what it means |
| -- | -- |
| `200` | The member with the new role. |
| `400` | bad_parameter: a field is missing, wrong, or not one this request takes; error.field names it. bad_request: the body is not one JSON object. |
| `401` | bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts. |
| `403` | wrong_scope (a scrape key on a route that needs an account key, or an account key on a scraping or batches route) or owner_only (your role is member). |
| `404` | not_found. No member with that person_id in this account. |
| `409` | last_owner. This would leave the account with no owner. |
| `413` | body_too_large. The body was larger than 4 KiB. |
| `415` | unsupported_media_type. Send Content-Type: application/json, even for an empty {} body. |
| `429` | rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again. |
| `500` | internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id. |
| `503` | busy. A store we need did not answer, or is not configured on this server. Send the same request again after the Retry-After seconds. |


## GET `/v1/account/usage`

Requests and credits per UTC day or per hour.

Any member. Newest first, today (or this hour) included and partial. A day or hour with no
traffic is present with zeros. Send days or hours, not both. Every request up to now is
counted: closed hours come from the hourly rollup, newer hours are counted from the request
records, so the totals match the request list.

### Parameters

| name | in | required | type or values | what it is |
| -- | -- | -- | -- | -- |
| `days` | query | no | integer, 1 to 90; default `30` | How many days back, 1 to 90. |
| `hours` | query | no | integer, 1 to 24 | How many hours back, 1 to 24. Rows then carry hour instead of date. |
| `key_id` | query | no | string | Only the usage of this key. A member asking for a key they did not make gets zeros. |


### Answers

| status | what it means |
| -- | -- |
| `200` | The days. |
| `400` | bad_parameter. error.field names the parameter; the message says which values work. An unknown query key is this 400 too. |
| `401` | bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts. |
| `403` | wrong_scope (a scrape key on a route that needs an account key, or an account key on a scraping or batches route) or owner_only (your role is member). |
| `429` | rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again. |
| `500` | internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id. |
| `503` | busy. A store we need did not answer, or is not configured on this server. Send the same request again after the Retry-After seconds. |


## GET `/v1/account/requests`

Your request records, newest first.

An owner sees every request of the account; a member sees the
requests made with their own keys. Records keep the site's host
only: no URL, path or query, no headers and no IP address. The last
90 days; with key_id, source or host, the last 7 days.

### Parameters

| name | in | required | type or values | what it is |
| -- | -- | -- | -- | -- |
| `cursor` | query | no | string | The next_cursor of the previous page, unchanged. Absent means the first page. |
| `limit` | query | no | integer, 1 to 100; default `50` | Rows per page, 1 to 100. |
| `key_id` | query | no | string | Only the requests made with this key, in the last 7 days. |
| `source` | query | no | `api`, `mcp`, `job`, `monitor` | Only the requests from this source, in the last 7 days. api also matches proxy. |
| `host` | query | no | string | Only the requests to this host, like example.com, in the last 7 days. Any case. |


### Answers

| status | what it means |
| -- | -- |
| `200` | One page of records. |
| `400` | bad_parameter. error.field names the parameter; the message says which values work. An unknown query key is this 400 too. |
| `401` | bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts. |
| `403` | wrong_scope (a scrape key on a route that needs an account key, or an account key on a scraping or batches route) or owner_only (your role is member). |
| `429` | rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again. |
| `500` | internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id. |
| `503` | busy. A store we need did not answer, or is not configured on this server. Send the same request again after the Retry-After seconds. |


## GET `/v1/account/requests/{id}`

One request, with its climb and where its credits came from.

The record from the request list, plus the routes we tried (hops) and
the credits split into their three parts. An owner sees every request
of the account; a member sees the requests made with their own keys.
The last 90 days. Any other id is a 404, never a 403.

### Parameters

| name | in | required | type or values | what it is |
| -- | -- | -- | -- | -- |
| `id` | path | yes | string | The X-Request-Id of that request. |


### Answers

| status | what it means |
| -- | -- |
| `200` | The request. |
| `401` | bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts. |
| `403` | wrong_scope (a scrape key on a route that needs an account key, or an account key on a scraping or batches route) or owner_only (your role is member). |
| `404` | not_found. No request with that id in your account in the last 90 days. |
| `429` | rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again. |
| `500` | internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id. |
| `503` | busy. A store we need did not answer, or is not configured on this server. Send the same request again after the Retry-After seconds. |


## GET `/v1/account/purchases`

What the account paid for.

Owner only. Paid purchases, newest first.

### Parameters

| name | in | required | type or values | what it is |
| -- | -- | -- | -- | -- |
| `cursor` | query | no | string | The next_cursor of the previous page, unchanged. Absent means the first page. |
| `limit` | query | no | integer, 1 to 100; default `50` | Rows per page, 1 to 100. |


### Answers

| status | what it means |
| -- | -- |
| `200` | One page of purchases. |
| `400` | bad_parameter. error.field names the parameter; the message says which values work. An unknown query key is this 400 too. |
| `401` | bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts. |
| `403` | wrong_scope (a scrape key on a route that needs an account key, or an account key on a scraping or batches route) or owner_only (your role is member). |
| `429` | rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again. |
| `500` | internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id. |
| `503` | busy. A store we need did not answer, or is not configured on this server. Send the same request again after the Retry-After seconds. |


## POST `/v1/account/checkout`

Open a Stripe payment page that adds credits to this account.

Owner only. A pack tops up an active subscription, and only the packs
of your plan are on sale; without one the answer is 409 no_subscription.
The credits land on this account once
Stripe confirms the payment. It makes no keys. Open checkout_url in a
browser; the page expires after 30 minutes. ref_token and ref_code
are read on every checkout, but only the account's first paid
purchase binds a referral (MEG-504). A bad ref is dropped, never an
error. Stripe sends the buyer back to the dashboard: /buy?paid, or
/buy?cancelled.

### Parameters

| name | in | required | type or values | what it is |
| -- | -- | -- | -- | -- |
| `Idempotency-Key` | header | no | string | Your own id for this call, 1 to 128 printable ASCII characters. A second call with the same key from the same account key inside 24 hours answers 200 with the same checkout_url, and opens no new payment page. A call that failed frees its key. |


### Body

| field | required | type or values | what it is |
| -- | -- | -- | -- |
| `pack` | yes | string | The pack's public name, like starter. A name we do not sell is 404 not_found. |
| `campaign` | no | string | Where the buyer came from, like reddit-launch. Never a URL or an email. |
| `ref_token` | no | string | Added by MEG-237. The ref_token the /r/{code} link put on the page's address. Checked with our secret; a bad, forged or expired one (older than 60 days) is dropped without an error. Binds only on the account's first paid purchase. |
| `ref_code` | no | string | Added by MEG-237. A referral code typed by the buyer, 8 of a-z and 0-9. An unknown code is dropped without an error. ref_token wins when both are sent. |


### Answers

| status | what it means |
| -- | -- |
| `200` | The Stripe payment page. Open checkout_url in a browser. It expires after 30 minutes. |
| `400` | bad_parameter: pack is missing (field pack), campaign is wrong (field campaign), Idempotency-Key is not 1 to 128 printable ASCII characters (field Idempotency-Key), or a key this request does not take (field names it). bad_request: the body is not one JSON object. |
| `401` | bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts. |
| `403` | wrong_scope (a scrape key on a route that needs an account key, or an account key on a scraping or batches route) or owner_only (your role is member). |
| `404` | not_found. No pack with that name. |
| `413` | body_too_large. The body was larger than 4 KiB. |
| `415` | unsupported_media_type. Send Content-Type: application/json, even for an empty {} body. |
| `422` | idempotency_mismatch. This Idempotency-Key already opened a checkout for a different body. Send the same body, or a new key. |
| `429` | rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again. |
| `500` | internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id. |
| `503` | checkout_failed (Stripe did not open the payment page; nothing was charged, try again in a minute), checkout_closed (buying is off on this server) or busy (the account store is not configured, or a request with this Idempotency-Key is still opening its page; send it again in a few seconds). |


## POST `/v1/account/subscription`

Subscribe to a plan, or change it.

Owner only. With no subscription, opens a Stripe payment page for the
plan. With one, moves to the plan: a higher plan is charged in full now
and starts a new month with its full credits; a lower plan starts at
your next renewal. Two identical changes sent at once are charged once.
Credits come only with a paid invoice. Packs top up
a subscription (POST /v1/account/checkout).

### Body

| field | required | type or values | what it is |
| -- | -- | -- | -- |
| `plan` | yes | string |  |


### Answers

| status | what it means |
| -- | -- |
| `200` | New subscription: checkout_url, a Stripe payment page that expires after 30 minutes. Stripe sends you back to /plan?subscribed or /plan?cancelled. A plan change: change is upgrade (paid now, the month restarts, the new credits land when Stripe confirms) or downgrade (from your next renewal; no money moves now). |
| `400` | bad_parameter: plan is missing or not a plan (field plan). bad_request: the body is not one JSON object. |
| `401` | bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts. |
| `402` | payment_failed. The payment for the higher plan failed. Your plan did not change. |
| `403` | wrong_scope (a scrape key on a route that needs an account key, or an account key on a scraping or batches route) or owner_only (your role is member). |
| `409` | checkout_open (a payment page is still open), past_due (the last payment failed; update the card in the billing portal) or already_on_plan. |
| `413` | body_too_large. The body was larger than 4 KiB. |
| `415` | unsupported_media_type. Send Content-Type: application/json, even for an empty {} body. |
| `429` | rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again. |
| `500` | internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id. |
| `503` | checkout_failed (Stripe did not answer; nothing was charged, try again in a minute) or checkout_closed (buying is off on this server). |


## POST `/v1/account/billing-portal`

Open the Stripe billing portal.

Owner only. Your card, your invoices, and canceling.

### Answers

| status | what it means |
| -- | -- |
| `200` | portal_url, a Stripe page for your card, your invoices and canceling. A cancel takes effect at the end of the paid month; your credits stay until they expire. |
| `401` | bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts. |
| `403` | wrong_scope (a scrape key on a route that needs an account key, or an account key on a scraping or batches route) or owner_only (your role is member). |
| `404` | not_subscribed. This account has no subscription yet. |
| `429` | rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again. |
| `500` | internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id. |
| `503` | checkout_failed (Stripe did not answer) or checkout_closed (buying is off on this server). |
