Skip to main content
Magic codes are the simplest sign-in flow Pylon ships. The user types an email, gets a 6-digit code, and types it back to sign in. There are no passwords to remember and no OAuth credentials to obtain. Most apps should start here.

How it works

If the user does not exist when the code is verified, Pylon creates a User row with that email and stamps emailVerified. Typing the code proves control of the address.

Send a code

Response:
In dev mode (PYLON_DEV_MODE=true), the response also includes dev_code. You can sign in without an email provider configured:

Verify a code

Response:
Store the token and pass it as Authorization: Bearer pylon_a1b2c3... on subsequent requests.

From the SDKs

Built-in security

  • Constant-time code comparison — no timing leak.
  • 5-attempt cap per code — burned after 5 wrong tries; even a correct subsequent attempt returns RATE_LIMITED.
  • 10-minute expiry — codes are short-lived.
  • 60-second send cooldown per email — clients can’t flood a user with codes. Returns 429 RATE_LIMITED with retry_after_secs.
  • Single-use — verifying a code consumes it.
  • CSPRNG-generated — codes are uniform random in 0..1_000_000.

Configuring email delivery

Magic codes need an email provider configured, otherwise they only work in dev mode. Pylon supports:
On Pylon Cloud, magic-link email is included. You need no provider config for the built-in sender. Configure your own domain in Settings → Email for production to keep deliverability high. If you set PYLON_EMAIL_PROVIDER=webhook, also set PYLON_EMAIL_ENDPOINT to your custom URL. Pylon POSTs { to, from, subject, body } to it. To give auth email its own key and from-address, separate from your app’s ctx.email, set the PYLON_AUTH_EMAIL_* family (_PROVIDER, _API_KEY, _FROM, _ENDPOINT). It overrides PYLON_EMAIL_* for auth flows only. See Auth → Configuration. See Stack0, Resend, SendGrid for transactional sending services.

Customizing the email

The default subject is “Your sign-in code” and the body is plain text:
To customize, write your own action that calls magic/send server-side and sends your own templated email. The plugin system also supports replacing the email transport. See Plugins → Integrations.

Error responses

Testing

In dev mode, skip the email entirely:
For integration tests, this is the fastest sign-in path — no SMTP mock needed.

When to choose magic codes vs alternatives

Most apps should start with magic codes, then add OAuth for one-click sign-in once they have users. Password is the third option, useful when email is not available (for example a shared device with no email access).