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

How it works

If the user doesn’t exist when the code is verified, Pylon auto-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 so you can sign in without configuring an email provider:

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:
If you’re on Pylon Cloud, magic-link email is included — no provider config needed for the included sender. Configure your own domain in Settings → Email for production use 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, intercept the send by writing your own action that calls magic/send server-side and ships your own templated email instead. 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 ship magic codes first, then add OAuth for one-click sign-in once they have users. Password is the third option, useful when email isn’t an option (e.g. shared device with no email access).