Skip to main content
AgentMark webhooks deliver alert notifications to your application when cost, latency, or error-rate thresholds are breached or resolved.

How it works

When an alert fires or resolves, the platform sends an HTTP POST request to your configured webhook URL. The request includes the alert event payload and an x-agentmark-signature-256 header for signature verification. Your endpoint verifies the signature, processes the alert, and returns a 200 status code.

Setup

1. Get your webhook secret

  1. Open your app in the AgentMark dashboard.
  2. Navigate to Settings.
  3. Under “Webhook Settings”, find:
    • Webhook URL — where you will enter your production endpoint URL.
    • Webhook Secret — used for signature verification.
Keep your webhook secret secure. Use environment variables — never commit it to source control.

2. Install dependencies

npm install @agentmark-ai/shared-utils

3. Create the webhook endpoint

Set up environment variables:
AGENTMARK_WEBHOOK_SECRET=your_webhook_secret
Create a POST endpoint that verifies signatures and handles alert events. This example uses Next.js App Router:
app/api/agentmark-alerts/route.ts
import { NextRequest, NextResponse } from "next/server";
import { verifySignature } from "@agentmark-ai/shared-utils";

export const dynamic = "force-dynamic";

export async function POST(request: NextRequest) {
  const payload = await request.json();
  const signature = request.headers.get("x-agentmark-signature-256");

  // 1. Verify signature
  if (
    !signature ||
    !(await verifySignature(
      process.env.AGENTMARK_WEBHOOK_SECRET!,
      signature,
      JSON.stringify(payload)
    ))
  ) {
    return NextResponse.json(
      { message: "Invalid signature" },
      { status: 401 }
    );
  }

  try {
    const { event } = payload;

    // 2. Handle alert events
    if (event.type === "alert") {
      const { alert, message, timestamp } = event.data;

      console.log(
        `Alert ${alert.status}: ${alert.type}${message} (${timestamp})`
      );

      // Route to your notification system (Slack, PagerDuty, email, etc.)
      // await sendSlackNotification(alert, message);

      return NextResponse.json({
        message: "Alert processed",
        alertId: alert.id,
        status: alert.status,
      });
    }

    return NextResponse.json(
      { message: `Unknown event type: ${event.type}` },
      { status: 400 }
    );
  } catch (error) {
    console.error("Webhook error:", error);
    return NextResponse.json(
      { message: "Internal server error" },
      { status: 500 }
    );
  }
}

4. Deploy and configure

1

Deploy your endpoint

Deploy your application to a publicly accessible URL (e.g., Vercel, Railway, AWS).
2

Add the webhook URL

In the AgentMark dashboard, go to Settings and enter your endpoint URL (e.g., https://your-app.vercel.app/api/agentmark-alerts).
3

Set the webhook secret

Add the webhook secret from the dashboard to your deployment’s environment variables as AGENTMARK_WEBHOOK_SECRET.
4

Test

Configure an alert in the platform (e.g., cost threshold), trigger the condition, and verify your endpoint receives the event.

Event format

{
  "event": {
    "type": "alert",
    "data": {
      "alert": {
        "id": "string",
        "currentValue": 0,
        "threshold": 0,
        "status": "triggered | resolved",
        "timeWindow": "string",
        "type": "cost | latency | error_rate"
      },
      "message": "string",
      "timestamp": "string"
    }
  }
}

Alert types

TypeMonitorsExample Threshold
costAPI usage costsSpending > $50/day
latencyResponse timesP95 latency > 5000ms
error_rateError frequencyError rate > 5%

Processing alerts

if (event.type === "alert") {
  const { alert, message, timestamp } = event.data;

  if (alert.status === "triggered") {
    switch (alert.type) {
      case "cost":
        console.log(`Cost alert: ${alert.currentValue} exceeded threshold ${alert.threshold}`);
        break;
      case "latency":
        console.log(`Latency alert: ${alert.currentValue}ms exceeded threshold ${alert.threshold}ms`);
        break;
      case "error_rate":
        console.log(`Error rate alert: ${alert.currentValue}% exceeded threshold ${alert.threshold}%`);
        break;
    }
  } else if (alert.status === "resolved") {
    console.log(`Alert ${alert.id} resolved at ${timestamp}`);
  }
}

Integration examples

Slack notifications

async function sendSlackNotification(alert: any, message: string) {
  const slackWebhookUrl = process.env.SLACK_WEBHOOK_URL;
  if (!slackWebhookUrl) return;

  await fetch(slackWebhookUrl, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      text: `AgentMark Alert: ${alert.type.toUpperCase()}`,
      blocks: [
        {
          type: "section",
          text: { type: "mrkdwn", text: message },
        },
        {
          type: "section",
          fields: [
            { type: "mrkdwn", text: `*Status:*\n${alert.status}` },
            { type: "mrkdwn", text: `*Current:*\n${alert.currentValue}` },
            { type: "mrkdwn", text: `*Threshold:*\n${alert.threshold}` },
            { type: "mrkdwn", text: `*Window:*\n${alert.timeWindow}` },
          ],
        },
      ],
    }),
  });
}

Email notifications

async function sendEmailAlert(alert: any, message: string) {
  // Use your preferred email service (Resend, SendGrid, AWS SES, etc.)
  const emailConfig = {
    from: process.env.ALERT_EMAIL_FROM,
    to: process.env.ALERT_EMAIL_TO,
    subject: `AgentMark Alert: ${alert.type} - ${alert.status}`,
    html: `
      <h2>AgentMark Alert</h2>
      <p>${message}</p>
      <table>
        <tr><td><strong>Alert ID:</strong></td><td>${alert.id}</td></tr>
        <tr><td><strong>Type:</strong></td><td>${alert.type}</td></tr>
        <tr><td><strong>Status:</strong></td><td>${alert.status}</td></tr>
        <tr><td><strong>Current Value:</strong></td><td>${alert.currentValue}</td></tr>
        <tr><td><strong>Threshold:</strong></td><td>${alert.threshold}</td></tr>
      </table>
    `,
  };

  // await sendEmail(emailConfig);
}

Security best practices

  1. Always verify signatures — reject requests with missing or invalid x-agentmark-signature-256 headers.
  2. Use HTTPS — your production endpoint must use HTTPS.
  3. Store secrets in environment variables — never hardcode credentials.
  4. Return proper status codes401 for auth failures, 400 for bad requests, 500 for server errors.
  5. Respond quickly — return a 200 status promptly, then process the alert asynchronously if needed.
  6. Route by type — send cost alerts to finance channels, latency alerts to engineering, etc.

Have Questions?

We’re here to help! Choose the best way to reach us: