HookGet Open dashboard

Events in, not just out

Connect Stripe, your email provider, your CRM, your automations and your LLM spend — and get one stream of verified, normalised events through the same pipeline that already delivers your webhooks. Same retries, same timeline, same replay.

In short

  • A source brings events in; an endpoint sends them out. Both share one pipeline.
  • Push sources (Stripe, SendGrid, GoHighLevel, n8n, Postmark) are verified at the door — signature over the raw bytes, before anything is stored.
  • Pull sources (OpenAI, Anthropic) are read on a schedule with a cursor: token usage and cost per model become events.
  • Connectors normalise: payment.succeeded with amount_cents, not a vendor-flavoured blob. Unmapped events pass through rather than being dropped.
  • Existing sources keep their old event names — canonical naming applies only to sources created from now on, so no filter breaks.
Push and pull sources feeding one pipeline Push sources such as Stripe, SendGrid, GoHighLevel and n8n send signed webhooks that are verified at the door. Pull sources such as OpenAI and Anthropic are read on a schedule by HookGet, with a cursor. Both normalise into the same event store, fan out to the same destinations, and appear on the same delivery timeline. They call you Stripe · SendGrid · GHL · n8n Verified signature, raw bytes We call them OpenAI · Anthropic usage APIs Scheduled cursor · backoff · budget Normalised one event model Delivered same pipeline same retries · same timeline · same replay · same metering
Two ways in, one pipeline out. A Stripe payment, a bounced email and an hour of Claude usage become the same kind of event — filtered, delivered, retried and replayed exactly like the ones you publish yourself.

The catalogue

ProviderKeyModeVerified byWhat it produces
StripestripePushHMAC signaturepayment, refund, invoice, subscription, dispute
GoHighLevelgohighlevelPushEd25519 / RSAlead, deal, appointment
SendGridsendgridPushECDSA P-256email delivered, opened, clicked, bounced
PostmarkpostmarkPushShared tokenemail delivered, bounced, complained
n8nn8nPushShared tokenworkflow run succeeded / failed
TwiliotwilioPushHMAC signatureinbound calls, missed calls, SMS
Meta Lead Adsmeta-leadsPushHMAC signatureleads from Facebook & Instagram forms
OpenAIopenaiPullAdmin keytokens and cost per model, hourly
AnthropicanthropicPullAdmin keyClaude tokens and cost per model, hourly
Google Analytics 4google-analyticsPullService accountdaily users, sessions, page views
Search Consolegoogle-search-consolePullService accountdaily clicks, impressions, position
Meta Adsmeta-adsPullAccess tokendaily spend, impressions, clicks, reach
TikTok Adstiktok-adsPullAccess tokendaily spend, impressions, clicks, reach

Alongside these, 15 inbound providers — GitHub, Shopify, Standard Webhooks, Alibaba EventBridge and more — are verified at the door and passed through under their own topic names. Verification always happens before an event exists.

How an inbound webhook is verified before it enters A provider sends a signed request. HookGet verifies the signature or token and deduplicates on the provider's delivery id before the event exists. A request that fails verification is refused with a 401 and never enters the pipeline. A verified event flows into the same pipeline as any other: retries, timeline, replay. The provider GitHub, Stripe, 13 more Verified at the door signature or token · dedupe The same pipeline retries · timeline · replay Refused bad signature → 401, nothing enters
Verification happens before the event exists, so a forged request is refused at the door — it is never stored, never retried, never seen again. Redeliveries are deduplicated on the provider’s own delivery id.

One envelope, whatever the provider

Each connector extracts the same canonical shape, stored beside your payload — never inside it, so the bytes a signature covers and the body your consumers receive are untouched.

"eventType": "payment.succeeded" Canonical, not vendor-flavoured — one alert covers every payment provider
"occurredAt": "2026-08-20T18:20:00.000Z" When it happened at the source. receivedAt is kept separately — provider delays stay visible
"entity": {"type":"customer","id":"cus_9"} Who or what it is about. Identifiers live here, never in attributes
"attributes": {"provider":"stripe","currency":"usd"} Only things you would group by. Ids, emails and URLs are refused by name
"metrics": {"amount_cents":4299} Finite numbers only, unit in the name. All money in cents, whatever the provider reports
"privacy": {"classification":"confidential","containsPii":true} Declared per event. The default is the strictest class, on purpose
The envelope a connector extracts, stored beside your payload — never inside it, so the bytes a signature covers and the body a consumer receives are untouched.

All money is in cents. Stripe reports cents, GoHighLevel reports whole currency units, Anthropic reports cents as a decimal string. Each connector converts at its own boundary, so amount_cents means one thing everywhere — a cross-source number you cannot trust is worse than no number.

Connect one in three steps

StepPush sourcePull source
1Create the source — you get an ingest URL and a secretCreate the source with the provider credential
2Paste the secret into the provider's webhook settingsChoose the interval (default 5 minutes) and how far back to backfill (up to 90 days)
3Events arrive, verified and normalisedThe first sync runs immediately; health is reported per source
curl -X POST https://api.hookget.com/v1/sources \
  -H "authorization: Bearer $HOOKGET_KEY" \
  -H "content-type: application/json" \
  -d '{"provider":"stripe","name":"prod payments"}'

# {"id":"src_…","secret":"whsec_…","ingest_path":"/ingest/src_…","mode":"push"}

Stated plainly

FactWhy it is this way
Pull syncs skip the most recent ~90 minutesProviders keep writing into the current bucket; reading it early would double-count the same hour on the next sync.
A failed sync keeps its old cursorA cursor advanced mid-failure silently skips events. Re-reads are free — the provider’s own delivery id deduplicates.
A source failing 20 syncs in a row pauses itselfRetrying a revoked key every five minutes, forever, gets us rate-limited by the provider in your name.
Postmark and n8n are token-verified, not signedNeither offers payload signing. We state the strongest verification that exists rather than implying one that does not.
GoHighLevel verification proves the sender, not the accountGHL signs with one key pair for all its customers. Filter on locationId if the distinction matters to you.

Questions

What is an event source?

The inverse of an endpoint. An endpoint is somewhere HookGet delivers to; a source is somewhere HookGet gets events from — a SaaS that sends webhooks, or an API we read on a schedule. Once an event is in, it takes exactly the same path as one you publish yourself: the same fan-out, signatures, retries, dead-letter queue and metering.

How is this different from the 15 inbound providers you already had?

Those verify a provider's signature and pass the body through under the provider's own topic name — github.push, shopify.orders.create. They still work, unchanged. The seven connectors on this page additionally normalise: a Stripe payment_intent.succeeded becomes payment.succeeded with the amount as a metric in cents and the customer as an entity, so one filter or one alert covers every payment provider you connect.

Will canonical names break my existing filters?

No. A source created before connectors existed keeps emitting the provider-flavoured names your filters already match — that behaviour is pinned per source, in the database, not in your configuration. Only sources created from now on default to canonical names, and you can choose either at creation with event_naming.

What happens to an event type you have not mapped?

It keeps the provider's name and flows through anyway. Stripe alone has several hundred event types; the mapped set covers what a revenue pipeline needs, and everything else arrives as stripe.<their name> rather than being dropped. Losing your charge.dispute.created because we had not mapped it yet is a failure mode this design refuses.

Where do the events go?

Anywhere HookGet delivers: HTTPS endpoints, queues and buses (SQS, EventBridge, Kafka, RabbitMQ, Pub/Sub), S3-compatible storage, or a polling cursor. Filters and transformations apply per destination, so the same payment.succeeded can hit your warehouse in full and your Slack alert as three fields.