Ingress Webhooks
Ingress webhooks are the simplest inbound integration: create a webhook in the RocketLead console, get a unique URL + token, and POST JSON to it from any external system (Zapier, Make, n8n, custom backends, form vendors). Each POST creates a lead entry in the bound Lead Pool.
Use ingress webhooks when:
- You don’t want to manage a Bearer token (e.g., a no-code platform that doesn’t support custom auth headers).
- The sending system already has its own retry/idempotency story.
- You only need to push leads in — you don’t need to read or update existing data.
For richer integrations (read leads, create bookings, update lead state), use the Connect API.
Endpoint
Section titled “Endpoint”| Method | Path | Auth |
|---|---|---|
POST | /public/ingress_webhooks/:id | x-rocketlead-ingress-token header |
The :id is the UUID of the ingress webhook configured in the console.
Authentication
Section titled “Authentication”Send the token as a custom header:
POST /public/ingress_webhooks/<uuid>x-rocketlead-ingress-token: <64-hex-token>Content-Type: application/jsonThe token is a 64-character hex string. Anything missing or wrong returns 401 Invalid webhook token.
Issuing a webhook
Section titled “Issuing a webhook”In the RocketLead console:
- Go to Settings → Ingress Webhooks (or the dedicated section in the table).
- Click Create, pick the destination Lead Pool.
- Copy the URL and the token — the token is shown once.
Tokens can be rotated (which invalidates the old one) but can’t be retrieved after creation.
{ data: Record<string, string | string[] | null>; customFieldData?: Record<string, unknown>;}| Field | Notes |
|---|---|
data | Free-form. Becomes the lead entry’s data column. Schema is auto-inferred — first POST locks the inferred types per key. |
customFieldData | Optional. Validated against the org’s custom fields. Unknown custom-field IDs return 400. |
Example
Section titled “Example”curl -X POST https://api.rocketlead.io/public/ingress_webhooks/<uuid> \ -H "Content-Type: application/json" \ -H "x-rocketlead-ingress-token: <token>" \ -d '{ "data": { "firstName": "Maria", "lastName": "Schmidt", "email": "maria@example.com", "phone": "+49 30 1234567", "interest": "Anfängerkurs" }, "customFieldData": { "<custom-field-uuid>": "instagram_ad" } }'Response
Section titled “Response”The created TableEntry (full shape — see Connect API → Data Model → TableEntry):
{ "id": "<uuid>", "tableId": "<uuid>", "organizationId": "<uuid>", "data": {"firstName": "Maria", "...": "..."}, "leadStateId": "<uuid>", "createdAt": "2026-05-10T12:00:00Z"}Side effects
Section titled “Side effects”- A
tableEntriesrow is inserted into the bound Lead Pool. - The default lead state for that pool is applied automatically (must exist; otherwise the request is rejected with
400). table.entry.addedautomation event fires on commit.
See Automations → Triggers for the event catalog.
Schema auto-inference
Section titled “Schema auto-inference”The bound table’s schema is inferred from the first POST per key:
// First POST locks typesdata: { email: "x@x", age: 25, optedIn: true }// → tableSchema: { email: "string", age: "number", optedIn: "boolean" }
// Subsequent POSTs must matchdata: { email: 123 }// → 400: type mismatch — email expected string, got number| Source value | Inferred type |
|---|---|
| string | string |
| number | number |
| boolean | boolean |
| array of strings | string[] |
null | (skipped — doesn’t infer a type) |
If a value can’t be coerced to the existing type, the request fails with 400 and a typeErrors block describing the conflict.
Idempotency
Section titled “Idempotency”Every POST creates a new lead entry. There’s no built-in deduplication. If your sender retries on a transient failure, you’ll get duplicate leads.
Two practical options:
- Dedupe upstream — let the sender (Zapier, Make, etc.) ensure exactly-once delivery using their built-in retry semantics.
- Dedupe downstream — automate a “find duplicate by email/phone” step in your workflow that merges or skips dupes after the fact.
Errors
Section titled “Errors”| Status | Cause |
|---|---|
400 Validation failed | Body shape is wrong, custom field ID unknown, or schema type mismatch. |
400 No default lead state | The bound pool has no default leadStateId — set one in the console. |
401 Invalid webhook token | Missing or wrong x-rocketlead-ingress-token. |
404 Webhook not found | The :id doesn’t match any webhook in your org. |
500 | Internal — retry with backoff. |
Comparison: Ingress vs Connect API
Section titled “Comparison: Ingress vs Connect API”| Ingress | Connect API | |
|---|---|---|
| Auth | Custom header + URL secret | Authorization: Bearer rocketlead_* |
| Direction | Inbound only (push leads in) | Bidirectional (read/write) |
| Scopes | None — token = full pool access | read / write / admin |
| Setup | One webhook per pool, in-console | One token per integration |
| Best for | No-code platforms, simple lead push | CRMs, custom backends, complex sync |
| Schema | Auto-inferred per pool | Validated against shared schemas |
Related
Section titled “Related”- Connect API → Leads — the richer alternative for backends.
- Connect API → Data Model → TableEntry.
- Automations → Triggers —
table.entry.addedfires here too.