Skip to content

Commit 92c3565

Browse files
committed
✨ feat: Newsletter signup API
1 parent 13efd8c commit 92c3565

1 file changed

Lines changed: 70 additions & 0 deletions

File tree

api/newsletter-signup.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { Resend } from "resend"
2+
3+
const resend = new Resend(process.env.RESEND_API_KEY)
4+
5+
export default async function handler(req: Request) {
6+
if (req.method !== "POST") {
7+
return new Response(JSON.stringify({ error: "Method not allowed" }), {
8+
status: 405,
9+
headers: { "Content-Type": "application/json" },
10+
})
11+
}
12+
13+
try {
14+
const { email, first_name, last_name } = await req.json()
15+
16+
if (!email) {
17+
return new Response(JSON.stringify({ error: "Email is required" }), {
18+
status: 400,
19+
headers: { "Content-Type": "application/json" },
20+
})
21+
}
22+
23+
// Validate email format
24+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
25+
if (!emailRegex.test(email)) {
26+
return new Response(JSON.stringify({ error: "Invalid email format" }), {
27+
status: 400,
28+
headers: { "Content-Type": "application/json" },
29+
})
30+
}
31+
32+
const audienceId = process.env.RESEND_AUDIENCE_ID
33+
if (!audienceId) {
34+
return new Response(
35+
JSON.stringify({ error: "Server configuration error" }),
36+
{ status: 500, headers: { "Content-Type": "application/json" } }
37+
)
38+
}
39+
40+
// Create contact in Resend
41+
const contact = await resend.contacts.create({
42+
email,
43+
firstName: first_name || undefined,
44+
lastName: last_name || undefined,
45+
audienceId,
46+
})
47+
48+
if (contact.error) {
49+
console.error("Resend API error:", contact.error)
50+
return new Response(
51+
JSON.stringify({ error: "Failed to subscribe to newsletter" }),
52+
{ status: 500, headers: { "Content-Type": "application/json" } }
53+
)
54+
}
55+
56+
return new Response(
57+
JSON.stringify({
58+
message: "Successfully subscribed to newsletter",
59+
id: contact.data?.id,
60+
}),
61+
{ status: 201, headers: { "Content-Type": "application/json" } }
62+
)
63+
} catch (error) {
64+
console.error("Newsletter signup error:", error)
65+
return new Response(JSON.stringify({ error: "Internal server error" }), {
66+
status: 500,
67+
headers: { "Content-Type": "application/json" },
68+
})
69+
}
70+
}

0 commit comments

Comments
 (0)