Next.js Webhook Setup

Instagram Webhook in Next.js (Route Handlers)

This is the clean Next.js way: create a single route handler that responds to GET verification and POST events.

Back to docs
Set this env var:
IG_WEBHOOK_VERIFY_TOKEN="your-secret-verify-token"

1) Create route handler

Create this file: app/api/webhooks/instagram/route.ts. Meta will call this endpoint for verification and events.

// app/api/webhooks/instagram/route.ts
import { NextRequest } from "next/server";

const VERIFY_TOKEN = process.env.IG_WEBHOOK_VERIFY_TOKEN!;

// GET = Verification request
export async function GET(req: NextRequest) {
  const { searchParams } = new URL(req.url);

  const mode = searchParams.get("hub.mode");
  const token = searchParams.get("hub.verify_token");
  const challenge = searchParams.get("hub.challenge");

  if (mode === "subscribe" && token === VERIFY_TOKEN && challenge) {
    return new Response(challenge, { status: 200 });
  }

  return new Response("Forbidden", { status: 403 });
}

// POST = Event notifications
export async function POST(req: NextRequest) {
  const body = await req.json();

  // Respond immediately
  // (If you need heavy processing, push to a queue here.)
  console.log("IG WEBHOOK EVENT:", JSON.stringify(body, null, 2));

  return new Response("OK", { status: 200 });
}

PRIVACY POLICY

privacy-policy/page.tsx


export default function PrivacyPolicyPage() {
  return (
    <div className="max-w-4xl mx-auto px-6 py-12 text-gray-900 leading-relaxed">
      <h1 className="text-3xl font-bold mb-2">Privacy Policy</h1>
      <p className="text-gray-500 mb-8">
        Last updated: {new Date().toISOString().slice(0, 10)}
      </p>

      <Card title="Overview">
        This application integrates with Instagram to enable messaging and
        webhook-based event handling. We process only the data required to
        provide the service and improve reliability.
      </Card>

      <Card title="Data We Collect">
        <ul className="list-disc ml-6 space-y-2">
          <li>Webhook event payloads sent by Meta/Instagram</li>
          <li>Technical metadata for debugging and reliability</li>
        </ul>
        <p className="mt-4">
          We do <strong>not</strong> sell your data.
        </p>
      </Card>

      <Card title="How We Use Data">
        <ul className="list-disc ml-6 space-y-2">
          <li>Deliver messaging features</li>
          <li>Monitor errors</li>
          <li>Prevent abuse</li>
        </ul>
      </Card>

      <Card title="Security">
        We use HTTPS and restricted access controls. Do not share your access
        tokens publicly.
      </Card>

      <Card title="Contact">
        Email: <strong>support@yourdomain.com</strong>
      </Card>
    </div>
  );
}

function Card({ title, children }: any) {
  return (
    <div className="border rounded-xl p-6 mb-6 shadow-sm">
      <h2 className="text-xl font-semibold mb-3">{title}</h2>
      {children}
    </div>
  );
}

2) Put the callback URL in Meta dashboard

Use this as your Callback URL in the Webhooks settings:

https://your-domain.com/api/webhooks/instagram

Set your Verify Token in the dashboard to match IG_WEBHOOK_VERIFY_TOKEN. When you click “Verify and Save”, Meta sends a GET request with the hub parameters, and your GET handler must echo back the challenge.

3) Message ID note (important)

You only get a message_id when you receive an incoming event (DM, comment, mention, etc.) through your webhook. That’s why webhooks are required for features like reactions (react/unreact needs a message id from an inbound payload).

Reference: Instagram Platform Webhooks docs + Meta Webhooks verification flow.