This page recommends the Autotouch CLI for the fastest execution path. Use the API reference when you need the raw HTTP contract.
What this is for
Inbound table webhooks are the low-friction ingest surface for pushing rows into a specific research table from external systems. Common examples are website visitor events, external intent providers, form fills, enrichment callbacks, and internal automation. They use a per-table token, not developer API key scopes.
If a provider emits company-level events separately from person-level events, use separate starter tables. Company events usually dedupe on domain or external account ID; person events usually dedupe on LinkedIn URL, email, or external person ID.
Setup flow
- With an authenticated API key or user session that can access the table, call
POST /api/tables/{table_id}/webhookto create or rotate the token. Developer-key writes usetables:write; reading config usestables:read. - Store the returned token securely. A rotation replaces the previous token; the full token is returned only when created or rotated.
- Configure duplicate handling with
PATCH /api/tables/{table_id}/webhook/settingswhen recurring events should update an existing row. - Send records to
POST /api/webhooks/tables/{table_id}/ingestwith headerx-autotouch-token. - Split the raw
webhook_payloadJSON into stable columns with projection columns before downstream enrichment.
CLI workflow
The CLI includes a scaffold for website visitor and external intent provider setup. It creates separate company/person starter-table instructions, webhook setup commands, ingest identity settings, and projection-column payloads.
autotouch workflows plan --type website_visitors
autotouch workflows scaffold --type website_visitors --out-dir autotouch-website-visitors
Use the generated projection payloads as starting points after you inspect the provider's first sample payload.
Example request
curl -X POST "https://app.autotouch.ai/api/webhooks/tables/<TABLE_ID>/ingest" \
-H "x-autotouch-token: <WEBHOOK_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"records":[{"first_name":"Ada","email":"ada@example.com"}]}'
Some webhook providers cannot send custom headers. In that case, use the compatibility query token form and treat the full URL as a secret:
curl -X POST "https://app.autotouch.ai/api/webhooks/tables/<TABLE_ID>/ingest?token=<WEBHOOK_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"event_type":"person_identified","email":"ada@example.com","linkedin_url":"https://www.linkedin.com/in/ada-lovelace"}'
Identity and duplicate handling
For event streams, configure the table to skip or upsert repeat events. match_rule_id must name a flat table column key available at ingest time; it cannot point to a nested path inside webhook_payload. Choose a supported match_strategy (domain, email, linkedin_url, external_id, or exact_text). If the provider only sends nested data, create or map a flat identity field before relying on upsert.
curl -X PATCH "https://app.autotouch.ai/api/tables/<TABLE_ID>/webhook/settings" \
-H "Authorization: Bearer stk_..." \
-H "Content-Type: application/json" \
-d '{
"match_rule_id": "linkedin_url",
"match_strategy": "linkedin_url",
"duplicate_mode": "upsert",
"merge_mode": "fill_empty"
}'
Recommended identity strategies:
- Company event table:
domainorcompany_domainwithmatch_strategy=domain. - Person event table:
linkedin_urlwithmatch_strategy=linkedin_url, oremailwithmatch_strategy=email. - Provider-owned IDs: use a stable
external_idfield withmatch_strategy=external_id.
Accepted payload shapes
- An array of objects.
{ "records": [...] }.{ "record": { ... } }.- A single object.
The HTTP body must be non-empty JSON, and every record must be an object; an empty array is rejected. A valid request to an invalid, missing, or deleting table is acknowledged with 202 and an ignored result.
Payload behavior
- Known keys map to matching table columns.
- Full raw payload is stored in the
webhook_payloadJSON column for later inspection. - New columns from mapped webhook fields are created only when the server setting
WEBHOOK_AUTO_CREATE_COLUMNS=true; event-stream tables disable this path. Plan the table schema instead of assuming every incoming key creates a column. - Use projection columns to split nested JSON fields into first-class table columns.
- Use table-side automation or downstream columns if the ingest event should trigger enrichment after insert.
