# Quickstart: your first check in 2 minutes

Veqen tells you whether a signup is real. You send an email address, an IP address, a phone number or a domain. You get back a **verdict** (`admit`, `review` or `refuse`), a **score** from 0 to 100, and the **reasons** in plain English.

## 1. Get an API key

1. [Create a free account](https://veqen-app.com/signup) and confirm your email. That unlocks 1,000 free credits every month.
2. Open [API keys](https://veqen-app.com/app/keys) and click **Create key**.
3. Copy the key. It starts with `vq_live_` and is shown **only once**.

Store it as an environment variable so it never ends up in your code:

```bash
export VEQEN_API_KEY="vq_live_..."
```

## 2. Check an email address

```bash [curl]
curl https://veqen-app.com/v1/email/check \
  -H "Authorization: Bearer $VEQEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "jane@mailinator.com"}'
```

```python [Python]
import os, requests

response = requests.post(
    "https://veqen-app.com/v1/email/check",
    headers={"Authorization": f"Bearer {os.environ['VEQEN_API_KEY']}"},
    json={"email": "jane@mailinator.com"},
    timeout=10,
)
result = response.json()
print(result["risk"]["verdict"])  # "refuse"
```

```javascript [JavaScript]
const response = await fetch("https://veqen-app.com/v1/email/check", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.VEQEN_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ email: "jane@mailinator.com" }),
});
const result = await response.json();
console.log(result.risk.verdict); // "refuse"
```

## 3. Read the answer

The part you act on is always `risk`:

```json
{
  "email": "jane@mailinator.com",
  "disposable": true,
  "did_you_mean": null,
  "risk": {
    "score": 90,
    "level": "high",
    "verdict": "refuse",
    "reasons": [
      {
        "code": "disposable_domain",
        "impact": 90,
        "message": "mailinator.com hands out throwaway inboxes."
      }
    ]
  }
}
```

| Field | What it means |
|---|---|
| `risk.verdict` | What we suggest you do: `admit`, `review` or `refuse`. |
| `risk.score` | 0 means nothing wrong, 100 means certainly fake or unusable. |
| `risk.reasons` | Every problem we found, strongest first. Each has a stable `code` and a human `message`. |

## 4. Act on the verdict

| Verdict | Score | What to do |
|---|---|---|
| `admit` | under 30 | Let them in. |
| `review` | 30 to 69 | Let them in with friction: confirm the email, verify the phone, or hold free credits until they do. |
| `refuse` | 70 and up | Block, and ask for a different email or phone with a friendly message. |

> **Tip:** show people the `message`, not the `code`. "Please use a permanent email address" works better than "Invalid email".

## What next?

- Checking a whole signup at once? Use the [signup check](/docs/signup-check). It combines email, IP and phone and catches mismatches between them.
- Building an AI agent? Connect the [MCP server](/docs/mcp).
- Want to know what every reason means? See [risk scores and reasons](/docs/reasons).
