# Ask for a link that verifies an email address (hosted auth UI)

`POST /v1/auth/verify-email/resend`

Emails a single-use link that verifies the address to the account
holding `email` in this organization, when there is one, its address is
not yet verified, and the organization has an email relay. The answer is
202 whether or not there is: the account is looked up, and the link
queued, after the response, so neither the status, the body nor the time
taken tells whether the address has an account here. The link works for
`auth.email_verification.validity`, and an account is sent at most
`auth.email_verification.max_requests` within that time; the requests
count toward the per-address sign-in throttle. With a captcha
configured, the request must carry a `captcha` solution; a refusal, 400
`captcha_failed`, is the same whatever the address.

## Authorization

None: this endpoint does not take API credentials.

This endpoint is rate limited; it answers `429` when a limit is hit.

## Headers

- `Origin` (string, optional): Browser Origin, checked (with Sec-Fetch-Site) as a same-origin/CSRF guard.
- `Sec-Fetch-Site` (string, optional): Fetch metadata; only same-origin is trusted (CSRF guard).
- `Content-Type` (string, optional): Must be application/json — a JSON body cannot be a CORS simple request, closing form-based CSRF.
- `Accept-Language` (string, optional): The browser's preferred languages (RFC 9110 §12.5.4); a message the operation queues, such as a new-sign-in alert, is written in the first one the server ships.

## Request body (`application/json`)

A request for a link that verifies the address of the account holding `email`. The remaining fields are the sign-in's preserved authorization request, as on SignInRequest: when they name a client registered in the organization, or the device page, the link carries them in its query so the verified user can continue to sign in for it.

- `email` (string (email), required): Constraints: at most 320 characters. Example: `"alice@example.com"`.
- `captcha` (string, optional): The captcha solution, required when the deployment asks for one. Constraints: at most 4096 characters.
- `client_id` (string, optional): Constraints: at most 256 characters.
- `ui_locales` (string, optional): Constraints: at most 256 characters.
- `redirect_uri` (string, optional): Constraints: at most 2048 characters.
- `response_type` (string, optional): Constraints: at most 32 characters.
- `scope` (string, optional): Constraints: at most 2048 characters.
- `state` (string, optional): Constraints: at most 1024 characters.
- `nonce` (string, optional): Constraints: at most 1024 characters.
- `code_challenge` (string, optional): Constraints: at most 128 characters.
- `code_challenge_method` (string, optional): Constraints: at most 16 characters.
- `login_hint` (string, optional): Constraints: at most 512 characters.
- `prompt` (string, optional): Constraints: at most 64 characters.
- `request_uri` (string, optional): Constraints: at most 512 characters.
- `resource` (string, optional): Constraints: at most 2048 characters.
- `authorization_details` (string, optional): Constraints: at most 8192 characters.
- `dpop_jkt` (string, optional): Constraints: exactly 43 characters; pattern `^[A-Za-z0-9_-]+$`.
- `max_age` (integer (int64), optional): Constraints: at least 0.
- `continue_path` (string, optional): Constraints: at most 128 characters.

No other properties are accepted.

## Responses

### 202 Accepted

The request was taken. A link is on its way if the address has an unverified account here.

Headers:
- `Cache-Control` = `no-store`

### 429 Too Many Requests

Too many requests.

Content type: `application/problem+json`

RFC 9457 (formerly RFC 7807) problem details (application/problem+json). `code` is a stable machine-readable slug for the problem kind (it mirrors the last path segment of `type`), so consumers can branch on it without parsing prose. `type` is `https://nauthera.io/problems/<code>`, which resolves to the code's runbook: why it happened, who is affected and what to do (RFC 9457 §3.1.1). A problem without a code has `about:blank`. `errors` is present on validation failures and lists every offending field.

- `title` (string, required): Example: `"Request validation failed"`.
- `status` (integer, required): Example: `400`.
- `type` (string (uri), optional): Example: `"https://nauthera.io/problems/validation_error"`.
- `detail` (string, optional): Example: `"One or more fields did not satisfy the API schema."`.
- `code` (enum, optional): The kind of problem, as a stable machine-readable slug a client branches on and translates rather than parsing `title` or `detail`, which are English prose for logs. A problem whose status says everything the server knows carries no `code`. One of: `"invalid_request"`, `"invalid_credentials"`, `"forbidden"`, `"unauthorized"`, `"insufficient_user_authentication"`, `"protected_account"`, `"password_held_by_directory"`, `"last_role_administrator"`, `"invalid_code"`, `"too_many_requests"`, `"too_many_attempts"`, `"account_locked"`, `"account_unavailable"`, `"already_enrolled"`, `"registration_disabled"`, `"registration_conflict"`, `"captcha_failed"`, `"invalid_reset_link"`, `"password_reused"`, `"password_too_short"`, `"password_too_long"`, `"password_compromised"`, `"invalid_verification_link"`, `"invalid_invitation_link"`, `"mail_relay_missing"`, `"email_unverified"`, `"not_found"`, `"conflict"`, `"unavailable"`, `"busy"`, `"window_too_large"`, `"too_many_series"`, `"internal_error"`, `"rate_limited"`, `"malformed"`, `"body_too_large"`, `"required"`, `"validation_error"`, `"unknown_org"`, `"invalid_token"`, `"invalid_dpop_proof"`, `"use_dpop_nonce"`, `"server_error"`.

  `validation_error` is the one code whose message is not a sentence about
  the code itself: the request failed the schema, and the specifics are
  the `errors` list — one entry per offending field — which a form renders
  on those fields. `required` and `malformed` are spelled like two of the
  per-field violation codes (`FieldError.code`) but mean something else;
  the two vocabularies are told apart by position, never by spelling.

  **Compatibility:** this is a CLOSED enum, with the same cost as
  `AuditAction`: a client generated against an older version of this
  document rejects a problem carrying a code added after it was built.
  Regenerate on upgrade, or decode the field as a plain string. It is
  enumerated anyway so that what a client must translate is knowable
  from the contract alone.
- `instance` (string, optional): Example: `"/introspect"`.
- `request_id` (string, optional): Example: `"8d94ed49-1caf-4ab3-9594-557142f2d023"`.
- `trace_id` (string, optional): Distributed-trace id (hex) for correlating this response with traces and logs. Present only when tracing is enabled and the request was recorded. Opaque and safe to log/share. Example: `"4bf92f3577b34da6a3ce929d0e0e4736"`.
- `errors` (array of objects, optional): Field-level violations (present for validation errors).

  Each item: A single field-level validation violation.
  - `field` (string, required): Offending field, dotted for nested bodies (e.g. child.id). Example: `"token_type_hint"`.
  - `code` (string, required): Machine-readable violation code: required, too_short, too_long, pattern, invalid_format, not_allowed, minimum, maximum, multiple_of, too_few, too_many, not_unique, malformed. Example: `"not_allowed"`.
  - `message` (string, required): Example: `"field token_type_hint must be one of [access_token, refresh_token]"`.

### Error

Problem details (RFC 9457).

Content type: `application/problem+json`

RFC 9457 (formerly RFC 7807) problem details (application/problem+json). `code` is a stable machine-readable slug for the problem kind (it mirrors the last path segment of `type`), so consumers can branch on it without parsing prose. `type` is `https://nauthera.io/problems/<code>`, which resolves to the code's runbook: why it happened, who is affected and what to do (RFC 9457 §3.1.1). A problem without a code has `about:blank`. `errors` is present on validation failures and lists every offending field.

- `title` (string, required): Example: `"Request validation failed"`.
- `status` (integer, required): Example: `400`.
- `type` (string (uri), optional): Example: `"https://nauthera.io/problems/validation_error"`.
- `detail` (string, optional): Example: `"One or more fields did not satisfy the API schema."`.
- `code` (enum, optional): The kind of problem, as a stable machine-readable slug a client branches on and translates rather than parsing `title` or `detail`, which are English prose for logs. A problem whose status says everything the server knows carries no `code`. One of: `"invalid_request"`, `"invalid_credentials"`, `"forbidden"`, `"unauthorized"`, `"insufficient_user_authentication"`, `"protected_account"`, `"password_held_by_directory"`, `"last_role_administrator"`, `"invalid_code"`, `"too_many_requests"`, `"too_many_attempts"`, `"account_locked"`, `"account_unavailable"`, `"already_enrolled"`, `"registration_disabled"`, `"registration_conflict"`, `"captcha_failed"`, `"invalid_reset_link"`, `"password_reused"`, `"password_too_short"`, `"password_too_long"`, `"password_compromised"`, `"invalid_verification_link"`, `"invalid_invitation_link"`, `"mail_relay_missing"`, `"email_unverified"`, `"not_found"`, `"conflict"`, `"unavailable"`, `"busy"`, `"window_too_large"`, `"too_many_series"`, `"internal_error"`, `"rate_limited"`, `"malformed"`, `"body_too_large"`, `"required"`, `"validation_error"`, `"unknown_org"`, `"invalid_token"`, `"invalid_dpop_proof"`, `"use_dpop_nonce"`, `"server_error"`.

  `validation_error` is the one code whose message is not a sentence about
  the code itself: the request failed the schema, and the specifics are
  the `errors` list — one entry per offending field — which a form renders
  on those fields. `required` and `malformed` are spelled like two of the
  per-field violation codes (`FieldError.code`) but mean something else;
  the two vocabularies are told apart by position, never by spelling.

  **Compatibility:** this is a CLOSED enum, with the same cost as
  `AuditAction`: a client generated against an older version of this
  document rejects a problem carrying a code added after it was built.
  Regenerate on upgrade, or decode the field as a plain string. It is
  enumerated anyway so that what a client must translate is knowable
  from the contract alone.
- `instance` (string, optional): Example: `"/introspect"`.
- `request_id` (string, optional): Example: `"8d94ed49-1caf-4ab3-9594-557142f2d023"`.
- `trace_id` (string, optional): Distributed-trace id (hex) for correlating this response with traces and logs. Present only when tracing is enabled and the request was recorded. Opaque and safe to log/share. Example: `"4bf92f3577b34da6a3ce929d0e0e4736"`.
- `errors` (array of objects, optional): Field-level violations (present for validation errors).

  Each item: A single field-level validation violation.
  - `field` (string, required): Offending field, dotted for nested bodies (e.g. child.id). Example: `"token_type_hint"`.
  - `code` (string, required): Machine-readable violation code: required, too_short, too_long, pattern, invalid_format, not_allowed, minimum, maximum, multiple_of, too_few, too_many, not_unique, malformed. Example: `"not_allowed"`.
  - `message` (string, required): Example: `"field token_type_hint must be one of [access_token, refresh_token]"`.

## Example request

```bash
curl -X POST 'https://auth.example.com/v1/auth/verify-email/resend' \
  -H "Content-Type: application/json" \
  -d '{
    "email": "alice@example.com"
  }'
```
