← All articles

Webhook In: POST records straight into a table

A Webhook In endpoint is a URL that files JSON POSTs into one table — Email In for machines. RowFold publishes the exact format on the endpoint's page, using the table's own field keys, so anything that can send an HTTP POST can create records: a script, a payment provider's custom action, an automation tool, ten lines of your own code. What it is Create an endpoint from a table's view bar (the Channels group) or from Channels → Add a channel, and you get a URL. Every JSON POST to it becomes a record of that table, immediately — no automation to build and no mapping to configure, because the payload's keys are the table's field keys. Records created this way are ordinary records: AutoNumber stamps them, automations and outgoing webhooks fire for them, live grids pick them up, and the audit log names the endpoint that filed each one. The format is published, not guessed The endpoint's page writes out the exact body to send — a real example built from the table's live schema, with a copy button and a ready-made curl line. It is one JSON object: an optional displayName (left out, the record is named after the first field's value, the same convention as the grid) and a values object keyed by field key. It is the same envelope as POST /api/v1/tables/{id}/records, so a sender that outgrows the endpoint moves to the REST API without reshaping its payload. Bad payloads are refused loudly: a 400 with a problems list naming each unknown key, unwritable field or malformed date — and nothing partial is stored. A retried POST carrying an Idempotency-Key header replays the original answer instead of filing twice. What a POST may write Any field a person could type into — including AI fields, which store text like any other. Computed fields (Lookup, Rollup, Formula, AutoNumber) have no stored value to write, attachments only move through their own upload endpoints, a Doc is written on its own page, and a field governed by a lifecycle or approval policy is refused here for the same reason Email In refuses to map one: an anonymous URL must not move records through states. The endpoint's page lists exactly which fields are out, and why, under the example. Relation values are record ids. Every id is checked against the relation's own target table before anything is stored — a guessed or foreign id links nothing, and the POST is told so. People values name members of the workspace, each by email address or by person id — an array, or just one. An address is matched against the workspace's members, ignoring case, and stored as that member's id, so a sender that only knows who it means by address can still assign them. A name, an address or id that isn't a member's, or an address two members share is refused rather than stored, and the POST is told which field. Security The URL is unguessable and acts as the credential — treat it like a password. Pausing the endpoint makes the URL answer 404 until you resume it; deleting it is permanent, though the records it created are untouched. For senders that can compute an HMAC, tick Require signatures: each POST must then carry X-RowFold-Signature: t=<unix seconds>,v1=hex(HMAC_SHA256(secret, "<t>.<body>")) with the timestamp within five minutes, and anything unsigned or mis-signed gets a 401. It is the exact scheme RowFold's outgoing webhooks sign with, so one implementation covers both directions. The secret can be rotated at any time — that is the leak response — and rotation only breaks senders while enforcement is on. POSTs are rate-limited per sender address, and a body is capped at 128 KB. Webhook In or an automation webhook? Same transport, opposite contracts. Webhook In publishes RowFold's format for one table and the sender conforms — right whenever you control the sender. An automation webhook accepts whatever shape the sender dictates (Stripe, a form tool) and the automation's steps reshape it with {{webhook.…}} tokens, run conditions, and can do things other than create a record. Pasting a URL into a system whose payload you can't change? Use the automation. Writing the sender yourself? Use this. Tips • The example on the endpoint's page is generated from the table's live schema — copy it as-is and it posts successfully, which makes it the fastest smoke test. • Send an Idempotency-Key header from anything that retries — the same key and body replays the first answer instead of creating a duplicate record. • Left out, displayName is taken from the first field's value — the first field is the record's label, same as everywhere else in RowFold. • Point the endpoint's watchers at whoever owns the intake — machine-created records otherwise arrive silently. Good to know • A paused endpoint answers 404, exactly like a URL that never existed — a sender can't tell the difference, so pause with intent. • Renaming a field changes nothing (keys are stable), but deleting a field makes payloads that still send its key fail with a 400 naming it. • The whole POST is refused when any field in it is refused — nothing partial is stored. That is the contract working: an integration must hear “no”, not discover half a record later. • Turning “Require signatures” on refuses unsigned POSTs immediately — hand the sender the secret and the scheme first.
Nothing here answered it? Ask us directly — we usually reply within one working day.

Made with RowFold