Outbound Webhooks

Copy page

Receive real-time HTTP notifications when conversations, feedback, or custom events occur in your project

Outbound webhooks send HTTP POST requests to your server when events happen in your project — new conversations, conversation updates, feedback submissions, and custom events. Use them to sync data with external systems, trigger downstream workflows, or build real-time integrations.

Note
Note

Outbound webhooks push data from Inkeep to your server. For the reverse — external services triggering your agents — see Webhook Triggers.

Create a webhook

Navigate to your project and select Outbound Webhooks in the left sidebar.

Click New Webhook.

Configure the destination

Fill in the required fields:

Webhook destination form with name, URL, custom headers, event type checkboxes, and agent scope
FieldRequiredDescription
NameYesHuman-readable identifier (e.g., "Slack Notifications" or "CRM Sync")
Destination URLYesThe HTTPS endpoint that receives webhook POST requests
Event TypesYesWhich events trigger delivery (select at least one)
DescriptionNoExplains what this webhook does
Custom HeadersNoAdditional HTTP headers sent with every delivery
AgentsNoScope to specific agents. Leave empty to receive events from all agents in the project
EnabledToggle on to activate immediately

Test the destination

After creating the destination, use the Test action to send a sample payload to your URL. The test request uses a test event type with synthetic data and a 10-second timeout, so you can verify your endpoint is reachable before real events fire.

Event types

Each webhook destination subscribes to one or more event types. Your endpoint receives every event that matches the selected types and agent scope.

Event typeFires when
conversation.createdA new conversation starts
conversation.updatedA user sends a message or the assistant replies
feedback.createdA user submits feedback on a conversation
event.createdA custom event is logged via POST /run/v1/events
evaluation.failedAn evaluation result does not meet its pass criteria
conversation.execution.errorConversation reaches terminal failure
conversation.generation.errorAn LLM call fails to produce a response
conversation.tool.errorA tool call returns an error
conversation.context.errorContext resolution encounters fetch failures

Agent scoping

When you select specific agents on a webhook destination, only events originating from those agents trigger delivery. Leave the agents field empty to receive events from every agent in the project.

Payload format

Every delivery is an HTTP POST with Content-Type: application/json. The body follows a consistent envelope:

{
  "type": "conversation.updated",
  "timestamp": "2026-05-12T14:30:00.000Z",
  "tenantId": "your-tenant-id",
  "projectId": "your-project-id",
  "agentId": "your-agent-id",
  "data": {
    // event-specific payload (see below)
  }
}

Conversation events

conversation.created and conversation.updated both deliver a conversation object inside data:

{
  "type": "conversation.created",
  "timestamp": "2026-05-12T14:30:00.000Z",
  "tenantId": "your-tenant-id",
  "projectId": "your-project-id",
  "agentId": "your-agent-id",
  "data": {
    "conversation": {
      "id": "conv_abc123",
      "agentId": "your-agent-id",
      "title": "How do I reset my password?",
      "userProperties": { "userId": "u_456" },
      "properties": { "pageUrl": "https://example.com/help" },
      "createdAt": "2026-05-12T14:29:50.000Z",
      "updatedAt": "2026-05-12T14:30:00.000Z",
      "messages": [
        {
          "id": "msg_001",
          "role": "user",
          "content": "How do I reset my password?",
          "createdAt": "2026-05-12T14:29:50.000Z"
        },
        {
          "id": "msg_002",
          "role": "assistant",
          "content": "You can reset your password from the Settings page...",
          "createdAt": "2026-05-12T14:30:00.000Z"
        }
      ]
    }
  }
}

Feedback events

feedback.created delivers both the feedback and the associated conversation:

{
  "type": "feedback.created",
  "timestamp": "2026-05-12T14:31:00.000Z",
  "tenantId": "your-tenant-id",
  "projectId": "your-project-id",
  "agentId": "your-agent-id",
  "data": {
    "feedback": {
      "id": "fb_789",
      "conversationId": "conv_abc123",
      "messageId": "msg_002",
      "type": "positive",
      "details": null,
      "createdAt": "2026-05-12T14:31:00.000Z",
      "updatedAt": "2026-05-12T14:31:00.000Z"
    },
    "conversation": {
      "id": "conv_abc123",
      "agentId": "your-agent-id",
      "title": "How do I reset my password?",
      "userProperties": null,
      "properties": null,
      "createdAt": "2026-05-12T14:29:50.000Z",
      "updatedAt": "2026-05-12T14:30:00.000Z",
      "messages": [
        {
          "id": "msg_001",
          "role": "user",
          "content": "How do I reset my password?",
          "createdAt": "2026-05-12T14:29:50.000Z"
        },
        {
          "id": "msg_002",
          "role": "assistant",
          "content": "You can reset your password from the Settings page...",
          "createdAt": "2026-05-12T14:30:00.000Z"
        }
      ]
    }
  }
}

Evaluation events

evaluation.failed fires when an evaluation result does not meet its pass criteria. The payload includes the evaluator name, the conversation ID, and the specific conditions that failed:

{
  "type": "evaluation.failed",
  "timestamp": "2026-05-12T14:33:00.000Z",
  "tenantId": "your-tenant-id",
  "projectId": "your-project-id",
  "agentId": "your-agent-id",
  "data": {
    "evaluator": { "id": "evaluator_abc", "name": "Response Quality" },
    "conversation": { "id": "conv_abc123" },
    "failedConditions": [
      {
        "field": "score",
        "operator": ">=",
        "value": 0.7,
        "actual": 0.3
      }
    ]
  }
}

Custom events

event.created delivers the persisted event object:

{
  "type": "event.created",
  "timestamp": "2026-05-12T14:32:00.000Z",
  "tenantId": "your-tenant-id",
  "projectId": "your-project-id",
  "agentId": "your-agent-id",
  "data": {
    "event": {
      "id": "evt_xyz",
      "type": "user_message_submitted",
      "agentId": "your-agent-id",
      "conversationId": "conv_abc123",
      "messageId": "msg_001",
      "properties": { "source": "chat-widget" },
      "userProperties": { "userId": "u_456" },
      "metadata": { "appVersion": "1.4.2" },
      "serverMetadata": { "authMethod": "apiKey" },
      "createdAt": "2026-05-12T14:32:00.000Z",
      "updatedAt": "2026-05-12T14:32:00.000Z"
    }
  }
}

Slack integration

Webhook destinations pointing to Slack automatically receive rich formatted messages instead of raw JSON. This applies whether the URL was added via the OAuth flow or typed manually.

Connect a Slack channel

On the Outbound Webhooks page, click Connect Slack Channel. This starts a Slack OAuth flow that lets you pick a channel and grants an incoming-webhook URL.

After authorizing, you're redirected back to the webhook creation form with the Slack URL pre-filled. Select your event types and click Create.

Slack payload format

{
  "type": "conversation.created",
  "timestamp": "2026-05-12T14:30:00.000Z",
  "tenantId": "your-tenant-id",
  "projectId": "your-project-id",
  "agentId": "your-agent-id",
  "data": {
    "conversation": { "id": "conv_abc123", "title": "..." }
  },
  "text": "New Conversation: conv id: conv_abc123",
  "blocks": [
    { "type": "header", "text": { "type": "plain_text", "text": "New Conversation" } },
    { "type": "section", "fields": ["..."] },
    { "type": "section", "text": { "type": "mrkdwn", "text": "<link|View Conversation>" } },
    { "type": "context", "elements": [{ "type": "mrkdwn", "text": "Inkeep" }] }
  ]
}

The text field serves as the notification preview (mobile push, channel sidebar). The blocks array renders the rich card in the channel. Non-Slack URLs always receive the standard JSON envelope without text or blocks.

Delivery and retries

Inkeep delivers each event to each matching destination independently with automatic retries.

BehaviorDetail
MethodPOST
Timeout30 seconds per attempt
Max attempts3
Retry backoffExponential: 2s, 4s

Custom headers

Webhook deliveries include any custom headers you configure on the destination.

Warning
Warning

The following reserved headers cannot be used as custom headers: Connection, Keep-Alive, TE, Trailer, Transfer-Encoding, Upgrade, Proxy-Authorization, Proxy-Connection, Content-Length.

Manage webhook destinations

The webhook destinations page shows all configured destinations with their name, URL, enabled status, and subscribed event types.

ActionDescription
EditUpdate the name, URL, events, headers, agent scope, or enabled status
TestSend a sample payload to verify the destination is reachable
DeletePermanently remove the destination

Toggle the Enabled switch to pause or resume delivery without deleting the destination.

Conversation error events

Subscribe to error events to get notified when agent conversations encounter failures. Four error event types are available:

Event typeFires when
conversation.execution.errorConversation reaches terminal failure (max consecutive errors, max transfers exhausted, or uncaught exception)
conversation.generation.errorAn LLM call fails to produce a response
conversation.tool.errorA tool call returns an error
conversation.context.errorContext resolution encounters fetch failures

Subscribing

In the webhook destination form, use the Conversation error checkbox to subscribe to all four error types at once. Click Advanced to select specific error types individually.

Each error event type is independently subscribable via the eventTypes array — subscribe only to the types you care about.

Example payloads

conversation.execution.error

{
  "type": "conversation.execution.error",
  "timestamp": "2026-05-26T19:30:00.000Z",
  "tenantId": "tenant_123",
  "projectId": "proj_456",
  "agentId": "agent_789",
  "data": {
    "conversation": { "id": "conv_abc" },
    "reason": "Maximum error limit (3) reached"
  }
}

conversation.generation.error

{
  "type": "conversation.generation.error",
  "timestamp": "2026-05-26T19:30:00.000Z",
  "tenantId": "tenant_123",
  "projectId": "proj_456",
  "agentId": "agent_789",
  "data": {
    "conversation": { "id": "conv_abc" },
    "reason": "Generation terminated by timeout/abort signal"
  }
}

conversation.tool.error

{
  "type": "conversation.tool.error",
  "timestamp": "2026-05-26T19:30:00.000Z",
  "tenantId": "tenant_123",
  "projectId": "proj_456",
  "agentId": "agent_789",
  "data": {
    "conversation": { "id": "conv_abc" },
    "tool": { "id": "tool_123", "name": "search_docs" },
    "mcpServer": { "id": "mcp_456", "name": "docs-server" },
    "reason": "Connection timeout after 30s"
  }
}

conversation.context.error

{
  "type": "conversation.context.error",
  "timestamp": "2026-05-26T19:30:00.000Z",
  "tenantId": "tenant_123",
  "projectId": "proj_456",
  "agentId": "agent_789",
  "data": {
    "conversation": { "id": "conv_abc" },
    "contextDefinition": { "id": "ctx_def_123" },
    "reason": "HTTP 500 from upstream"
  }
}

Next steps