Verify and log in through OTP
Verify a one-time password (or email confirmation link) and produce a session.
Submit the code or token a user received from sign_in_with_otp, an email confirmation link, an SMS, or a password-recovery email to GoTrue's POST /verify endpoint. On success the user is signed in, the session is persisted, and a SIGNED_IN event is emitted.
Two related input modes:
token:+ (email:orphone:) — the 6-digit code path (used by SMS and email OTPs).token_hash:(no email/phone needed) — the link path, where the hashed token comes from the URL query string of a magic link / confirmation / recovery email.
Signature
supabase.auth.verify_otp(params)params is a hash — pass a literal or use Ruby's hash-literal shorthand.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
type | String | Required | OTP type: "signup", "magiclink", "recovery", "invite", "email_change" for email flows; "sms", "phone_change" for phone flows; "email" for token_hash link flows. |
email | String | Optional | User email. Required with token: for email-OTP flows; ignored when token_hash: is provided. |
phone | String | Optional | User phone number in E.164 format. Required with token: for SMS flows; ignored when token_hash: is provided. |
token | String | Optional | 6-digit code the user received. Mutually exclusive with token_hash:. |
token_hash | String | Optional | Hashed token from a magic-link / confirmation / recovery URL. Used in place of token: + email/phone for link-based flows. |
options | Hash | Optional | Nested options: redirect_to (String, post-verification redirect for link flows), captcha_token (String). |
Returns
A Struct with :user and :session. On successful verification both are populated; the session is also saved to the configured storage and SIGNED_IN is dispatched to every on_auth_state_change subscriber.
Example — verify an email magic-link code
response = supabase.auth.verify_otp(
email: "ada@example.com",
token: "123456",
type: "email"
)
response.user.email # => "ada@example.com"
response.session.access_token # => "eyJ..."Example — verify an SMS code
response = supabase.auth.verify_otp(
phone: "+15555550123",
token: "123456",
type: "sms"
)Example — verify a token_hash from a magic link URL
# Your callback page receives ?token_hash=...&type=email in the URL.
response = supabase.auth.verify_otp(
token_hash: params[:token_hash],
type: params[:type] # e.g. "email" or "recovery"
)
response.session.access_tokenExample — verify a password-recovery code
# After reset_password_for_email lands the user with a code:
response = supabase.auth.verify_otp(
email: "ada@example.com",
token: "654321",
type: "recovery"
)
# Now update_user can be called against the recovered session.
supabase.auth.update_user(password: "new-strong-password-2026")On success the returned session is saved and SIGNED_IN is dispatched. Invalid or expired codes surface as Supabase::Auth::Errors::AuthApiError.