# API keys

> Create, scope, rotate and revoke EmailVerify Pro API keys. Every key belongs to one account, with per-tier rate limits.

Source: https://emailverifypro.com/docs/api-keys

Every key belongs to exactly one account, identified by `owner_email`. That ownership is
what lets you list, inspect, rotate and revoke it — and what stops anyone else doing the
same to your keys.

## Create a key

```bash
curl -X POST https://emailverifypro.com/keys \
  -H "Content-Type: application/json" \
  -d '{"name":"my-laptop","tier":"free","owner_email":"you@company.com"}'
```

```json
{
  "key_id": "kid_a1b2c3d4e5f60718",
  "api_key": "evp_xxxxxxxxxxxxxxxxxxxxxxxx",
  "tier": "free",
  "monthly_limit": 100,
  "rate_per_min": 10,
  "owner_email": "you@company.com",
  "warning": "Save this key now — it cannot be retrieved again."
}
```

| Field | Required | Notes |
|---|---|---|
| `name` | yes | A label you'll recognise later — `ci`, `laptop`, `production` |
| `owner_email` | yes | Scopes the key to you. Must be a valid address |
| `tier` | no | `free`, `starter`, `pro`, `enterprise`. Defaults to `free` |

> **Warning.** `api_key` is returned once and never again. No endpoint will show it to
> you later — only metadata. If you lose it, rotate the key.

> A new key takes up to 2 minutes to replicate to every verification worker. Until then
> it can return `401 Invalid or revoked API key`. Wait and retry.

Anonymous creation is capped at **5 keys per IP per hour**. Authenticated callers are not
capped, and their new keys are always bound to their own account regardless of what
`owner_email` says.

## Use a key

```bash
curl -H "X-API-Key: evp_your_key" https://emailverifypro.com/me/usage
```

```bash
curl "https://emailverifypro.com/me/usage?api_key=evp_your_key"
```

> **Warning.** A key in a query string ends up in browser history, proxy logs and server
> access logs. Use the header wherever you can.

With the CLI, store it once:

```bash
emailverify login
```

## List your keys

Authenticate with any active key you own. The response is scoped to that key's
`owner_email` and never contains secrets.

```bash
curl -H "X-API-Key: evp_your_key" https://emailverifypro.com/keys
```

```json
{
  "owner_email": "you@company.com",
  "keys": [
    {
      "key_id": "kid_a1b2c3d4e5f60718",
      "name": "my-laptop",
      "tier": "free",
      "is_active": 1,
      "monthly_limit": 100,
      "rate_per_min": 10,
      "verifications_this_month": 12,
      "verifications_total": 480,
      "created_at": 1785680898.94,
      "last_used": 1785690000.11
    }
  ]
}
```

## Inspect one key

```bash
curl -H "X-API-Key: evp_your_key" \
  https://emailverifypro.com/keys/kid_a1b2c3d4e5f60718/usage
```

Another account's `key_id` returns `404`, not `403` — the API will not confirm that an id
it doesn't own even exists.

## Rotate a key

Issues a fresh secret with the same name and tier, and revokes the old one.

```bash
curl -X POST -H "X-API-Key: evp_your_key" \
  https://emailverifypro.com/keys/kid_a1b2c3d4e5f60718/rotate
```

```json
{
  "key_id": "kid_9f8e7d6c5b4a3021",
  "api_key": "evp_yyyyyyyyyyyyyyyyyyyyyyyy",
  "rotated_from": "kid_a1b2c3d4e5f60718",
  "revoked": "kid_a1b2c3d4e5f60718"
}
```

> **Warning.** The old key stops working immediately. Deploy the new one first, or accept
> a gap. Rotate whenever a key may have been exposed — in a commit, a log, a screenshot
> or a support ticket.

## Revoke a key

```bash
curl -X DELETE -H "X-API-Key: evp_your_key" \
  https://emailverifypro.com/keys/kid_a1b2c3d4e5f60718
```

Irreversible. You cannot revoke a key you do not own.

## Who can do what

| Endpoint | Auth | Scope |
|---|---|---|
| `POST /keys` | optional | Anonymous self-serve, 5 per IP per hour. Authenticated callers get a key bound to their own account |
| `GET /keys` | **required** | Only your keys |
| `GET /keys/{key_id}/usage` | **required** | Yours only; another account's id returns 404 |
| `POST /keys/{key_id}/rotate` | **required** | Yours only |
| `DELETE /keys/{key_id}` | **required** | Yours only |

## Tiers and limits

| Tier | Verifications / month | Requests / minute |
|---|---|---|
| `free` | 100 | 10 |
| `starter` | 1,000 | 30 |
| `pro` | 10,000 | 100 |
| `enterprise` | unlimited | 500 |

Check what's left:

```bash
curl -H "X-API-Key: evp_your_key" https://emailverifypro.com/me/usage
```

Exceeding a limit returns `429`. The SDKs back off and retry automatically.

## Keeping keys safe

- Put keys in environment variables or a secret manager, never in source control.
- Use a **separate key per environment** — laptop, CI, staging, production — so you can
  revoke one without disrupting the others.
- The CLI stores its key at `~/.config/emailverify/config.json` with mode `600`.
- Rotate on any suspicion of exposure. Rotation is instant and free.
- Prefer the `X-API-Key` header over the `api_key` query parameter.

## With the CLI

```bash
emailverify login                                        # store a key
emailverify keys                                         # list yours
emailverify create-key --name ci --owner-email you@co.com
emailverify raw POST /keys/kid_abc123/rotate             # rotate
emailverify raw DELETE /keys/kid_abc123                  # revoke
emailverify config                                       # which key is in use
emailverify logout                                       # forget it
```
