Lua/Honeycomb

Connectors & Webhooks

Wire GitHub, Slack, CRMs, ticket trackers, and your own systems into Honeycomb with signed webhooks and authenticated push endpoints — then watch source health live.

Honeycomb gets more useful the more of your organization's activity flows into it. Connectors are how that happens: point your tools' webhooks at your Honeycomb deployment, and every commit, conversation, deal, and ticket becomes searchable, permission-aware memory — automatically normalized, deduplicated, and scoped to the right people.

At a glance

  • GitHub and Slack have dedicated signed webhook endpoints — no API key in the URL; each request is verified with an HMAC signature before anything is stored.
  • CRMs, ticket trackers, and email-style payloads push to POST /api/v1/webhook/:source with your hck_... API key.
  • Your own systems can push anything via POST /api/v1/ingest — see Ingesting Data.
  • Every record carries a stable external reference, so webhook redeliveries and record updates never create duplicates — updates supersede older versions in place.
  • Access is inherited from the source: public channels and repos become org-readable; private channels are scoped to their members; emails are scoped to their recipients. When in doubt, Honeycomb fails closed to private.
  • Prefer one click? An org admin can connect a whole company's CRM, Linear, or Slack from the Lua app with no webhook setup — and Lua CRM feeds memory natively with zero setup at all — see Company Connections.
  • Monitor everything with GET /api/v1/sources/health or the Sources page in the console.

How live data flows in

Entry pointAuthBest for
POST /api/v1/webhook/githubHMAC signature (webhook secret)GitHub repos and orgs
POST /api/v1/webhook/slackHMAC signature (signing secret)Slack workspaces
POST /api/v1/webhook/:sourceAuthorization: Bearer hck_...CRM records, tickets, email, anything else
POST /api/v1/ingestAuthorization: Bearer hck_...Direct pushes from your own pipelines

Once normalized, everything downstream is identical regardless of source — the same search, Ask, and Spaces behavior applies to a Slack thread and a CRM deal alike.

GitHub

Set it up

  1. Get your deployment's GitHub webhook secret. It's configured on your Honeycomb deployment when the connector is enabled — generate a strong random string and set it during onboarding (your Lua contact can confirm it's in place).
  2. In GitHub, go to your repository or organization Settings → Webhooks → Add webhook.
  3. Set Payload URL to https://YOUR_HONEYCOMB_HOST/api/v1/webhook/github.
  4. Set Content type to application/json.
  5. Paste the same secret into the Secret field.
  6. Choose Let me select individual events and pick: Pushes, Pull requests, Issues, Issue comments, Pull request reviews.
  7. Save. GitHub sends a ping event; Honeycomb acknowledges it and you'll see a green checkmark in GitHub's recent deliveries.

Every delivery is verified against the X-Hub-Signature-256 header using a constant-time comparison. Requests with a missing or invalid signature are rejected with 401.

Note: If the endpoint returns 503 with Webhook verification not configured, the webhook secret hasn't been set on your deployment yet — finish step 1 first.

What lands in memory

GitHub eventStored asWhat Honeycomb extracts
PushCommit recordsCommit authors as people, the repo, who works on what
Pull requestPull request recordTitle, body, assignees and requested reviewers as people
IssueTicket recordTitle, body, assignee, labels as tags
Issue commentMessage recordComment text in context of its issue
PR reviewCode review recordReview body and verdict

Events outside these five are still accepted (and acknowledged) but stored as low-fidelity generic records — which is why we recommend selecting individual events rather than "send me everything."

Visibility and access

  • Public and internal repos are treated as org-visible: anyone in your organization can retrieve their content.
  • Private repos fail closed: content is ingested but scoped privately, since the webhook payload doesn't carry a collaborator roster.

Slack

Set it up

  1. Create a Slack app for your workspace (or reuse an existing one) at api.slack.com.
  2. From the app's Basic Information page, copy the Signing Secret and configure it on your Honeycomb deployment (same onboarding path as the GitHub secret).
  3. Under Event Subscriptions, enable events and set the Request URL to https://YOUR_HONEYCOMB_HOST/api/v1/webhook/slack. Honeycomb answers Slack's URL-verification challenge automatically, so the URL verifies immediately.
  4. Subscribe to bot events: message.channels, message.groups, message.im, message.mpim (pick the subset you want captured).
  5. Install a bot token with read scopes on your deployment as well — this is what lets Honeycomb resolve user IDs to names, stitch threads together, and read private-channel membership.
  6. Install the app to your workspace and invite the bot to the channels you want remembered.

Every event is verified with Slack's v0 HMAC scheme (X-Slack-Signature + X-Slack-Request-Timestamp), with a five-minute replay window — stale or unsigned requests get 401.

Threads become living memories

Slack conversations evolve, and Honeycomb tracks that instead of storing a pile of fragments.

Each reply re-ingests the whole thread as one transcript and supersedes the previous version — so search always finds the current state of the conversation, never a stale fragment. Deep entity and fact extraction waits for a quiet period (about 30 minutes of no new replies by default) so a busy thread is enriched once, not on every message.

People and privacy

  • User mapping is automatic. Slack user IDs resolve to real names and profile emails, and feed Honeycomb's identity graph — so "what did Priya say about the migration?" works even though Slack only sent U04AB12CD. The same graph links a person's Slack identity to their email and GitHub identity across sources.
  • Public channels are org-visible: anyone in your organization can retrieve their content.
  • Private channels are scoped to their member roster — Honeycomb reads the membership and grants retrieval to exactly those people. In very large private channels, grants cover the first 200 members.
  • When privacy can't be determined (for example, the bot token is missing), Honeycomb fails closed and keeps the content private.

Warning: Without a bot token, threaded messages degrade to standalone messages and user/channel IDs are stored raw (U04AB12CD instead of names). The connector still works, but recall quality drops noticeably — install the bot token.

Generic webhooks: CRM, tickets, email

POST /api/v1/webhook/:source is the authenticated catch-all for everything that isn't GitHub or Slack. Unlike the two signed endpoints, it uses your normal API key:

Authorization: Bearer hck_your_api_key

Three source names get first-class structured parsing. Anything else is accepted as free-form.

PathPayload shapeStored as
/api/v1/webhook/emailfrom, to, cc, subject, body, messageId, threadId, dateEmail — readable only by the people on it
/api/v1/webhook/crmrecordType, id, name, fields, platform, updatedAtCRM record with deal, owner, and account entities
/api/v1/webhook/ticketkey, summary, description, status, assignee, reporter, priority, labels, project, platform, updatedAtTicket with assignee and project entities
any other nameFree-form JSON — text pulled from text, body, content, or messageGeneric record tagged with your source name

Example: push a CRM deal

Works for any CRM — set platform to identify yours:

curl -X POST "https://YOUR_HONEYCOMB_HOST/api/v1/webhook/crm" \
  -H "Authorization: Bearer hck_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "recordType": "deal",
    "id": "deal-88412",
    "name": "Northwind Traders - Enterprise Renewal",
    "platform": "hubspot",
    "updatedAt": "2026-07-07T09:14:00Z",
    "fields": {
      "stage": "negotiation",
      "amount": 84000,
      "owner": "Maya Chen",
      "account": "Northwind Traders",
      "close_date": "2026-08-15"
    }
  }'

Honeycomb extracts the deal, its owner, and the account as linked entities, and records each field as a fact on the deal — so stage and amount are queryable, not just full-text-searchable. When the deal changes, push it again with the same id: the update supersedes the old version.

Response (201 Created):

{
  "id": "km_9f3c2e71",
  "chunksCreated": 1,
  "entitiesExtracted": 3,
  "factsRecorded": 4,
  "extractionTier": 1
}

Example: push a ticket

curl -X POST "https://YOUR_HONEYCOMB_HOST/api/v1/webhook/ticket" \
  -H "Authorization: Bearer hck_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "ENG-1432",
    "summary": "Checkout latency spikes above 2s at peak",
    "description": "p95 latency regressed after the cache change...",
    "status": "In Progress",
    "priority": "High",
    "labels": ["performance", "checkout"],
    "assignee": { "name": "Diego Ramos" },
    "reporter": { "name": "Sam Okafor" },
    "project": { "name": "Payments", "key": "PAY" },
    "platform": "linear",
    "updatedAt": "2026-07-07T08:02:11Z"
  }'

Anything else: the firehose

Unknown source names are accepted too — Honeycomb pulls the best available text and tags the record with your source name:

curl -X POST "https://YOUR_HONEYCOMB_HOST/api/v1/webhook/statuspage" \
  -H "Authorization: Bearer hck_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "text": "Incident resolved: API error rate back to baseline as of 09:40 UTC." }'

This is a great starting point for a new integration — you can graduate to fully structured pushes via Ingesting Data later without changing anything downstream.

Push from your own systems

If you control the sender, you don't need a webhook shape at all — call POST /api/v1/ingest with content, metadata, and optional pre-extracted entities. It also auto-detects the structured payloads above, and an X-Source header (for example X-Source: crm) forces a specific interpretation when a payload is ambiguous. Full details, including audience scoping and extraction tiers, live in Ingesting Data and the API Reference.

Monitoring source health

The health endpoint

curl "https://YOUR_HONEYCOMB_HOST/api/v1/sources/health" \
  -H "Authorization: Bearer hck_your_api_key"
{
  "sources": [
    {
      "source": "slack",
      "count": 1423,
      "lastSeen": "2026-07-07T09:12:44.000Z",
      "enrichment": { "complete": 1390, "pending": 21, "failed": 12 },
      "backlog": 33
    },
    {
      "source": "github",
      "count": 611,
      "lastSeen": "2026-07-07T08:55:10.000Z",
      "enrichment": { "complete": 611 },
      "backlog": 0
    }
  ],
  "totalBacklog": 33,
  "generatedAt": "2026-07-07T09:15:00.000Z"
}
FieldMeaning
sources[].countTotal records ever ingested from this source
sources[].lastSeenTimestamp of the most recent record — your freshness signal
sources[].enrichmentRecords by processing status (complete, pending, failed)
sources[].backlogRecords still pending or failed
totalBacklogBacklog summed across all sources

Two things to watch: a stale lastSeen on a source that should be chatty means deliveries stopped (check the webhook config on the sender's side), and a growing backlog means ingestion is outpacing enrichment.

Warning: The GitHub and Slack webhook endpoints deliberately return 200 even when processing fails internally — this prevents the provider from hammering your deployment with redeliveries. Don't monitor connector health via webhook HTTP status codes; monitor lastSeen and backlog here instead.

The Sources page in the console

The console gives you the same picture visually. Open Sources in the sidebar:

  • Overview tab — enrichment throughput plus per-source cards showing volume, last-seen, and backlog at a glance.
  • Documents tab — browse individual ingested documents with their full provenance: which source, which channel, when, and what was extracted.

Troubleshooting

SymptomLikely cause
503 Webhook verification not configuredThe GitHub or Slack secret isn't set on your deployment yet
401 Missing signature / 401 Invalid signatureSecret mismatch between the sender and your deployment — re-paste it on both sides
401 Request too old (Slack)Delivery arrived more than 5 minutes after signing — usually clock skew or a slow proxy in front of your deployment
Slack messages stored with raw IDs like U04AB12CDBot token missing — names, threads, and private-channel scoping all need it
GitHub deliveries show green but nothing appearsEvent type isn't one of the five structured kinds, or check backlog on the health endpoint
Duplicate-looking recordsUsually not duplicates — check for differing external references; true redeliveries are deduplicated automatically

Next up: control who can retrieve what with Spaces & Permissions, or start asking questions with Ask.