Vibha's data and monitoring platform · vibha.org

Integrations

Data can leave this platform in two directions. A webhook is Vibha pushing — the moment a form is submitted, it posts the response straight to a URL you control, unasked. An API key is the reverse — a credential you hand to another system so it can come and pull data on its own schedule. Both are Admin-only, because both can move every response your organization collects to somewhere outside it.

Which one do you actually need?

Think of a webhook as giving a courier your address so a package is delivered the instant it arrives, instead of you walking to the post office every hour to check. Nobody has to ask; Vibha simply tells your system “a new response just came in” as it happens.

An API key is closer to a library card: it lets an outside system — a script that runs every night, a reporting dashboard, a data warehouse — come in and read (or export) what it is entitled to, whenever it chooses to look. Nothing is pushed to it; it has to ask.

Use a webhook when something else needs to react immediately to a new response. Use an API key when something else just needs to read data on its own timetable.

Setting up a webhook

Webhooks are configured per form, not for the whole organization at once — a webhook you add only ever sends that one form's submissions. If you want several forms to push data out, each gets its own webhook.

  1. 1Go to Integrations and choose the form under Form at the top of the page.
  2. 2Click Add webhook, pick a destination — a plain HTTPS endpoint you run yourself, or a Slack/Google Chat incoming webhook URL (see below) — and give it a name and the URL that should receive submissions.
  3. 3Tick which events it should fire for: a new response, a status change, or a deletion. Pick only what the receiving side actually needs to act on.
  4. 4For a plain HTTPS endpoint, you are shown a signing secret exactly once, at creation. Copy it into whatever is receiving the webhook right away — it is encrypted at rest afterwards and cannot be displayed again. If it is lost, rotate it for a new one rather than trying to recover the old value. Slack and Google Chat destinations skip this step: nothing on their end verifies a signature.

Alerting Slack or Google Chat instead

If what you actually want is a message in a channel rather than data landing on your own server, choose Slack or Google Chatas the destination instead of a plain HTTPS endpoint. There is no server to run and no secret to manage — paste the platform's own incoming webhook URL and a short message is posted there for each event you ticked.

PlatformWhere to get the URL
SlackSlack → Apps → Incoming Webhooks → add a new webhook for a channel.
Google ChatOpen the space → ⚙ (space settings) → Apps & integrations → Webhooks → create one.

Sending responses straight to a Google Sheet

Two ways in, both appending one row per event to a spreadsheet you own — pick whichever fits how your team already works.

DestinationBest for
Google SheetsOne sheet at a time, from anyone — no Google Workspace connection needed, just a quick share.
Google Sheets (my Drive)An organization that has already connected Google Workspace (for Calendar/Docs/Slides) and would rather point at a sheet already in that Drive than share each one individually.

Choose Google Sheets as the destination to have each event appended as a new row in a spreadsheet you own — no code, no API key of your own, no OAuth login to click through.

  1. 1Open the sheet you want responses in, and copy its URL from the address bar.
  2. 2In the Add webhook dialog, choose Google Sheets, paste that URL, and note the service-account email address shown underneath it.
  3. 3Share the spreadsheet with that email address, giving it Editoraccess — the same way you'd share it with a colleague. Nothing is readable or writable until you do this.

The first response creates a header row automatically. From then on, columns only ever get added, never reordered or removed — if the form gains a question later, a new column appears for it the next time someone answers it, and every earlier row simply has a blank cell there.

Google Sheets (my Drive)skips the sharing step entirely: instead of a service account, it authenticates as your organization's own connected Google account — the same one-time Connect Google Workspaceused by Calendar/Docs/ Slides below. Paste the URL of a sheet already in that account's Drive and it's ready; everything else — the header row, new columns appearing automatically — works identically to the sharing-based version above.

Sending WhatsApp alerts

Choose WhatsAppas the destination to send a message on your own organization's WhatsApp Business number for each event. This is a heavier setup than Slack, Google Chat, or Google Sheets — WhatsApp only allows pre-approved, templated messages, and you need your own Meta developer setup already in place before you start here.

Before you start, you need, from Meta's own Business Manager:

  • A WhatsApp Business Account and a phone number connected to the Cloud API.
  • That phone number's phone number ID (a numeric id, not the phone number itself) and a permanent access token for it.
  • At least one message templatealready approved by Meta — this app cannot create, preview, or submit one for approval; that happens entirely on Meta's side.
  1. 1In Add webhook, choose WhatsApp, then fill in the phone number id, the template's language code (e.g. en_US), the exact template name, and paste the access token.
  2. 2List recipients as phone numbers with country code (e.g. +919876543210), separated by commas or one per line. Each one must already have messaged this WhatsApp number, or opted in some other way Meta recognises — WhatsApp's own policy, not something this app can change.
  3. 3Add one parameter for each {{n}} placeholder your template actually has, in order — the form title, the event, a status, or the answer to one specific question.

Connecting to Zapier, Make, or n8n

These are “connect anything to anything” tools — thousands of other apps, no code required. There isn't a dedicated ImpactLens app listed inside any of them yet, but you don't need one: all three can trigger straight off a plain HTTPS webhook, which is exactly what Add webhook already gives you today.

ToolWhat to add on their side
ZapierA Zap that starts with the Webhooks by Zapier trigger, using Catch Hook. Zapier gives you a URL — that's what you paste in as the webhook destination here.
MakeA scenario that starts with a Custom webhook module. Click Add to generate its URL, then paste that in here the same way.
n8nA workflow that starts with a Webhook trigger node, set to receive a POST. Copy the URL it shows you. Unlike the other two, n8n can be run on a server Vibha already controls, at no per-automation cost — worth it if a tech volunteer is available to set it up.

Booking Calendar events, or filling in Docs/Slides

Google Calendar + Meet, Google Docs, and Google Slidesare the three destinations that share a single organization-wide connection instead of their own credentials — connect it once, and every form's webhooks of these kinds use it.

  1. 1On Integrations → Webhooks, click Connect Google Workspace and approve access with whichever Google account should own the calendar events and documents these create.
  2. 2Add a webhook and choose one of the three destinations — each is greyed out until the step above is done.

Google Calendar + Meet. Pick a Datequestion on the form to supply the event's day — there is no separate time-of-day question type in this app, so the time is one value you set once when configuring the webhook, not something a respondent picks. Optionally invite the respondent as an attendee, from an Email question, and add a Google Meet link automatically.

Google Docs / Google Slides. Point at a Doc or Slides file you already have — each response makes its own copy, the template is never changed. List the placeholders your template actually contains (e.g. {{student_name}}) and what fills each one: the form title, the event, a status, or the answer to a specific question.

Verifying a delivery is genuinely from Vibha

This section covers a plain HTTPS endpoint only — Slack and Google Chat destinations are not signed; see the previous section.

Anyone can send a POST request to your endpoint pretending to be Vibha — the source address alone proves nothing. What actually proves a request is authentic is the signature: a code computed from the request's exact contents and your secret, which only the two of you know. If even one character of the payload changes, or the secret used does not match, the signature will not check out.

Each request carries three headers alongside the JSON body:

HeaderWhat it holds
X-FormBuilder-Signaturet=<timestamp>,sha256=<hmac> — see below.
X-FormBuilder-EventOne of submission.created, submission.updated, or submission.deleted — matches the event field in the body exactly, and matches whichever events you ticked when setting the webhook up.
X-FormBuilder-DeliveryA unique id for this exact delivery — shared across every retry of the same event, so it doubles as an idempotency key. See "Handling a delivery more than once" below.
hmac_sha256(secret, `${timestamp}.${rawBody}`)

The signature is computed over the timestamp and the exact raw request body, joined with a dot — not just the body on its own. Signing the timestamp too means a captured, genuine request cannot be replayed later; it will carry a timestamp your endpoint should recognise as stale.

  1. 1Read t and sha256 out of the X-FormBuilder-Signature header.
  2. 2Recompute the same HMAC yourself, using your stored secret and the exact raw body you received.
  3. 3Compare your result against sha256 using a constant-time comparison, not plain string equality — an ordinary comparison can leak how many leading characters matched through timing, which is information an attacker can use to guess the rest.
  4. 4Reject the request if t is too far in the past — a few minutes of tolerance is normal. This is what stops a captured, validly-signed request from being replayed against you a week later.

What to expect from delivery

AspectWhat actually happens
RetriesA non-2xx response, a timeout, or a connection failure is retried automatically, on a growing delay — 5 minutes, 30 minutes, 2 hours, 6 hours, then 24 hours — so a receiver that is down for a deploy or a restart still gets the event once it is back.
After the last retry failsYour organization's admins get a notification that this webhook is failing and why. The webhook itself stays on — the next submission gets its own fresh set of retries, in case the problem was temporary.
After 10 failures in a rowThe webhook switches itself off and admins are told why. Fix the destination, then turn it back on from Integrations — this also resets the failure count, so it is not disabled again after only a couple of new failures.
RedirectsNever followed automatically. A 3xx response counts as a failed delivery, the same as an error would.
OrderingNot guaranteed. Two submissions can be delivered out of order under load — use the submission’s own timestamp in the payload to sequence them, not the order requests arrived in.

Why your endpoint has to look a certain way

A webhook makes Vibha's own servers reach out to a URL you supply — which means a badly-restricted webhook could be turned into a way of probing your infrastructure from the inside. A few requirements exist purely to close that off:

  • Must be a public https:// address — no internal hostnames, no bare IP ranges reserved for private networks, no unusual ports commonly used by databases or internal services.
  • Checked again at the moment of every single delivery, not just when you first save the URL. A hostname that resolves publicly today but gets quietly repointed at an internal address next month (known as DNS rebinding) is caught the next time it would have fired, not just once at setup.
  • Must return a 2xx status to count as delivered. Anything else is a failure and is retried.

Reading data out instead: API keys

Where a webhook pushes data to you the moment it exists, an API key is what you hand to something that needs to pull data on its own — a nightly script that syncs responses into a data warehouse, say, rather than reacting to each one individually.

  1. 1Go to Integrations and click Create API key — this is organization- wide, unlike a webhook, so there is no form to choose first.
  2. 2Give it a name that says what it is for (“Nightly export script”, not “key 1”) and choose its scopes — exactly what it is allowed to do, and nothing more.
  3. 3Optionally set an expiry date. A key with no expiry is valid until someone revokes it.
  4. 4The full key is shown exactly once, immediately after creation. Copy it into whatever will use it right away — like a webhook secret, it cannot be displayed again.
ScopeWhat it allows
forms:readRead form definitions and questions.
forms:writeCreate and update forms.
submissions:readList and read responses.
submissions:exportDownload full response exports.
submissions:aggregateRead grouped counts and averages only — never a single response or a respondent field, whatever is asked for. Safe to hand to a wider audience than the scopes above.

Other routes out, for a one-off

Neither a webhook nor an API key is the right tool for a single, one-time need. For a one-off analysis, export straight from Responses as CSV or Excel instead of standing up an integration for it. And for reference data flowing the other way — a list of schools from your own system, feeding a dropdown here — upload it as an dropdown list rather than an API integration; see Dropdown lists.