# Account, API keys and signup

Agents and accounts

Sign up, manage API keys (scopes, spend limits, expiry, IP allowlists, live and test modes), read usage and the credit ledger, and get balance alerts.

Everything about your account is an API route, free, and also available in the [dashboard](https://staging-fly.socialtap.dev/dashboard/).

## Sign up

**People:** create your account on the [signup page](https://staging-fly.socialtap.dev/signup/) with Google, GitHub, or an email address and a password (we email you a link to verify the address first). Your first sign-in gives you **100 free credits** (once per account, no card) and two keys, a live key and a test key, shown once.

**AI agents:** an agent without a key signs up with its human's email address:

Shell:

```shell
curl -X POST https://staging-fly.socialtap.dev/v1/agent_signup \
  -H 'content-type: application/json' \
  -d '{"email": "you@example.com", "name": "my-agent"}'
```

The answer has two keys. The **test key** works at once: every endpoint answers from recorded responses, free (see [test mode](https://staging-fly.socialtap.dev/docs/test-mode/index.md)). The **live key** is *pending*: it spends nothing and can only call `GET /v1/account` until the human opens the confirmation email and confirms, which activates it and grants the free credits. Agents never get spending power without a human. Poll `GET /v1/account` with the live key: `api_key.status` turns from `pending` to `active`. An address that already has an account gets no keys and is not refused: the answer is HTTP `202`: The address already has an account: no keys were made; its owner was emailed a sign-in link to create a key for you in the dashboard. Ask them to check their email.

Signup is throttled per IP address and per email address, and disposable email domains are refused.

## Routes

| Route | What it does | Auth |
| --- | --- | --- |
| `GET /v1/account`<br>Get the account, balance and calling key | The account's balance and plan, the low-balance alert threshold, and the calling key: its mode, scopes, spend limit (with what it used this interval) and expiry. Free; never cached. A pending agent key may call it (and nothing else) to learn when its owner confirmed. | key with account:read, or the session |
| `PATCH /v1/account`<br>Update account settings | Sets low_balance_threshold: credits.low (an event and an email to the owner) fires once each time a request takes the balance from above it to at or below it; credits.depleted fires when the balance reaches 0. Free. | key with admin, or the session |
| `POST /v1/agent_signup`<br>Sign up as an agent: a test key now, live on confirm | For AI agents: send your human's email address and get a test key that works at once (recorded responses, free) and a live key that stays pending until the human confirms by email, which grants the free credits. Agents never get spending power without a human. For an address that already has an account, no keys are made: the owner is emailed a sign-in link to create one in the dashboard, and the answer is 202 with the human signup's object (check your email). | none |
| `POST /v1/api_keys`<br>Create an API key | Creates a key with the given scopes, spend limit, expiry and IP allowlist. The secret is in this answer only: store it now. A key never gets a scope its creator lacks. Free. | key with admin, or the session |
| `GET /v1/api_keys/{id}`<br>Get an API key | One key and its spend this interval; never its secret. Free. | key with account:read, or the session |
| `GET /v1/api_keys`<br>List API keys | The account's keys, newest first, revoked ones included; never their secrets. Free. | key with account:read, or the session |
| `DELETE /v1/api_keys/{id}`<br>Revoke an API key | Revokes a key for good (a key may revoke itself). It stops working within a minute everywhere; revoking it again changes nothing. Free. | key with admin, or the session |
| `PATCH /v1/api_keys/{id}`<br>Update an API key | Changes a key's name, scopes, spend limit, expiry or IP allowlist; absent fields keep their value. Takes effect within a minute everywhere. Free. | key with admin, or the session |
| `GET /v1/credit_transactions`<br>List credit transactions (the ledger) | Every change to the balance, newest first, cursor-paged: grants (free credits), purchases, hourly usage roll-ups and adjustments. Per-request detail is in GET /v1/usage. Free. | key with account:read, or the session |
| `POST /v1/docs_feedback`<br>Send feedback on a docs page | Records whether a docs page helped, with an optional comment: what every docs page's "Was this page helpful?" sends. Agents are welcome to report a page that was wrong, unclear or missing something (set \`agent\`). Free; limited per IP address. | none |
| `GET /v1/security_events`<br>List sign-in and security events | The signed-in person's sign-ins, failed sign-ins, password, email, two-factor and session changes, newest first, with the network and browser each came from. Kept \`security_events_retention_s\`. Free. | dashboard session |
| `POST /v1/session`<br>Start the dashboard: set up the account | The dashboard calls it once it is signed in (people sign in with Google, GitHub or an email address and password on the sign-in page). The first call of a new account returns its live and test keys (secrets shown only here); with agent_token, it approves that agent signup, activating the agent's pending live key and granting the free credits. An account an agent opened that its owner signs in to without approving the agent gets fresh keys, and the agent's are revoked. Free. | dashboard session |
| `DELETE /v1/session`<br>Sign out | Ends the session and clears its cookie. | dashboard session |
| `GET /v1/session`<br>Get the dashboard session | The signed-in person and account of the session cookie. | dashboard session |
| `GET /v1/usage`<br>Usage report: requests and credits over time | Requests, successes, failures, cache hits and credits charged per time bucket, optionally grouped by endpoint, key and outcome. Buckets are listed oldest first, cursor-paged. Data is complete to within about 5 minutes; credits reconcile with the ledger. Free. | key with account:read, or the session |

## API keys

Send the key in the `x-api-key` header. A key has:

- a **mode**: live keys start with `st_live_` and make real, billed requests; test keys start with `st_test_` and answer from recorded responses, free. The mode is stored with the key; the prefix is only a hint for people.
- **scopes**, what it may call. A new key gets every scope but `admin` unless you choose, and a key never gets a scope its creator lacks. Without the scope a route needs, the answer is [`forbidden`](https://staging-fly.socialtap.dev/docs/errors/index.md#forbidden) with `details.required_scope`.
- an optional **spend limit**: at most that many credits per UTC day or month. Past it, requests fail with [`spend_limit_reached`](https://staging-fly.socialtap.dev/docs/errors/index.md#spend_limit_reached) (HTTP 402, never retried automatically) until `details.resets_at`, even when the account still has credits. Concurrent requests can never take a key past its limit.
- an optional **expiry** and **IP allowlist** (addresses or CIDR ranges, IPv4 or IPv6). An expired key, or a call from another address, is refused with [`forbidden`](https://staging-fly.socialtap.dev/docs/errors/index.md#forbidden) (`details.reason` says which).

The secret is shown once, when the key is created; the API only ever shows its prefix afterwards. Changes and revocations reach every server within a minute.

| Scope | Routes that need it |
| --- | --- |
| `endpoints` | the routes of its own feature (see above) |
| `jobs` | `POST /v1/jobs/{id}/cancel`, `POST /v1/jobs`, `GET /v1/jobs/{id}`, `GET /v1/jobs`, `GET /v1/jobs/{id}/results` |
| `account:read` | `GET /v1/account`, `GET /v1/api_keys/{id}`, `GET /v1/api_keys`, `GET /v1/credit_transactions`, `GET /v1/events/{id}`, `GET /v1/events`, `GET /v1/security_events`, `POST /v1/session`, `DELETE /v1/session`, `GET /v1/session`, `GET /v1/usage`, `GET /v1/webhook_endpoints/{id}/deliveries`, `GET /v1/webhook_endpoints/{id}`, `GET /v1/webhook_endpoints` |
| `admin` | `PATCH /v1/account`, `POST /v1/api_keys`, `DELETE /v1/api_keys/{id}`, `PATCH /v1/api_keys/{id}`, `POST /v1/events/{id}/redeliver`, `POST /v1/webhook_endpoints`, `DELETE /v1/webhook_endpoints/{id}`, `POST /v1/webhook_endpoints/{id}/rotate_secret`, `POST /v1/webhook_endpoints/{id}/test`, `PATCH /v1/webhook_endpoints/{id}` |

## Usage and the ledger

`GET /v1/usage` reports requests, successes, failures, cache hits and credits per hour or day, grouped by endpoint, key or outcome. `GET /v1/credit_transactions` lists every change to the balance: free credits, purchases, hourly usage and adjustments, with the balance after each.

## Balance alerts

Set `low_balance_threshold` with `PATCH /v1/account`. When a request takes the balance from above it to at or below it, the account gets a `credits.low` event and an email to its owner, once per crossing. `credits.depleted` fires when the balance reaches 0, and `api_key.spend_limit_reached` the first time in an interval that a key is refused for its spend limit.

## The dashboard session

Signing in starts a dashboard session: a signed cookie with the `__Host-` prefix on this origin (`Secure`, `HttpOnly`, `SameSite=Lax`), checked against the server on every request, so signing out, a password reset or "sign out everywhere else" ends it at once. The session can read and manage the account and keys, never call data endpoints. Every change it makes must come from this origin (the API checks the request's `Origin`), so another site can neither read nor drive it. Creating or changing API keys needs a recent sign-in: after a while the dashboard asks for your password or a two-factor code again.

Turn on two-factor authentication (an authenticator app, with one-time backup codes) in the security settings: every sign-in then asks for a code, with a password, Google or GitHub alike. The same page lists your sessions and a log of your sign-ins and security changes.

---

[HTML version](https://staging-fly.socialtap.dev/docs/account/) · [Docs index for AI agents](https://staging-fly.socialtap.dev/llms.txt) · [All docs in one file](https://staging-fly.socialtap.dev/llms-full.txt)
