Back to News & Insights
Web Development October 2, 2026 · 5 min read

Sending form submissions to Slack, Discord, Airtable and Notion

Every integration below has one setup mistake that returns success and delivers nothing. Here is each...

Sending form submissions to Slack, Discord, Airtable and Notion

Every integration below has one setup mistake that returns success and delivers nothing. Here is each one, how to spot it, and the webhook payload I ended up designing around them.

I build a form builder, Seagit Forms, and most of the support questions I get aren't about forms at all. They're about a response that should have landed in Slack or Notion and didn't, while every dashboard said it worked.

After wiring up nine destinations, I noticed a pattern. Each service has exactly one mistake that a careful, correct-looking setup still hits, and it never throws an error. No 4xx, no exception, no red banner. Just silence.

Here are the ones worth knowing, whether you use my tool, someone else's, or write the integration yourself.

You create a Slack app, add the chat:write scope, install it, copy the xoxb- bot token and a channel ID. You call chat.postMessage. Slack answers HTTP 200.

Slack returns errors in the body with a 200 status. A bot with chat:write can't post to a channel it hasn't joined. Two fixes:

or add the chat:write.public scope, which lets the bot post to any public channel without joining. Private channels always need the invite.

The rule: never check response.ok on a Slack call. Check body.ok. A client that only looks at the HTTP status reports success for every misconfiguration Slack has.

Also set text on every message, even when you use blocks. Slack uses it for the notification and sidebar preview; without it the message arrives but notifies with a blank line.

Discord channel webhooks are the easiest integration there is: one URL, no auth flow. POST JSON to it, get a 204.

Now Discord waits until the message is created and returns it as JSON, or returns a real error if it was rejected (an embed field over the length limit, for example). Without it, a message Discord refused looks exactly like one it posted.

Treat the webhook URL as a password, too. Anyone holding it can post to the channel.

Airtable's API matches fields by column name. If your payload has ten fields and one name doesn't match a column exactly, Airtable rejects the entire record, not just that field.

That makes renames dangerous. Someone tidies "Email address" to "Email" in the base, and from then on every submission is rejected.

What worked for me: Read the table's schema first. Send only fields whose names match a column. Surface the unmatched ones to the form owner as a warning, rather than failing.

Also: don't send "" for blank answers. An empty string into a date, number or single-select column is itself a rejection. Omit the field instead.

You create an internal integration, copy its token, copy your database ID from the URL, and call the API. Notion answers:

The database exists. It just isn't connected to your integration. In Notion, open the database, then ••• → Connections → add your integration. Notion deliberately reports "not found" instead of "forbidden" so it doesn't confirm the page exists, and that sends everyone after the wrong problem.

Want to discuss this further?

Book a free strategy call with our team to see how these insights apply to your specific business goals.

Book a consultation