Skip to main content
This endpoint receives contact form submissions, validates input with Zod, and returns a JSON response. It does not require authentication by default.
This API endpoint receives and processes submissions from the frontend contact form. It’s responsible for server-side validation and handling the submitted data.
  • Endpoint: POST /api/contact
  • File Location: src/app/api/contact/route.ts

Parameters

firstName
string
Sender’s first name. Minimum length: 2.
lastName
string
Sender’s last name. Minimum length: 2.
email
string
Valid email address for reply.
company
string
Company or organization name. Minimum length: 2.
message
string
Message content. Minimum length: 10.

Request/Response

Example Request

curl -X POST 'http://localhost:3000/api/contact' \
  -H 'Content-Type: application/json' \
  -d '{
    "firstName": "Jane",
    "lastName": "Doe",
    "email": "[email protected]",
    "company": "Acme Inc",
    "message": "I would like to learn more about Sabo."
  }'

Example Response (Success)

{
  "success": true,
  "message": "Thank you for your message! We'll get back to you soon."
}

Example Response (Validation Error · 400)

{
  "success": false,
  "message": "Validation failed",
  "errors": [
    {
      "code": "too_small",
      "minimum": 2,
      "type": "string",
      "inclusive": true,
      "exact": false,
      "message": "First name must be at least 2 characters",
      "path": ["firstName"]
    }
  ]
}

Example Response (Server Error · 500)

{
  "success": false,
  "message": "An error occurred while processing your request"
}

How It Works

  1. Receives Data: The endpoint accepts a POST request with a JSON body containing the form data.
  2. Validates Data: It uses a Zod schema to perform server-side validation. This is a crucial security step to ensure data integrity. If validation fails, it returns a 400 Bad Request error.
  3. Processes Data: By default, the endpoint logs the validated data to the server console.
  4. Returns Response: On success, it returns a 200 OK response with a success message.

Customizing the Submission Logic

To make the contact form useful, you need to replace the default console.log action with your own business logic. A common use case is to send an email notification.

Example: Sending an Email with Resend

Here’s how you can modify the endpoint to send an email using Resend, a popular email service for React developers.
1

Install Resend

First, add the Resend package to your project.
pnpm add resend
2

Get API Key

Sign up for a Resend account and get your API key. Add it to your .env.local file.
.env.local
RESEND_API_KEY=your_api_key_here
3

Update the API Endpoint

Modify the route.ts file to import Resend and use it to send an email with the form data.
src/app/api/contact/route.ts
import { NextResponse } from "next/server";
import { z } from "zod";
import { Resend } from "resend";

// Initialize Resend
const resend = new Resend(process.env.RESEND_API_KEY);

const contactFormSchema = z.object({
  firstName: z.string().min(2),
  lastName: z.string().min(2),
  email: z.string().email(),
  company: z.string().optional(),
  message: z.string().min(10),
});

export async function POST(request: Request) {
  try {
    const body = await request.json();
    const data = contactFormSchema.parse(body);

    // Replace console.log with email sending logic
    await resend.emails.send({
      from: '[email protected]', // Your verified sending email
      to: '[email protected]', // Your personal email to receive notifications
      subject: `New Contact Form Submission from ${data.firstName}`,
      text: `Name: ${data.firstName} ${data.lastName}\nEmail: ${data.email}\nCompany: ${data.company || 'N/A'}\nMessage: ${data.message}`,
    });

    return NextResponse.json({ message: "Form submitted successfully!" });
  } catch (error) {
    if (error instanceof z.ZodError) {
      return NextResponse.json({ error: error.errors }, { status: 400 });
    }
    return NextResponse.json({ error: "Something went wrong" }, { status: 500 });
  }
}
You can also use this endpoint to save submissions to a database, post to a Slack channel, or integrate with any other service.
Resend is optional and not bundled by default. This example shows how you can wire it if you need email notifications. For global route protection vs per‑route guards, see Routing & Middleware.