API reference
Email sign-in API
Sign in with an emailed 6-digit code or magic link.
- Send a sign-in code:
POST /v1/auth/email/start - Verify a code:
POST /v1/auth/email/verify - Complete a magic link:
GET /v1/auth/email/callback
Send a sign-in code
POST /v1/auth/email/start
- Authentication: none on this route.
- Who: No authentication.
Request body (application/json, EmailStartRequest)
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | |
return_to | string | null | No | Same-origin UI path to open after sign-in; invalid values become /. |
Responses
| Status | Description | Body |
|---|---|---|
202 | Sent if the address can receive email; the answer never depends on whether an account exists | EmailStarted |
404 | unsupported_provider: email sign-in is not configured | ProblemDetails |
422 | Invalid request (invalid_request); field_errors names the fields. | ProblemDetails |
429 | rate_limited per address or client IP, with Retry-After | ProblemDetails |
503 | email_unavailable | ProblemDetails |
curl -X POST "$VMYARD_API_URL/v1/auth/email/start" \
-H "Content-Type: application/json" \
-d '{
"email": "ada@example.com",
"return_to": "/"
}'{
"message": "If the address can receive email, a code is on its way."
}Verify a code
POST /v1/auth/email/verify
Signs in with an emailed code, creating the user on the first verified
sign-in. A code requested through POST /v1/auth/link/email instead
links the address to the signed-in user and needs that session's cookie
and CSRF token.
- Authentication: none on this route.
- Who: No authentication.
Request body (application/json, EmailVerifyRequest)
| Field | Type | Required | Description |
|---|---|---|---|
code | string | Yes | The 6-digit code from the email. |
email | string | Yes |
Responses
| Status | Description | Body |
|---|---|---|
200 | Signed in (session and CSRF cookies set) or address linked | EmailVerified |
400 | invalid_code: wrong, expired, used, or superseded | ProblemDetails |
401 | A linking code without a session | ProblemDetails |
403 | A linking code with another user's session, a missing CSRF token, or an API key | ProblemDetails |
404 | unsupported_provider | ProblemDetails |
409 | identity_in_use: the address is another user's sign-in method | ProblemDetails |
429 | Too many requests; wait for Retry-After. | ProblemDetails |
curl -X POST "$VMYARD_API_URL/v1/auth/email/verify" \
-H "Content-Type: application/json" \
-d '{
"email": "ada@example.com",
"code": "123456"
}'{
"return_to": "string"
}Complete a magic link
GET /v1/auth/email/callback
Completes a magic link. It works once, within ten minutes, and only in
the browser that requested it (vmyard_email_state); on another device
type the code instead. A linking link also needs the requesting user's session.
- Authentication: none on this route.
- Who: No authentication.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
token | query | string | No | The magic-link token from the email. |
Responses
| Status | Description | Body |
|---|---|---|
303 | Success: redirect to the stored return_to on the UI origin. Failure: redirect to <ui>/sign-in?error=session_expired|identity_in_use|unsupported_provider | — |
curl "$VMYARD_API_URL/v1/auth/email/callback"