# CheckDisposable Email — API Documentation

> One endpoint. Bearer auth. JSON in, JSON out.

## Base URL

```
https://api.checkdisposable.email
```

## Authentication

Pass your API key as a Bearer token. Get one for free at https://app.checkdisposable.email/signup.

```
Authorization: Bearer cde_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

## Check a single email

`GET /v1/check?email=<email>`

### Example

```bash
curl 'https://api.checkdisposable.email/v1/check?email=test@mailinator.com' \
  -H 'Authorization: Bearer cde_live_...'
```

### Response (200)

```json
{
  "email": "test@mailinator.com",
  "domain": "mailinator.com",
  "is_disposable": true,
  "blocked": true,
  "reason": "Domain is a known disposable / temporary email provider.",
  "duration_ms": 47
}
```

### Clean email response

```json
{
  "email": "founder@stripe.com",
  "domain": "stripe.com",
  "is_disposable": false,
  "blocked": false,
  "reason": "Domain is not flagged as disposable.",
  "duration_ms": 19
}
```

## Rate limits

| Plan | Monthly cap | Burst |
|------|-------------|-------|
| free | 500 / month | 5 requests/second |
| unlimited | ∞ | 15 requests/second |
| lifetime | ∞ | 15 requests/second |

Every 200 response includes:

```
X-RateLimit-Plan: free | unlimited | lifetime
X-RateLimit-Limit: 500 | unlimited
X-RateLimit-Remaining: <int> | unlimited
X-RateLimit-Burst-Limit: 5 | 15
X-RateLimit-Burst-Remaining: <int>
```

When a burst limit is hit, you get `429 rate_limit_exceeded` plus a `Retry-After` header. When the monthly cap is hit, you get `429 plan_limit`.

## Error codes

| Status | Error | Meaning |
|--------|-------|---------|
| 400 | bad_request | Missing/malformed `email` parameter |
| 401 | invalid_api_key | API key is wrong or revoked |
| 429 | rate_limit_exceeded | Burst limit (req/sec) hit |
| 429 | plan_limit | Monthly cap exhausted |
| 502 | upstream_error | Provider unreachable — fail open |

## Code recipes

### Node.js / Next.js

```ts
const res = await fetch(
  'https://api.checkdisposable.email/v1/check?email=' + encodeURIComponent(email),
  { headers: { Authorization: 'Bearer ' + process.env.CDE_KEY } }
);
const { is_disposable } = await res.json();
if (is_disposable) throw new Error('Disposable signup rejected');
```

### Python

```python
import os, httpx

def is_disposable(email: str) -> bool:
    r = httpx.get(
        "https://api.checkdisposable.email/v1/check",
        params={"email": email},
        headers={"Authorization": f"Bearer {os.environ['CDE_KEY']}"},
        timeout=5.0,
    )
    r.raise_for_status()
    return r.json()["is_disposable"]
```

## Performance

- p50 latency: 47 ms
- Uptime: 99.95%
- Domains tracked: 120k+
- New domains added per day: ~~140
