Quickstart
This page walks you through the fastest possible integration smoke test: register your system as a producer in the Kudos CRM operator console, copy the issued signing secret, sign a webhook.ping event, and POST it. You will know the integration is wire-correct when the operator console shows your event in the inbound stream.
The whole path is browser + one HTTP request. No SDK, no library, no toolchain.
1. Register a source in the CRM

A Kudos CRM operator with the admin role goes through this once per producer system.
- Open the operator console
Sign in at
https://app.kudoscrm.comand open Integrations → Inbound sources (direct path/integrations/sources). - Register
Click Register source. Fill in:
- Name — internal label, e.g.
Kudos Billing Production. - Producer — your system name, e.g.
Kudos. - Sync base URL —
https://api.your-system.example/api/v1(skip if you are not implementing the pull channel yet). - Allowed event types — keep the default (all 36) or narrow down.
- Name — internal label, e.g.
- Copy the signing secret
A modal appears with the signing secret cleartext. This is the only time it will be displayed. Click Reveal, then Copy, then tick I have stored this credential securely, then Done.
- Note the source_id
The new source row shows a
src_…identifier. Copy it — it is part of your delivery URL.
You now have:
source_id— looks likesrc_AbCdEf0123456789abcdef01. Public-ish — not a credential, but unguessable.signing_secret— looks likewhsec_…. Treat like a database password. Store in your secret manager.
2. Sign and send your first event
Kudos CRM requires every webhook to carry an HMAC signature over the raw request body plus a unix timestamp. The header format is identical to Stripe's:
X-Kudos-Signature: t=<unix_seconds>,v1=<hex_hmac>
Pick a language and run the snippet. Substitute the placeholders:
BODY='{"schema_version":1,"event_id":"evt_'"$(uuidgen | tr -d - | head -c 25)"'","event_type":"webhook.ping","fired_at":"'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'","producer":{"name":"kudos","version":"1.0.0"},"tenant":null,"data":{"hello":"world"}}'
TS=$(date +%s)
SECRET='whsec_REPLACE_ME'
SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | sed 's/^.* //')
curl -sS -X POST \
-H "Content-Type: application/json" \
-H "User-Agent: Kudos-Webhook/1.0.0 (+https://kudos.example)" \
-H "X-Kudos-Signature: t=$TS,v1=$SIG" \
-H "X-Kudos-Event-Id: $(echo "$BODY" | python3 -c 'import json,sys;print(json.load(sys.stdin)["event_id"])')" \
-H "X-Kudos-Event-Type: webhook.ping" \
-H "X-Kudos-Schema-Version: 1" \
-H "X-Kudos-Delivery-Attempt: 1" \
-d "$BODY" \
https://api.kudoscrm.com/api/v1/ingest/webhooks/src_REPLACE_ME/events
A successful POST returns 202 Accepted with a small JSON envelope:
{ "data": { "received": true, "event_id": "evt_…", "duplicate": false } }
duplicate: true is returned when you replay an event_id Kudos CRM has already processed — that is intentional, not an error. The integration is idempotent on event_id. Always retry on 5xx; never invent new event_ids when retrying.
3. Verify in the operator console
The CRM operator can verify the event arrived by:
- Navigating to Integrations → Inbound sources.
- Clicking the row → Last event updates to "a few seconds ago".
- The inbound-events drawer lists the
webhook.pingevent with statusprocessed.
Where to go next
The full signing reference: header parsing, multi-secret rotation, timing-safe compare.
The closed catalog of 36 events with payload examples.
Why we send the same event_id up to eight times, and what your handler should do.
For the pull channel and reverse-channel inbox.