# Authentication

> Authenticate to the WAFlow Public API with an API key, and control access with scopes.

Source: https://edesy.in/docs/waflow/api/authentication

The WAFlow Public API is authenticated with an **API key**. Every request under `/api/v1` must include a valid key.

## Create an API key

1. Sign in to [waflow.edesy.in](https://waflow.edesy.in) and open the workspace you want to integrate.
2. Go to **Settings → API Keys**.
3. Click **Create API Key**, give it a name, and copy the key.

> **Note:** The full key is shown **only once** at creation — store it securely (e.g. a secrets manager). Keys are prefixed `wc_` and are scoped to a single workspace. You can revoke a key at any time from the same screen.

## Send the key

Provide the key on every request using **either** header:

```http
X-API-Key: wc_your_api_key
```

or

```http
Authorization: Bearer wc_your_api_key
```

**cURL Example:**
```bash
curl "https://waflow.edesy.in/api/v1/contacts" \
  -H "X-API-Key: wc_your_api_key"
```

**JavaScript Example:**
```javascript
const res = await fetch('https://waflow.edesy.in/api/v1/contacts', {
  headers: { 'X-API-Key': process.env.WAFLOW_API_KEY }
});
const data = await res.json();
```

---

## Scopes

Each API key carries a set of **scopes** that control which operations it may perform. A request to an endpoint the key isn't scoped for returns `403 INSUFFICIENT_SCOPE`.

| Scope | Grants |
|-------|--------|
| `messages.send` | Send individual messages (`POST /messages`) |
| `campaigns.create` | Create and start campaigns (`POST /send`) |
| `campaigns.read` | Read campaign status |
| `templates.read` | List, read, and sync templates |
| `templates.write` | Create/submit and delete templates |
| `contacts.read` | List and read contacts and lists |
| `contacts.write` | Create, update, and delete contacts and lists |

New keys are granted all scopes by default. You can narrow a key's scopes when creating it (e.g. a send‑only key with just `messages.send`).

---

## Rate limits

| Limit | Value |
|-------|-------|
| Per API key | 100 requests / 15 minutes (configurable per key) |
| Per IP (unauthenticated guard) | 600 requests / 15 minutes |

Every response includes standard rate‑limit headers:

```http
RateLimit-Limit: 100
RateLimit-Remaining: 97
RateLimit-Reset: 812
```

When the limit is exceeded you receive `429`:

```json
{
  "success": false,
  "error": "Too many requests",
  "code": "RATE_LIMIT_EXCEEDED",
  "message": "Rate limit exceeded for this API key."
}
```

---

## Error responses

**Missing API key (401):**
```json
{
  "success": false,
  "error": "API key is required",
  "code": "MISSING_API_KEY",
  "message": "Include your API key in the 'X-API-Key' header or 'Authorization: Bearer <key>' header"
}
```

**Invalid or revoked key (401):**
```json
{
  "success": false,
  "error": "Invalid API key",
  "code": "INVALID_API_KEY",
  "message": "The provided API key is not valid or has been revoked"
}
```

**Insufficient scope (403):**
```json
{
  "success": false,
  "error": "Insufficient API key permissions",
  "code": "INSUFFICIENT_SCOPE",
  "message": "This API key lacks the 'templates.write' permission.",
  "requiredScope": "templates.write"
}
```

## Security best practices

- Treat API keys like passwords — never commit them to source control or expose them in client‑side code.
- Use a separate key per integration so you can revoke one without affecting others.
- Prefer least‑privilege scopes (e.g. a `messages.send`‑only key for a notification service).
- Rotate keys periodically; revoke immediately if one may be compromised.
