Skip to main content
When you create a new conversation and authorize a client session you can set custom metadata and custom headers that will be included in every webhook sent for that conversation (and its sessions).

1) Set metadata and headers during authorization

Include the optional custom_metadata and custom_headers objects in your call to POST /v1/agents/web/authorize_session (see REST API docs). Both fields must be plain JSON objects.
curl -X POST https://api.layercode.com/v1/agents/web/authorize_session \
  -H "Authorization: Bearer $LAYERCODE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "dvv052qk",
  }'
Next.js app/api/authorize/route.ts
export const dynamic = "force-dynamic";
import { NextResponse } from "next/server";

export const POST = async (request: Request) => {
  // Here you could do any user authorization checks you need for your app
  const endpoint = "https://api.layercode.com/v1/agents/web/authorize_session";
  const apiKey = process.env.LAYERCODE_API_KEY;
  if (!apiKey) {
    throw new Error("LAYERCODE_API_KEY is not set.");
  }
  const requestBody = await request.json();
  if (!requestBody || !requestBody.agent_id) {
    throw new Error("Missing agent_id in request body.");
  }

  ///
  // Custom metadata and headers can be set on the conversation here, so they're included in the authorization request to Layercode.
  // The values set here will then be included in every webhook request sent to your backend for this conversation and its sessions.
  //
  requestBody.custom_metadata = {
    "tenant_id": "t_42",
    "crm_contact_id": "abc-123"
  }
  requestBody. custom_headers = {
    "x-tenant-id": "t_42",
    "x-layercode-flow": "concierge"
  }

  try {
    const response = await fetch(endpoint, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${apiKey}`,
      },
      body: JSON.stringify(requestBody),
    });
    if (!response.ok) {
      const text = await response.text();
      throw new Error(text || response.statusText);
    }
    return NextResponse.json(await response.json());
  } catch (error: any) {
    console.log("Layercode authorize session response error:", error.message);
    return NextResponse.json({ error: error.message }, { status: 500 });
  }
};

2) Read the metadata in your webhook handler

Every webhook invocation now includes the metadata you provided:
{
  "type": "message",
  "session_id": "a0ad4pv43sdakgh99lxeik8x",
  "conversation_id": "ary4c07o15n5l43iu7dkhukt",
  "custom_metadata": {
    "tenant_id": "t_42",
    "crm_contact_id": "abc-123"
  },
  // ...
}

3) Inspect custom headers on receipt

Layercode prepends two headers to every webhook call: Content-Type: application/json and layercode-signature. Your custom headers are then appended.
webhook-handler.ts
export async function POST(request: Request) {
  const xTenantId = request.headers.get('x-tenant-id');
  // ...
  const payload = await request.json();
  // ...
}
I