Creating an API Route for Form Data

    Jack HerringtonJack Herrington

    Start by creating a new file at api/registerForm/route.tsx.

    The code in this file will be mostly the same as in the register/route.tsx file, but with a couple of key differences.

    This time w'll be using req.formData() inside of the POST request handler, and using Object.fromEntries() to get the form data into a simple object:

    // inside api/registerForm/route.tsx
    import { schema } from "@app/registrationSchema"
    export async function POST(req: NextRequest) {
      const formData = await req.formData(); // Get the form data
      const data = Object.fromEntries(formData); // Convert form data into a simple data object
      let parsed = schema.safeParse(data)
      if (parsed.success) {
        // Add to the database
        return NextResponse.json({ message: "User registered", data: });
      } else {
        return NextResponse.json(
          { error: parsed.error },
          { status: 400 }  

    With these changes in place, we've created a registerForm endpoint which expects data to be posted in formData format instead of JSON.

    Adjusting Our Registration Form

    Inside of the RegistrationForm.tsx file, we'll need to make a few changes to the fetch request.

    First we'll comment out the existing fetch request to the JSON register endpoint.

    In its place we'll create a new FormData object and append the first, last, and email fields to it. Then we'll send the FormData object as the body of the request, without setting the Content-Type header:

    // inside of RegistrationForm
    const onSubmit = aysync (data: z.infer<typeof schema>) => {
      const formData = new FormData(); // Create a new FormData object
      formData.append("first", first)
      formData.append("last", last)
      formData.append("email", email)
      fetch("/api/registerForm", {
        method: "POST",
        body: formData,
      .then(response => response.json())
      .then(data => console.log(data))

    We don't need to send the Content-Type header, because FormData is the default format.

    Testing the Form

    Over on the page, we can hit submit and see the "User registered" message in the console!

    This is the second method of sending form data to the server. In the next lesson, we'll discuss how to use server actions for submitting form data and performing server-side validation.


    Now I'm going to go create a new route here called register form, route.tsx. And in there, I'm going to bring the code from register is mostly the same, but now we've got back this form data object. That is a special object that has getters and setters on it.

    We really want a simple object that has just the first, last, and email on it. So what we're going to do is use object at from entries to take that form data and convert it into a simple data object. And that's really it. So now we have this API register form endpoint,

    and we just need to post to that in a form data format as opposed to a JSON format. So let's go back into our registration form and I will copy this section and then comment it out. So you still have it, but we're going to make some changes. We're going to say,

    we want to go to register form and start to make some form data. So to do that, we create a new form data object, and then we just set the values individually. We just append first, last, and email to our form data. And then we can just send that as the body. Now what happens here to the content type? Well, we just get rid of it.

    Form data is the default. All right, let's give it a try. And then let's hit submit. And there you go. User registered. Awesome. In the next section, we'll take a look at server actions and how to use them to go and submit form data and also validate it on the server side.