
# Add an unverified secondary email address to a user

`POST /v1/users/{user_id}/emails` · permission `users:write`

Adds a secondary, unverified email address to the user. The address is normalized before it is stored. If the user already has the same address, no row is written and the existing row is returned (it may be verified or primary), so repeating the request is safe. A new row is written to the management audit log as `user.email_added` with the API key as actor; the address itself is not written to the audit record. To verify the address, send a verification email with `POST /v1/users/{user_id}/emails/{email_id}:send-verification` or mark it verified with `:verify`.

## Request

| Parameter | In | Required | Description |
|---|---|---|---|
| `user_id` | path | yes | User id, prefixed `usr_`. |

| Field | Type | Required | Description |
|---|---|---|---|
| `email` | string | yes | The address, at most 320 characters. |

## Response

`201 Created` with the email row. Without the `users:read_pii` permission the address is masked (`a***@e***.com`).

```json
{
  "id": "0191f0a0-3333-7444-8555-666666666666",
  "email": "ada@example.com",
  "verified": false,
  "primary": false,
  "created_at": "2026-01-15T09:30:00Z"
}
```

## Errors

Every error is an `application/problem+json` body with a stable `code`.

| HTTP | `code` | When |
|---|---|---|
| 400 | `malformed_request`, `unknown_field` | The body is not valid JSON or has an unknown field. |
| 409 | `conflict` | The address is verified on another user of this environment (`errors[]`: `/email`, `email_taken`). |
| 409 | `email_limit_reached` | The user already has 10 addresses. |
| 415 | `unsupported_media_type` | The body was sent without `Content-Type: application/json`. |
| 422 | `validation_failed` | `email` is missing, empty, longer than 320 characters, not a valid address, or has the wrong type. |
| 404 | `not_found` | The user does not exist in this environment, is being deleted, or the id is malformed. |
| 401 | `unauthenticated` | The API key is missing, invalid or revoked. |
| 403 | `insufficient_permissions` | The key lacks the `users:write` permission. |
| 429 | `rate_limited` | The rate limit was exceeded; honor `Retry-After`. |
| 503 | `service_unavailable` | A dependency is temporarily unavailable; retry later. |

## Example

```bash
curl -X POST https://api.eu.keenauth.com/v1/users/usr_0a1b2c3d4e5f6g7h8j9k0m1n2p/emails \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "ada@example.com"}'
```

## Personal data

This endpoint carries personal data: end-user profile. [Personal data in the KeenAuth APIs](/docs/policies/personal-data) describes what is stored, how long it is kept and how it is deleted. Do not send special categories of personal data (health, biometric data, religion, political opinions, sexual orientation) in any field.
