Contact methods
A user can link one or more contact methods: an email address, phone number, or Google Account. Contact methods identify users and provide channels for verification and sign-in.
By default, only users with at least one verified contact method can call your Forte services. Forte rejects unauthenticated requests with HTTP 401 and requests from unverified users with HTTP 403.
To learn more about user authentication, see Authentication and Sessions.
Choose a contact method
| Type | Verified by default | Requires verification |
|---|---|---|
| Google OAuth | Yes* | No |
| No | Yes | |
| Phone number | No | Yes |
*When Google indicates that the user's email is verified. In rare cases, OAuth accounts may require manual verification.
Verify an email or phone number
For email and phone contact methods, Forte sends a 6-digit verification code to the user:
- The user adds a new contact method (email or phone) to their account.
- Forte sends a 6-digit verification code to the contact method.
- The user enters the code in your app.
- Your app submits the code to Forte's verification endpoint.
Verification rules:
- Codes expire after 10 minutes
- Resending a code requires a 60-second cooldown between attempts
- Users cannot delete their last verified contact method
Signing in can also verify a contact method — but only while the account has no verified contact method yet. Completing an OTP login or a password reset on an unverified contact verifies it, which is how an unverified user recovers. Once an account has a verified owner, you can only verify more contacts through the in-session flow described earlier. See Authentication → Edge Cases and Recovery.
Fixed test codes in sandbox
In sandbox projects, you can assign a fixed 6-digit code to a contact method so automated tests can complete OTP flows deterministically. While a fixed code is set, every one-time code sent to that contact method — verification, OTP sign-in, and email/SMS MFA challenges — uses the fixed code, and no email or SMS is actually delivered.
Fixed codes can only be assigned to designated test contact methods:
- phone: a United States number with a
555exchange, for example+1 202 555 0142 - email: a reserved test domain —
example.com,example.net,example.org, or any domain ending in.test,.example, or.invalid
Attempting to assign a fixed code to any other contact method returns CONTACT_METHOD_NOT_ELIGIBLE_FOR_FIXED_CODE (HTTP 400), and the operation is rejected entirely outside sandbox projects (SANDBOX_MODE_REQUIRED).
Assigning a fixed code
From the console: open the user's detail page. From the contact method menu, choose Set Fixed OTP… under Sandbox only. The contact method row displays the assigned code.
From the API: use the administrative contact-method update endpoint:
PATCH /api/v1/{projectId}/users/{userId}/contact-methods/{contactMethodId}
{ "fixedVerificationCode": "123456" }To remove it:
PATCH /api/v1/{projectId}/users/{userId}/contact-methods/{contactMethodId}
{ "removeFixedVerificationCode": true }The current fixed code is readable on ContactMethod responses as fixedVerificationCode, and assignments/removals are recorded in the user's action log (CONTACT_METHOD_FIXED_OTP_SET / CONTACT_METHOD_FIXED_OTP_REMOVED).
Flow semantics
The fixed code substitutes for the random code at send time — your test still triggers the same send/resend calls a real client would:
- Trigger the flow as normal (add contact method, request OTP login, send verification code, …).
- Nothing is delivered, but the pending code is armed with your fixed value.
- Submit the fixed code to the verification endpoint.
Expiry (10 minutes), the 60-second resend cooldown, and attempt limits all behave exactly as in production, so sandbox tests exercise the real state machine. Verifying a contact method does not clear its fixed code — it keeps working for later sign-in and MFA flows.
Unverified contact methods
An unverified email or phone number is reserved within the project as soon as the user adds it — a second user in the same project cannot register or add the same identifier while the first user's verification is still in progress. Attempting to do so returns USER_ALREADY_EXISTS (HTTP 409).
This reservation is time-bound, not permanent. Once the original verification code expires (10 minutes after the last send) without being entered, the unverified contact method becomes stale and is eligible to be reclaimed.
What "stale" means
A contact method is stale when both:
- It has never been verified, and
- More than 10 minutes have passed since the last verification code was issued (that is, the code window has elapsed and the owner did not complete verification or request a new code).
A verified contact method is never stale and is never reclaimed — it permanently owns that identifier within the project.
Reclaim behavior
When a new user attempts to register — or an existing user attempts to add a contact method — that matches a stale unverified entry on another user, Forte transfers the identifier to the new caller:
- The stale entry is removed from the original user.
- If that was the original user's only contact method, the original user is removed from the project — the identifier is being transferred to the new caller, and the displaced account has no other way to authenticate. Any session token that was issued to that user during their incomplete registration is invalidated at the same moment — see Sessions → Understand automatic invalidation.
- The new caller's request proceeds as if the identifier had been free. A fresh verification code is sent to the new caller.
- An audit log entry of type
CONTACT_METHOD_DISPLACEDis recorded against the original user, naming the displacedcontactMethodId. See Administration for retrieving user action logs.
Reclaim only happens when the original user abandons the identifier — leaves it unverified past the window — and another user actively claims it. Before that, the original user is not locked out: signing in via OTP or completing a password reset verifies the contact and ends its staleness. See Authentication → Edge Cases and Recovery.
When the new caller eventually verifies the reclaimed identifier (their first verified contact method on the new account), every other outstanding session for that account is also invalidated. This protects the account against any stale sessions that may have existed from prior unverified registration attempts on the same identifier — see Sessions → Understand automatic invalidation.
When the request is still rejected
You still see USER_ALREADY_EXISTS (HTTP 409) when:
- Another user in the project owns the identifier as a verified contact method.
- Another user in the project is mid-verification — they added the identifier within the last 10 minutes and the code has not yet expired.
In both cases the new caller should treat the identifier as taken. The first case requires the original owner to remove the contact method themselves; the second resolves automatically once the verification window elapses.
SDK functions
The Forte SDK includes functions for contact method verification:
resendOTP— Send another one-time passcode to the user's phone number or email address. Subject to a 60-second cooldown between attempts.resendVerificationCode— Send another verification code for a contact method that is not yet verified. Also subject to a 60-second cooldown.
Next steps
- Set up Authentication methods for your users
- Learn about Sessions and token management
- Manage users from the Forte console