email field and stamps emailVerified on a successful verify.
The OAuth and SSO sign-in paths stamp emailVerified automatically, because the upstream IdP already verified the email. Use this flow when the IdP did not verify the email (manual signup, edit-email flow, etc.).
Endpoints
Schema
The User entity needs anemailVerified field. Pylon writes the current ISO 8601 timestamp on success:
update rejects the unknown column and /email/verify returns 500 PERSIST_FAILED (with a hint to add an emailVerified datetime field to the User entity) instead of silently succeeding.
Sending a verification code
email, creates a code, and sends an email with subject "Verify your email address" through the configured email transport. Body: "Your email verification code is: <code>\n\nThis code will expire in 10 minutes.". Override both with PYLON_EMAIL_TEMPLATE_EMAIL_VERIFY_SUBJECT and PYLON_EMAIL_TEMPLATE_EMAIL_VERIFY_BODY. The response includes codeLength.
Response in production:
PYLON_DEV_MODE=true) to a request from the same machine:
The throttle is shared with magic-code sends: 1 code per email per minute. The 10-minute TTL is shared too.
Verifying
emailVerified to the current ISO 8601 timestamp and echoes it back in the response.
Errors:
Gating handlers on emailVerified
In your TS code:
emailVerified from the User entity and reference it directly:
auth.emailVerified to the policy DSL today. The field lives on your User row. You reference it through your own handlers or queries.
Security guarantees
- Code generation, comparison, throttling shared with magic-codes — numeric (6 digits by default,
PYLON_AUTH_CODE_LENGTH), 10-minute TTL, burn-after-5-wrong-attempts, the same daily wrong-guess limit per email (429 CODE_LOCKED), constant-time comparison. - Session-gated — only the authenticated user can request and verify their own email. There is no admin override. To mark an email verified from another process, write the User row directly with admin auth.
- ISO 8601 timestamp format —
pylon_kernel::util::now_iso()produces2026-01-15T10:30:00Z. An email is verified only whenemailVerifiedis non-null.
Where to go next
- Magic codes — the same code primitive as a primary sign-in flow
- Password — the register flow that produces an unverified email