---
title: Browser email-code sign-in
description: Post an application's browser email-code sign-in forms, preserve their binding cookie, and handle HTML, redirects, and JSON refusals.
slug: /reference/browser-email-code-sign-in
order: 11
visibility: public
redirects_from: []
---

# Browser email-code sign-in

Use these endpoints to post an application user's address and emailed code from a custom page. Successful responses are HTML or redirects, with the browser keeping the cookies that bind and complete the sign-in.

This reference covers ordinary browser sign-in. [Add sign-in to your app](/cloud/guides/add-sign-in-to-your-app/) declares the accounts service and enables the `email` method. Native authorization and reauthentication have additional state; use their own flows rather than adding those fields to an ordinary sign-in.

## Origin and browser state

Send both requests to the same application's sign-in origin and environment, under `/__account/`. Use its custom domain when that is the active sign-in origin. A code and cookie from another application, environment, or hostname cannot complete this flow.

Both posts check `Origin`: if present, it must exactly equal the sign-in origin. Without `Origin`, the request needs `Sec-Fetch-Site: same-origin`. The browser supplies these headers for an ordinary form; a different origin is refused `invalid_request` with status 400.

An accepted start sets the opaque `__Host-turnzero_cloud_signin_code` binding cookie. It is host-only, `HttpOnly`, `Secure`, and `SameSite=Lax`, with `Path=/`. Keep cookies enabled and use the same browser for verification. Do not read or construct the cookie's value in your page.

## Start: request a code

Send `POST /__account/email/start` with `Content-Type: application/x-www-form-urlencoded`. Use the field names below; the address field is named `address`.

| Field | Required | Value |
| --- | --- | --- |
| `address` | Yes | The person's email address, as a string. |
| `return_to` | No | The application path to open after completion. It follows the [return-path rules](/cloud/guides/add-sign-in-to-your-app/#2-send-people-to-sign-in) and is at most 512 characters. |

An accepted request returns status 200 and `text/html`: the code-entry page. It also sets the binding cookie above. The mail send completes separately, so this response does not prove that mail has arrived and does not return the code.

To send a new code, post the start form again with the address and the browser's cookie. Use the code from that request. A resend is subject to the [emailed-code limits](/cloud/guides/manage-end-users/#the-limits-on-emailed-codes), so do not keep retrying a refused start.

## Verify: submit the code

Send `POST /__account/email/verify` as another form-encoded request. The browser must send the binding cookie from the accepted start.

| Field | Required | Value |
| --- | --- | --- |
| `code` | Yes | The six digits as a string, preserving any leading zero. |
| `address` | No | The address to redisplay on a code-entry or resend form after a refusal. It does not choose the identity being verified. |
| `return_to` | No | Repeat the accepted start's value for the retry form. The successful destination remains the one stored at the start. |

Verification uses the binding cookie, not an address supplied in this second request, to find the pending code. Keep the start and verification in the same browser; a code without its binding cannot be confirmed.

## Successful responses and redirects

| Response to verification | What it means |
| --- | --- |
| 302 with `Location` | The ordinary sign-in continues to its application return path. With no `return_to`, that path is `/`. Let the browser follow the redirect. |
| 200 with `text/html` | A platform screen continues the flow, such as an account-linking choice or the passkey offer. Present that screen and follow its controls. |

A code proving an address does not bypass account admission: invitation-only sign-up, suspended accounts, and the realm's other checks still apply. A 200 response alone therefore does not establish that a session opened.

When the ordinary flow opens a session, the browser receives the `__Host-turnzero_cloud_realm` session cookie. There is no JSON success object or token response to extract from these two form endpoints. Read the signed-in user as [Show the user and sign out](/cloud/guides/add-sign-in-to-your-app/#4-show-the-user-and-sign-out) describes.

Normal form navigation lets the browser render the returned pages and follow redirects. If your page uses `fetch`, inspect the status and `Content-Type`; do not call `response.json()` on every answer or parse HTML for a code or token.

## Refused requests

A wrong, expired, already used, or unbound code returns status 400 with an HTML code-entry page naming `signin_code_invalid`. It does not complete a new sign-in. Read the code again or use the page's resend control to start again when needed.

Some checks instead return `application/json` with `contract_version`, `error`, and `detail`: a disabled method can answer 400 `route_not_enabled`, an origin or return-path check 400 `invalid_request`, and the source's start limit 429 `signin_rate_limited`. Address validation, mail limits, and account admission can answer HTML refusal pages. Inspect the response type before choosing how to display it.

The [sign-in guide's refusals](/cloud/guides/add-sign-in-to-your-app/#refusals) and [emailed-code limits](/cloud/guides/manage-end-users/#the-limits-on-emailed-codes) give the causes and remedies, including `signin_code_rate_limited` and `email_domain_undeliverable`. Use the returned page's controls or named remedy; repeated posts do not bypass a limit.

## Related

- [Add sign-in to your app](/cloud/guides/add-sign-in-to-your-app/) configures sign-in and verifies a user's session in the backend.
- [Make sign-up invitation-only](/cloud/guides/make-sign-up-invitation-only/) controls who may create an account.
- [Manage end users](/cloud/guides/manage-end-users/) describes the realm's settings, passkeys, and code limits.
- [Sign in from a native app](/cloud/guides/sign-in-from-a-native-app/) uses the native authorization flow.
- [Test sign-in with test end users](/cloud/guides/test-sign-in-with-test-end-users/) exercises sign-in without a person receiving mail.
