SheetLink Formsbeta

Developer docs

One endpoint per form. Five ways in: an HTML form action, JSON, the sl.js embed, platform webhooks, or email. Everything lands in your connected Google Sheet.

Quick start: plain HTML

Point any form at your endpoint. No JavaScript required.

<form action="https://sheetlinkforms.com/f/YOUR_TOKEN" method="POST"> <input type="text" name="name" placeholder="Name"> <input type="email" name="email" placeholder="Email"> <textarea name="message"></textarea> <input name="_slhp" tabindex="-1" autocomplete="off" style="position:absolute;left:-9999px"> <button type="submit">Send</button> </form>

The browser is 303-redirected to your form's redirect URL (or a hosted thank-you page). Field names that match your sheet's column headers map automatically - "Email", "email", and "E-mail" all match an "Email" column. The hidden _slhp input is the spam honeypot: keep it in, leave it empty.

JSON API

POST https://sheetlinkforms.com/f/YOUR_TOKEN Content-Type: application/json {"name": "Ada", "email": "ada@example.com", "message": "Hello"} -> 200 {"ok": true, "id": "..."}

Requests with Content-Type: application/json or Accept: application/json get a JSON response instead of a redirect. Multipart is accepted too (file parts are dropped in the current release). Bodies are capped at 256 KB. Errors: 404 unknown token, 410 paused form, 403 origin not allowed or challenge failed, 413 too large, 429 rate limited (per-form and per-IP), 400 unreadable body. Delivery to the sheet is asynchronous with automatic retries (5 min, 30 min, 2 h).

sl.js embed

<script src="https://sheetlinkforms.com/sl.js" data-token="YOUR_TOKEN"></script>

Add once per page. It binds any <form data-sheetlink> and upgrades any form whose action already points at your endpoint:

  • AJAX submit with inline success/error text - no page reload
  • Ad attribution: utm_*, gclid, wbraid, gbraid, fbclid, msclkid captured from the URL and persisted across pages - add matching columns to receive them
  • Page URL, referrer, and a bot-timing signal (stored as submission metadata)
  • Honeypot injected automatically
  • SPA-safe: late-rendered forms are bound via MutationObserver

Form attributes: data-sheetlink="slf_..." (bind + per-form token), data-redirect (navigate on success), data-success-message (inline text). Events: sheetlink:success and sheetlink:error bubble from the form with details in event.detail.

Webflow & Framer webhooks

Webflow: https://sheetlinkforms.com/w/webflow/YOUR_TOKEN Framer: https://sheetlinkforms.com/w/framer/YOUR_TOKEN

Webflow: Site settings -> Integrations -> Webhooks -> Add webhook, trigger type "Form submission", paste the URL - one webhook covers every form on the site, and the originating form name is stored with each submission. Framer: set the Form component's submission destination to Webhook and paste the URL. Both v2 and legacy Webflow payloads are handled.

Email-in

YOUR_TOKEN@sheetlinkforms.com

The catch-all: point any system's notification email at your form's address and lines shaped Label: value become fields; when nothing parses, the subject, sender, and body are stored so the lead is never lost.

For IT admins: Microsoft 365 approval

If your organization requires admin approval for new apps, an Entra admin can grant SheetLink org-wide consent in one step - after that, users connect their Microsoft account without an approval prompt:

https://sheetlinkforms.com/api/hosted/oauth/microsoft/admin-consent

What you are approving: app "SheetLink", application (client) ID 27b7f757-de78-4806-a92a-c4e50572a825. Delegated permissions only - Files.ReadWrite (write rows to the workbook the user picks), User.Read (show which account is connected), offline_access (keep delivering while the user is offline). No application-level (app-only) permissions, no admin data access. All SheetLink traffic to Microsoft originates from the static egress IP 69.197.187.14 if you allowlist outbound integrations. Refresh tokens are stored AES-256-GCM encrypted and are revocable at any time from your tenant's Enterprise applications blade or the SheetLink dashboard.

Code snippets

fetch (browser or edge)

await fetch("https://sheetlinkforms.com/f/YOUR_TOKEN", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name, email, message }) });

Node.js

const res = await fetch("https://sheetlinkforms.com/f/YOUR_TOKEN", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: "Ada", email: "ada@example.com" }) }); const { ok, id } = await res.json();

PHP

wp_remote_post("https://sheetlinkforms.com/f/YOUR_TOKEN", [ "headers" => ["Content-Type" => "application/json"], "body" => wp_json_encode(["name" => "Ada", "email" => "ada@example.com"]), ]); // or plain PHP: curl / file_get_contents with a JSON POST

curl

curl -d "name=Ada" -d "email=ada@example.com" https://sheetlinkforms.com/f/YOUR_TOKEN

Spam handling & control fields

Every submission passes rate limits, an origin allowlist (when configured), the honeypot, and content heuristics tuned by your form's strictness dial. Suspicious submissions are quarantined for review in the dashboard, never silently dropped - approving one delivers it. Reserved field names (stripped from your sheet, used by the pipeline):

FieldPurpose
_slhpHoneypot - must be present and empty; bots that fill it are marked spam
_sl_elapsed_mssl.js timing signal (load-to-submit)
_sl_pageSubmitting page URL (stored as metadata)
_sl_referrerPage referrer (stored as metadata)
cf-turnstile-responseCloudflare Turnstile token, when the challenge is enabled

SheetLink Forms beta - sign in · privacy