# Sign up as an agent: a test key now, live on confirm

Signup

POST `/v1/agent_signup`

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).

**Auth:** none.

## Example

cURL:

```shell
curl -X POST 'https://staging.socialtap.dev/v1/agent_signup' \
  -H "content-type: application/json" \
  -d '{
  "email": "string"
}'
```

## Authorizations

No API key: anyone may call it.

## Body

JSON. Fields marked nullable may be `null`; optional ones may be left out.

| Field | Type | Description |
| --- | --- | --- |
| `email` | `string` | Your human's email address: they confirm there before the live key works. |
| `name?` | `string` | Your name as an agent, shown to the human and used as the keys' label: at most 40 ASCII letters, digits, spaces, hyphens, underscores or parentheses, starting with a letter or digit (anything else is invalid_input). Default: "Agent". |

## Response

### 201

Sign up as an agent: a test key now, live on confirm

| Field | Type | Description |
| --- | --- | --- |
| `data` | `object` |  |
| `data.account_id` | `string` | The new account (unverified until the human confirms). |
| `data.confirmation_expires_at` | `string` (date-time) | When the confirmation link stops working; then sign up again. |
| `data.email` | `string` | Where the confirmation link was sent. |
| `data.free_credits` | `integer` | Credits the account gets when the human confirms. |
| `data.live_key` | `object` | Pending until the human confirms by email; until then it can only read GET /v1/account (poll api_key.status). |
| `data.live_key.created_at` | `string` (date-time) | When the key was created, RFC 3339 UTC. |
| `data.live_key.expires_at` | `string` (date-time) or `null` | When the key stops working, RFC 3339 UTC; null when it never expires. |
| `data.live_key.id` | `string` | Key ID (key_…): manage the key with it. It is not the secret. |
| `data.live_key.ip_allowlist` | `string[]` | IP addresses or CIDR ranges (IPv4 or IPv6) the key works from; \[\] = any. |
| `data.live_key.last_used_at` | `string` (date-time) or `null` | About when the key was last used (updated at most hourly); null when never. |
| `data.live_key.mode` | `string` | live keys spend credits on real requests; test keys answer from recorded responses, free.<br>One of `live`, `test` |
| `data.live_key.name` | `string` | Your label for the key. |
| `data.live_key.object` | `string` | Always api_key.<br>One of `api_key` |
| `data.live_key.prefix` | `string` | The secret's first characters, to recognize it. |
| `data.live_key.revoked_at` | `string` (date-time) or `null` | When the key was revoked; null while it is not. |
| `data.live_key.scopes` | `string[]` | What the key may call: endpoints (data endpoints), jobs, account:read (account, usage, ledger, keys), admin (account settings and key management; includes account:read).<br>One of `endpoints`, `jobs`, `account:read`, `admin` |
| `data.live_key.secret` | `string` | The key itself: send it in the x-api-key header. Shown only once: store it now. |
| `data.live_key.spend_limit` | `object` or `null` | The key's spend limit and what it used this interval; null when the key has none. |
| `data.live_key.status` | `string` | pending: created by an agent signup and waiting for the owner's email confirmation (it can only read GET /v1/account). expired: past expires_at.<br>One of `active`, `pending`, `expired`, `revoked` |
| `data.object` | `string` | Always agent_signup.<br>One of `agent_signup` |
| `data.test_key` | `object` | Works now: every endpoint answers from recorded responses, free. Build and test with it. |
| `data.test_key.created_at` | `string` (date-time) | When the key was created, RFC 3339 UTC. |
| `data.test_key.expires_at` | `string` (date-time) or `null` | When the key stops working, RFC 3339 UTC; null when it never expires. |
| `data.test_key.id` | `string` | Key ID (key_…): manage the key with it. It is not the secret. |
| `data.test_key.ip_allowlist` | `string[]` | IP addresses or CIDR ranges (IPv4 or IPv6) the key works from; \[\] = any. |
| `data.test_key.last_used_at` | `string` (date-time) or `null` | About when the key was last used (updated at most hourly); null when never. |
| `data.test_key.mode` | `string` | live keys spend credits on real requests; test keys answer from recorded responses, free.<br>One of `live`, `test` |
| `data.test_key.name` | `string` | Your label for the key. |
| `data.test_key.object` | `string` | Always api_key.<br>One of `api_key` |
| `data.test_key.prefix` | `string` | The secret's first characters, to recognize it. |
| `data.test_key.revoked_at` | `string` (date-time) or `null` | When the key was revoked; null while it is not. |
| `data.test_key.scopes` | `string[]` | What the key may call: endpoints (data endpoints), jobs, account:read (account, usage, ledger, keys), admin (account settings and key management; includes account:read).<br>One of `endpoints`, `jobs`, `account:read`, `admin` |
| `data.test_key.secret` | `string` | The key itself: send it in the x-api-key header. Shown only once: store it now. |
| `data.test_key.spend_limit` | `object` or `null` | The key's spend limit and what it used this interval; null when the key has none. |
| `data.test_key.status` | `string` | pending: created by an agent signup and waiting for the owner's email confirmation (it can only read GET /v1/account). expired: past expires_at.<br>One of `active`, `pending`, `expired`, `revoked` |
| `meta` | `object` | The shared route meta (see the API reference introduction). |

### 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.

| Field | Type | Description |
| --- | --- | --- |
| `data` | `object` |  |
| `data.email` | `string` | Where the link was sent. |
| `data.expires_at` | `string` (date-time) | When the link stops working, RFC 3339 UTC. |
| `data.object` | `string` | Always signup.<br>One of `signup` |
| `meta` | `object` | The shared route meta (see the API reference introduction). |

### 400

400 Bad Request.

| Code | HTTP | Retry | Meaning | What to do |
| --- | --- | --- | --- | --- |
| `invalid_input` | 400 | No | The request parameters are missing or malformed, or the URL is not a supported link for this endpoint. | Fix the parameter named in param (the message says how); for a link of the wrong kind, call the endpoint the message names. |

### 429

429 Too Many Requests.

| Code | HTTP | Retry | Meaning | What to do |
| --- | --- | --- | --- | --- |
| `rate_limited` | 429 | Yes, later | The account exceeded its runaway-protection ceiling: plans do not limit request rate, but a high per-account safety ceiling stops broken client loops. Support raises it on request. Without an API key (signup, the MCP server's tool listing and find_endpoint), requests are limited per IP address instead. | Wait for the number of seconds in the retry-after header, then retry; ask [support](https://staging.socialtap.dev/docs/index.md) to raise the ceiling if your sustained traffic needs more (calls without an API key: use one). |

operationId `agent_signup.create`

---

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