Capxul Docs
HooksAuth & session

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:

FieldDescription
mutateFire the mutation (fire-and-forget; pair with onSuccess/onError callbacks).
mutateAsyncFire the mutation and get a Promise of the result. Rejects with a CapxulError on failure.
dataThe mutation result (typed per hook, shown above). undefined until the first success.
errorA CapxulError when the last attempt failed, otherwise null.
isPendingtrue while the mutation is in flight. Use it to disable submit buttons.
resetClear 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:

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.

On this page