Integrations
Point Clerk or Auth0 webhooks at Invoance and every organization in your app gets signed audit events, with no code of your own.
Clerk
One Svix-signed event per delivery: organizations, memberships, roles, sessions and users.
Set up ClerkAuth0
Log stream batches checked by a static token: sign-ins, signups, password and email changes.
Set up Auth0Create the source
In the dashboard open Audit Logs, then Integrations, then connect a provider. The webhook URL is shown once; the server stores only its SHA-256.
Point the provider at it
Clerk gets the URL and gives you a whsec_ signing secret. Auth0 gets the URL and the Authorization token you set on the source.
Every delivery is checked first
A Clerk delivery carries a Svix signature. An Auth0 delivery carries the token. Nothing is parsed before the check passes.
Events become audit events
Each mapped event goes through the same code as POST /v1/audit/events: envelope checks, quota, sequence number, Ed25519 signature.
/v1/integrations/webhooks/{token}Receive a provider webhook
Accepts one Clerk event or one Auth0 log batch, checks the provider's signature or token, maps each entry to an audit event and stores it as if it came from POST /v1/audit/events.
svix-idClerk: the Svix message id; used as the Idempotency-Key, so a redelivery never stores a second event.
svix-timestampClerk: unix seconds when Svix signed the delivery; rejected when more than 300 seconds from server time.
svix-signatureClerk: space-separated v1,<base64> entries, each an HMAC-SHA256 over "{svix-id}.{svix-timestamp}.{body}" with the whsec_ secret; any entry that verifies is accepted.
AuthorizationAuth0: the token set on the log stream, compared after trimming with the token stored on the source.
tokenThe URL token minted when the source was created; the server stores only its SHA-256.
typeClerk: the event type, for example organizationMembership.created; a type not in the map is skipped.
timestampClerk: unix milliseconds, stored as occurred_at; when missing or invalid the receive time is used.
dataClerk: the object the event is about; an organization, membership, session or user.
[].log_idAuth0: the log entry id; used as the Idempotency-Key for that entry. An entry without one is skipped.
[].data.typeAuth0: the tenant log code, for example s or fp; a code not in the map is skipped.
[].data.dateAuth0: stored as occurred_at; when missing or invalid the receive time is used.
- No API key: the URL token identifies the source and the provider's signature (Clerk) or token (Auth0) authenticates the delivery. No SDK calls this endpoint; the provider does.
- Each Clerk event and each Auth0 entry is capped at 64 KB. A whole delivery is capped at 1 MB and a larger body gets a plain 413 before the handler runs.
- Auth0 entries are handled one by one: a permanent skip is counted per entry, and one transient entry fails the whole batch with 500 so Auth0 replays it. Entries that already landed are deduplicated by log_id.
- Every delivery that passes the auth check counts toward the source's events_received, one per Auth0 entry. Skips count toward events_skipped and use no quota.
- The last 50 skips per source are kept for 7 days with the reason, the delivery id and the organization, and shown in the dashboard. Payloads are never stored.
# An Auth0-shaped test delivery: a JSON array of log entries.
# Clerk deliveries are signed by Svix and cannot be hand-built.
curl -X POST https://api.invoance.com/v1/integrations/webhooks/$WEBHOOK_TOKEN \
-H "Authorization: $AUTH0_STREAM_TOKEN" \
-H "Content-Type: application/json" \
-d '[{
"log_id": "90020260922081407412000000000000000000000000000000000000",
"data": {
"type": "s",
"date": "2026-09-22T08:14:07.412Z",
"user_id": "auth0|66f1c2d3e4a5b6c7d8e9f0a1",
"user_name": "ada@acme.com",
"ip": "203.0.113.7",
"user_agent": "Mozilla/5.0",
"org_id": "org_5xK2mQ9pL3nR8vT1",
"org_name": "Acme"
}
}]'
{
"received": true,
"accepted": 1,
"skipped": 0
}
receivedAlways true on a 200.
event_idClerk only: the aevt_ id of the stored audit event.
acceptedAuth0 only: entries in the batch that were stored.
skippedAuth0: entries in the batch that were skipped. Clerk, or a whole delivery that was skipped: the reason, for example unmapped_type.
invalid_signatureClerk: a svix header is missing, the timestamp is outside the 300 second window, or no v1 signature matches.
invalid_authorizationAuth0: the Authorization header is missing or does not match the token on the source.
unknown_sourceThe token is not 20 to 128 characters, or no source has it, including a deleted one.
rate_limitedMore than 50 deliveries in one second, or 3,000 in one minute, reached this source; Retry-After says how long to wait.
quota_exceededThe monthly audit event quota is used up; the provider's retry schedule is the backoff.
transientThe database, the queue or the secret store failed; the provider retries and the idempotency key stops duplicates.
| Organization | Clerk: the organization on the event. Auth0: org_id and org_name on the entry. A source that auto-creates makes a new organization under that name, up to the plan's audit org cap (set by plan; seeded as developer 2, builder 1,000, growth 3,000, compliance 10,000, enterprise unlimited). |
|---|---|
| Allowlist mode | With auto-create off, an event for an organization you did not create is skipped as org_not_found. |
| Org-less events | orgless_policy skip, the default, skips them. catch_all routes them to the organization named in catch_all_external_id. |
| Paused source | A paused source answers 200 with skipped set to paused, so the provider keeps the endpoint. Resume from the dashboard. |
| Secret roll | Set a new signing_secret on the source when the provider rotates it. The URL and the idempotency scope stay the same. |
| Quota | Only stored events count against the monthly audit event quota. The organization is resolved before the quota check, so a skip is free. |
A skip answers 200 with skipped set to one of these reasons. The provider does not retry, and nothing is billed.
| Reason | Meaning |
|---|---|
paused | The source is paused. |
provider_not_supported | The source's provider is not clerk or auth0. |
unmapped_type | The Clerk event type or Auth0 log code is not in the provider's map. |
invalid_payload | The body is not JSON, a Clerk envelope has no type or data, or an Auth0 entry has no log_id or type. |
payload_too_large | One Clerk event or one Auth0 entry is over 64 KB. |
orgless | The event names no organization and the policy is skip, or catch_all names no organization. |
org_cap | Auto-create would exceed the plan's audit org cap. |
org_archived | The organization is archived; unarchive it to resume. |
org_not_found | Auto-create is off and the organization does not exist. |
invalid_event | The mapped event failed the audit envelope checks, for example a field over its limit. |
<ingest error code> | Any other validation error from the audit ingest core, recorded under that error code. |