# Verify Email

> Check whether one email address is deliverable.

Requires an API key with the `write` scope.

The call waits for the verification provider and can take up to about 30 seconds, so set a generous client timeout. It needs a paid plan and at least one credit. A credit is charged only when the verdict is `good` or `bad`; `unknown` and `error` are free. This response is not wrapped in `data`.

## Body Parameters

<ParamField body="email" type="string" required>
  The address to verify.
</ParamField>

<ParamField body="leadId" type="string">
  A lead in this workspace. When it exists, its `verificationStatus`, `verificationResult` and `verifiedAt` are updated with the verdict. An id that is not in this workspace is ignored.
</ParamField>

## Response

<ResponseField name="email" type="string">The address that was checked.</ResponseField>

<ResponseField name="quality" type="string">`good`, `bad`, `unknown` or `error`. Only `good` and `bad` use a credit.</ResponseField>

<ResponseField name="result" type="string">The reason: `accepted`, `probable`, `rejected`, `not_found` or `error`.</ResponseField>

<ResponseField name="didYouMean" type="string">A suggested correction for a typo, or `null`.</ResponseField>

<ResponseField name="free" type="boolean">`true` for a free-provider address such as Gmail.</ResponseField>

<ResponseField name="role" type="boolean">`true` for a role address such as info@ or support@.</ResponseField>

<RequestExample>
```bash cURL
curl -X POST "https://api.foxreach.io/api/v1/verification/verify" \
  -H "X-API-Key: otr_your_key" \
  -H "Content-Type: application/json" \
  -d '{"email": "john@acme.com"}'
```

```python Python SDK (beta)
from foxreach import FoxReach

client = FoxReach(api_key="otr_your_key")
result = client.verification.verify("john@acme.com")
```

```typescript TypeScript SDK (beta)
import { FoxReach } from "foxreach";

const client = new FoxReach({ apiKey: "otr_your_key" });
const result = await client.verification.verify("john@acme.com");
```
</RequestExample>

<ResponseExample>
```json
{
  "email": "john@acme.com",
  "quality": "good",
  "result": "accepted",
  "didYouMean": null,
  "free": false,
  "role": false
}
```
</ResponseExample>

## Errors

| Status | Description |
|--------|-------------|
| `401` | Missing, invalid, revoked or expired API key |
| `403` | API key does not have the required scope: `write` |
| `402` | `insufficient_verification_credits`: `{"detail": {"code": "insufficient_verification_credits", "message": "...", "balance": 0, "required": 1}}` |
| `403` | `upgrade_required` on the Free plan: `{"detail": {"code": "upgrade_required", "limit_type": "email_verification", "message": "..."}}`. A missing scope also returns 403 with a plain `detail` string |
| `422` | `email` is missing or not a valid address |
| `502` | `Email verification service unavailable. No credits were charged.` |

## Rate Limit

- **100 requests per minute, per API key.** Fixed 60-second window.
- Every response includes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` (unix epoch seconds).
- A `429` response includes a `Retry-After` header (seconds until the bucket resets).

For client-side patterns (`Retry-After`, exponential backoff, monitoring `X-RateLimit-Remaining`), see [Rate Limiting](/rate-limiting).
