---
title: "Look up which sign-in path an email address needs"
method: POST
path: "/api/auth/email-status"
tags: ["account"]
---

# Look up which sign-in path an email address needs

`POST /api/auth/email-status`

## Request

- Base URL: `https://voltplan.app`
- URL: `https://voltplan.app/api/auth/email-status`
- Auth: none required

No authentication. Drives the second step of the stepped login.

- Rate limit, checked before the body is parsed: more than 15 requests within 60 s from one client IP answer 429. The IP is the first `x-forwarded-for` entry, else `x-real-ip`, else the shared bucket `unknown`. The limiter is in-memory per server instance, and rejected requests count toward the window.
- `email` is normalized with `String(email ?? '').trim().toLowerCase()`; a non-JSON body answers 400 `Invalid request`, an empty or malformed email (`^[^\s@]+@[^\s@]+\.[^\s@]+$`) 400 `Invalid email`.
- The `users` lookup and the external-auth listing run with the PocketBase superuser client (`getAdminPb`, `POCKETBASE_ADMIN_EMAIL` / `POCKETBASE_ADMIN_PASSWORD`).
- `new`: no account with this email. `oauth`: the account is linked to Google and/or Apple. `password`: any other account. Every backend failure (including the superuser login) also answers `password`, so this operation never returns 500.

## Request body

- AuthEmailStatusRequest
  - `email` string, required: Trimmed and lowercased server-side (`trim().toLowerCase()`); must then match `^[^\s@]+@[^\s@]+\.[^\s@]+$`.

## Response `200`

Sign-in path for the email address.

- union: `new`: no account with this email. `password`: password account, or the lookup failed. `oauth`: the account is linked to the listed social providers.
  - AuthEmailStatusBasicResponse: No account (`new`) or a password account / failed lookup (`password`).
    - `status` 'new' | 'password', required
  - AuthEmailStatusOAuthResponse: Account linked to at least one social provider; steer the user to the provider button.
    - `status` 'oauth', required
    - `providers` string[], required

## Other responses

- `400`: Body is not JSON, or the email is empty or malformed after normalization.
- `429`: More than 15 requests from this client IP within 60 seconds.

---

[API](https://skmtc.dev/voltplan/apis/voltplan-api.md) · [All operations](https://skmtc.dev/voltplan/apis/voltplan-api/llms.txt) · [OpenAPI document](https://skmtc.dev/voltplan/apis/voltplan-api/revisions/575b86a7af92?raw)
