# MailValid auth.md

> Self-contained agent authentication & registration guide. The H1 contains
> `auth.md` so validators (e.g. isitagentready.com) detect this as an Auth.md
> document. Audience: autonomous agents that need credentials to call the
> MailValid email-verification API.

MailValid issues **API keys** (not OAuth bearer access tokens). The flow is:
discover → register (anonymous) → claim (human binds the account) → use the
API key → revoke. An agent can register and start verifying immediately on a
small free allowance; a human claims the account to unlock the full free
allowance, the dashboard, and credit purchases.

## Step 1 — Discover

- Protected resource metadata: `https://mailvalid.io/.well-known/oauth-protected-resource`
- Authorization metadata: `https://mailvalid.io/.well-known/oauth-authorization-server`
- API catalog: `https://mailvalid.io/.well-known/api-catalog`
- API documentation: `https://mailvalid.io/docs`

The `agent_auth` block in the metadata above advertises
`identity_types_supported: ["anonymous"]`, the `register_uri`, and the
`claim_uri` used below.

## Step 2 — Pick a method

MailValid supports one Auth.md identity type: **anonymous**. The issued
credential type is `api_key`, transported in the `X-API-Key` header.

## Step 3 — Register (anonymous)

`POST https://mailvalid.io/api/auth/agent/register`

Request body:

```json
{"type": "anonymous", "label": "my-agent (optional)"}
```

Response (the `api_key` and `claim_token` are returned **once** — store them
securely; never expose them in page text, logs, URLs, or agent messages):

```json
{
  "registration_id": "reg_...",
  "registration_type": "anonymous",
  "api_key": "mv_live_...",
  "api_key_prefix": "mv_live_....",
  "credential_transport": {"header": "X-API-Key"},
  "scopes": ["email.verify:single", "email.verify:bulk", "credits:read", "webhooks:write"],
  "credits_granted": 25,
  "claim_url": "https://mailvalid.io/agent/claim?token=clm_...",
  "claim_token": "clm_...",
  "claim_token_expires_at": "<ISO 8601>"
}
```

Registration is rate-limited per IP. Use the API key right away (Step 5).

## Step 4 — Claim ceremony (hand off to the user)

Anonymous accounts must be claimed by a human to unlock the full free
allowance, dashboard access, and purchases. Present `claim_url` to the account
owner. They set a real email + password there; under the hood that page calls:

`POST https://mailvalid.io/api/auth/agent/claim`

```json
{"claim_token": "clm_...", "email": "owner@example.com", "password": "<8+ chars>"}
```

On success the response includes a JWT `access_token` for the dashboard and
the topped-up credit balance. The API key from Step 3 keeps working unchanged.

## Step 5 — Use the credential

Send the API key on every protected API request:

```http
X-API-Key: mv_live_...
```

Supported scopes: email.verify:single, email.verify:bulk, credits:read, webhooks:write. Start with
`POST https://mailvalid.io/api/v1/verify/single`.

## Errors

- `401` — missing or invalid `X-API-Key`. The `WWW-Authenticate` header points
  at the protected-resource metadata.
- `402` — insufficient credits. Claim the account (Step 4) or purchase credits.
- `429` — rate limited; honor the `Retry-After` header.

## Revocation

API keys are revoked by the authenticated account owner from the dashboard
(`https://mailvalid.io/dashboard/api-keys`) or `DELETE /api/auth/api-keys/{key_id}`.
MailValid does not currently provide an OAuth authorization-code flow, ID-JAG
identity assertions, or a provider-driven revocation (logout-token) callback.
