> ## Documentation Index
> Fetch the complete documentation index at: https://dynamic-docs-feat-sidebar-revamp.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Headless Email Signup

## Introduction

This guide will help you let a user signup/login with email, without any of our UI components. We've split the guide into two tabs as you'll see below. The first uses our SDK hooks (but none of the UI components) - we recommend this choice if you can. The second tab shows you how to handle email login without any SDK interaction at all i.e. API only.

## Tutorial

<Tabs>
  <Tab title="SDK Hooks">
    ### Configuring the SDK

    Let's start by installing our packages. Follow our [Quickstart guide](/quickstart) for a detailed walkthrough.

    When you're done, we'll update our App.js to include our environment ID in the setup and import the `DynamicContextProvider` and `EthereumWalletConnectors`.

    You app.js file should look like this (note that we are only importing the EthereumWalletConnectors for now):

    ```jsx
    import { DynamicContextProvider } from '@dynamic-labs/sdk-react-core';
    import { EthereumWalletConnectors } from "@dynamic-labs/ethereum";

    // Placeholder for our SMS signup/login form component
    import ConnectWithEmailView from './ConnectWithEmailView';


    function App() {
      return (
        <div className="App">
            <DynamicContextProvider
              settings={{
                environmentId: "YOUR_ENVIRONMENT_ID_GOES_HERE",
                walletConnectors: [ EthereumWalletConnectors ],

              }}
            >
            <ConnectWithEmailView />
            </DynamicContextProvider>
        </div>
      );
    }

    export default App;
    ```

    ### useConnectWithOtp

    All we will need for this use case is the [useConnectWithOtp hook](/react-sdk/hooks/login-user-management/useconnectwithotp). This exposes multiple methods, and we are interested primarily in the following:

    * connectWithEmail
    * verifyOneTimePassword

    Once you have those available in your component, the rest is as simple as building your form!

    ### Code Example

    ```tsx
    import { FC, FormEventHandler } from 'react';
    import { useConnectWithOtp, useDynamicContext } from '@dynamic-labs/sdk-react-core';

    const ConnectWithEmailView: FC = () => {
      const { user } = useDynamicContext()

      const { connectWithEmail, verifyOneTimePassword } = useConnectWithOtp();

      const onSubmitEmailHandler: FormEventHandler<HTMLFormElement> = async (
        event,
      ) => {
        event.preventDefault();

        const email = event.currentTarget.email.value;

        await connectWithEmail(email);
      };

      const onSubmitOtpHandler: FormEventHandler<HTMLFormElement> = async (
        event,
      ) => {
        event.preventDefault();

        const otp = event.currentTarget.otp.value;

        await verifyOneTimePassword(otp);
      };

      return (
        <div>
          <form key='email-form' onSubmit={onSubmitEmailHandler}>
            <input type='email' name='email' placeholder='Email' />
            <button type='submit'>Submit</button>
          </form>

          <form key='otp-form' onSubmit={onSubmitOtpHandler}>
            <input type='text' name='otp' placeholder='OTP' />
            <button type='submit'>Submit</button>
          </form>

          {!!user && (
            <p>Authenticated user:</p>
            <pre>
              {JSON.stringify(user, null, 2)}
            </pre>
          )}
        </div>
      )
    }
    ```
  </Tab>

  <Tab title="API Only">
    Here we follow three simple steps, creating the email verification, verifying the OTP, and getting the JWT.

    ### Basic UI

    First let's create a basic React component to help us handle the UI:

    ```JSX
    import React, { useState } from 'react';

    const EmailSignup = () => {

        const DYNAMIC_ENVIRONMENT_ID = "YOUR_ENVIRONMENT_ID";

        const [email, setEmail] = useState("");
        const [verifying, setVerifying] = useState(false);
        const [OTP, setOTP] = useState("");
        const [UUID, setUUID] = useState("");
        const [JWT, setJWT] = useState("");

        const sendEmailVerification = async () => {};
        const verify = async () => {};

        return (
            <div>
                <h1>Signup with Email</h1>
                <input
                type="text"
                onChange={(e) => setEmail(e.target.value)}
                placeholder="Enter your email"
                value={email}
                />
                <button onClick={() => sendEmailVerification()}>Submit</button>
                {verifying && (
                <div>
                    <input
                    type="text"
                    onChange={(e) => setOTP(e.target.value)}
                    placeholder="Enter your OTP"
                    value={OTP}
                    />
                    <button onClick={() => verify()}>Verify</button>
                </div>
                )}
                {JWT && <p>Your JWT is: {JWT}</p>}
            </div>
        );
    }
    ```

    We're creating a few state variables to help us keep track of the user's email, the OTP, the verificationUUID, and the JWT. We're also creating a couple of (currently empty) functions to handle the email verification and the OTP verification.

    You might be wondering what the UUID variable is for. When you create an email verification, we return a verificationUUID that you must pass into the API along with the OTP itself so that it's correctly verified.

    Lastly but most importantly, there's a variable called DYNAMIC\_ENVIRONMENT\_ID. We will need this to populate the URLs for the API calls. You can find your environment ID in the [Dynamic dashboard](https://app.dynamic.xyz/dashboard/developer/api).

    OK, let's fill in the empty functions now, going step by step:

    ### Create an email verification

    You will be interacting with [the emailVerification endpoint](https://docs.dynamic.xyz/api-reference/sdk/createEmailVerification) for this. This will send an email to the user with a One Time Password so they can verify their email address.

    You can find the full reference for the endpoint in the link above, but the main thing you need to pass is the email address of the user. We'll edit our `sendEmailVerification` function like so:

    ```javascript
    const sendEmailVerification = async () => {
      setVerifying(true);

      const options = {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ email: email }),
      };

      fetch(
        `https://app.dynamicauth.com/api/v0/sdk/${DYNAMIC_ENVIRONMENT_ID}/emailVerifications/create`,
        options
      )
        .then((response) => response.json())
        .then((response) => {
          setUUID(response.verificationUUID);
        })
        .catch((err) => console.error(err));
    };
    ```

    ### Verify the OTP

    With the above step complete, as long as the email address is valid, the user will receive an email with an OTP. They will enter the OTP in the UI, and we will verify it once they hit the "Verify" button.

    To verify the OTP, the next call will be to signIn endpoint, which you can find [here](https://docs.dynamic.xyz/api-reference/sdk/signInWithEmailVerification). You will need to pass the OTP from the email and the verificationUUID from the previous response.

    Let's fill in our `verify` function with that in mind:

    ```javascript
    const verify = async () => {
      const options = {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          verificationToken: OTP,
          verificationUUID: UUID,
        }),
      };

      fetch(
        `https://app.dynamicauth.com/api/v0/sdk/${DYNAMIC_ENVIRONMENT_ID}/emailVerifications/signIn`,
        options
      )
        .then((response) => response.json())
        .then((response) => {
          setVerifying(false);
          setJWT(response.jwt);
        })
        .catch((err) => console.error(err));
    };
    ```

    ### Get the JWT

    At this point, you'll have a JWT returned from the verify call and saved in state as the jwt variable. This JWT will be tied to a session in Dynamic, and we return details of the user from that JWT.

    Learn more about the JWT object [here](/react-sdk/objects/user-payload).

    ## Summary

    That's it! You now have a completely headless sign-in with email, using Dynamic OTP.
  </Tab>
</Tabs>
