Skip to main content

How webhooks work

Webhooks send HTTP POST requests to your server when events occur in Inbox — a new message arrives, a thread is assigned, a campaign target replies, and more. Instead of polling the API for changes, register a webhook URL and Inbox pushes events to you as they happen.
Your server ◀── POST /your-webhook ── Inbox
Configure webhooks in Settings → Webhooks in your Inbox dashboard. You choose which event types each webhook receives.

Event envelope

Every webhook delivery wraps event-specific data in a consistent envelope:
id
string
required
Unique event ID. Use this to deduplicate deliveries.
seq
number
required
Monotonically increasing sequence number per team. Use this to detect missed events and maintain ordering.
teamId
string
required
The team this event belongs to.
type
string
required
The event type in resource.action format (e.g., thread.created, message.created).
timestamp
string
required
ISO 8601 timestamp of when the event occurred.
version
string
required
Schema version. Currently always "1.0".
data
object
required
The event payload. Structure varies by event type — see individual event pages for details.
{
  "id": "ck9v2m5nj0xp4wq7ybftrae8",
  "seq": 42,
  "teamId": "hzcai5t59nn9vsck3rbuepyg",
  "type": "thread.created",
  "timestamp": "2025-01-15T10:30:00.000Z",
  "version": "1.0",
  "data": {
    "thread": { "..." },
    "prospect": { "..." }
  }
}

Supported event types

Inbox supports 32 event types across 7 categories. Subscribe to individual events or entire categories.

Thread events

EventDescription
thread.createdA new thread is created
thread.deletedA thread is deleted
thread.assignedA thread is assigned to a team member
thread.unassignedA thread is unassigned from a team member
thread.archivedA thread is marked as done
thread.unarchivedA thread is reopened
thread.typingA prospect is typing in an X Chat thread

Message events

EventDescription
message.createdA message is sent or received
message.editedA message is edited
message.deletedA message is deleted
message.reactionAddedA reaction is added to a message
message.reactionRemovedA reaction is removed from a message

Prospect events

EventDescription
prospect.createdA new prospect is created
prospect.statusChangedA prospect’s pipeline status changes
prospect.tagsChangedTags are added or removed from a prospect
prospect.notesChangedA prospect’s notes are updated
prospect.valuationChangedA prospect’s valuation changes
prospect.enrichedA prospect is enriched with fresh platform data

Tag events

EventDescription
tag.createdA new tag is created
tag.updatedA tag is updated
tag.deletedA tag is deleted

Status events

EventDescription
status.createdA new pipeline status is created
status.updatedA pipeline status is updated
status.deletedA pipeline status is deleted

Campaign events

EventDescription
campaign.createdA new campaign is created
campaign.startedA campaign is started
campaign.pausedA campaign is paused
campaign.resumedA campaign is resumed
campaign.completedA campaign completes

Target events

EventDescription
target.contactedA campaign target receives the initial message
target.followUpSentA follow-up message is sent to a target
target.repliedA campaign target replies

Delivery behavior

Inbox attempts delivery once with no retries. Responses are not checked — delivery is fire-and-forget. Use the Events API to fetch any events your webhook missed. Events are retained for 7 days.

Handling webhooks

Your endpoint should:
  1. Deduplicate using event.id in case of rare duplicate deliveries
  2. Handle events idempotently
  3. Track the latest seq value so you can backfill missed events via the Events API
import express from 'express';

const app = express();
app.use(express.json());

app.post('/webhooks/inbox', async (req, res) => {
  const event = req.body;

  // Return 200 immediately
  res.sendStatus(200);

  // Process asynchronously
  switch (event.type) {
    case 'message.created':
      await handleNewMessage(event.data);
      break;
    case 'thread.assigned':
      await handleThreadAssigned(event.data);
      break;
    case 'prospect.statusChanged':
      await syncProspectToCRM(event.data);
      break;
  }
});

app.listen(3000);

Events API

The Events API lets you replay events from the last 7 days. Use it to recover missed webhooks or backfill data.
cURL
curl "https://inboxapp.com/api/v1/events?afterSeq=0&limit=100" \
  -H "Authorization: Bearer $INBOX_API_TOKEN"
Response:
{
  "events": [
    {
      "id": "ck9v2m5nj0xp4wq7ybftrae8",
      "seq": 1,
      "teamId": "hzcai5t59nn9vsck3rbuepyg",
      "type": "message.created",
      "timestamp": "2025-01-15T10:30:00.000Z",
      "version": "1.0",
      "data": { }
    }
  ],
  "hasMore": true,
  "lastSeq": 100
}
ParameterTypeDescription
afterSeqnumberReturn events after this sequence number. Omit to start from the beginning.
limitnumberMaximum events to return. Default: 100, max: 1000.
Use lastSeq from the response as afterSeq in your next request to paginate through all events.
Store the last processed seq value persistently. Run a background job that periodically polls the Events API using your stored seq to catch anything your webhook handler missed.

Missed event recovery

import axios from 'axios';

const client = axios.create({
  baseURL: 'https://inboxapp.com/api/v1',
  headers: {
    'Authorization': `Bearer ${process.env.INBOX_API_TOKEN}`,
  },
});

async function syncMissedEvents(lastSeq: number): Promise<number> {
  let afterSeq = lastSeq;

  while (true) {
    const { data } = await client.get('/events', {
      params: { afterSeq, limit: 1000 },
    });

    for (const event of data.events) {
      await processEvent(event); // Deduplicate using event.id
    }

    if (!data.hasMore) {
      return data.lastSeq ?? afterSeq;
    }

    afterSeq = data.lastSeq;
  }
}

Next steps