useCapxulVerifyOtp
Mutation hook for verifying the email OTP code — completes sign-in and returns the session.
Completes email OTP sign-in: verifies the code sent by
useCapxulSignIn and signs the user in.
On success the mutation returns the new Session immediately.
Import
import { useCapxulVerifyOtp } from "@capxul/sdk-react";Usage
"use client";
import { useState } from "react";
import { useCapxulVerifyOtp } from "@capxul/sdk-react";
function VerifyOtpForm({ email }: { email: string }) {
const verifyOtp = useCapxulVerifyOtp();
const [code, setCode] = useState("");
return (
<form
onSubmit={async (event) => {
event.preventDefault();
await verifyOtp.mutateAsync({ email, code });
}}
>
<input
inputMode="numeric"
autoComplete="one-time-code"
required
value={code}
onChange={(event) => setCode(event.target.value)}
/>
<button type="submit" disabled={verifyOtp.isPending}>
{verifyOtp.isPending ? "Verifying…" : "Verify and log in"}
</button>
{verifyOtp.error ? <p>{verifyOtp.error.message}</p> : null}
</form>
);
}Verification is both "create user" and "log in": if the email has never signed
in before, Capxul creates the user identity during this call — your app does
not call a separate create-user API. After the code is accepted the SDK also
runs its post-verification setup: it detects and accepts any pending
organization invitations for the email (where organization support is
configured), and it starts the account lane in
the background when the provider's requirement is not "none" — watch that
setup with
useCapxulAccountLifecycle.
Parameters
The hook itself takes no parameters. The mutation takes a VerifyOtpInput:
Prop
Type
Return type
import { type UseCapxulVerifyOtpReturn } from "@capxul/sdk-react";
// UseMutationResult<Session, CapxulError, VerifyOtpInput>On success, data is the new Session: the authUserId, the signed-in
email, the session token, and expiresAt (epoch milliseconds). This is
the same value useCapxulSession
serves after its refetch.
The hook returns TanStack Query's UseMutationResult. The most-used fields:
| Field | Description |
|---|---|
mutate | Fire the mutation (fire-and-forget; pair with onSuccess/onError callbacks). |
mutateAsync | Fire the mutation and get a Promise of the result. Rejects with a CapxulError on failure. |
data | The mutation result (typed per hook, shown above). undefined until the first success. |
error | A CapxulError when the last attempt failed, otherwise null. |
isPending | true while the mutation is in flight. Use it to disable submit buttons. |
reset | Clear the mutation state (data, error) back to idle. |
Mutations do not retry by default. The full field list is in the
TanStack Query useMutation reference;
see also the TanStack Query integration guide.
Cache behavior
On success this mutation invalidates the auth boundary — the queries whose answers change when someone signs in:
["capxul", "session"](useCapxulSession)["capxul", "profile"](useCapxulProfile)["capxul", "accountLifecycle"](useCapxulAccountLifecycle)["capxul", "accountBalance"](useCapxulAccountBalance)
These are background refetches (invalidate, not reset) so mounted screens
update without flashing empty state. The hard reset happens on
useCapxulSignOut.
Errors
Failures surface as a CapxulError on error /
thrown from mutateAsync — most commonly an incorrect or expired code. A
failure in the SDK's post-verification setup (invitation detection, signer
session reset) also surfaces on this mutation, even though the code itself was
accepted.
Client method
This hook wraps client.auth.verifyOtp(input) on the core SDK.