Developer docs

Keepp for Zapier: API reference

Keepp is a website and link-in-bio builder for creators and small businesses, with a store, bookings, forms and chat on one page. Keepp’s Zapier app sends the people who buy, book or fill in a form on that page to any app in Zapier, each tagged with what they bought, booked or filled in. This page documents the API the app uses.

Setting up a Zap rather than building one? Follow the step-by-step guide.

Triggers

New PurchasepurchaseSomeone ordered one of the page's products: paid, confirmed or fulfilled.
New BookingbookingSomeone booked one of the page's offerings, confirmed or completed.
New Form ResponseformSomeone filled in one of the page's forms. Choose one form, or leave it empty for every form. A form that asks the visitor to confirm their email triggers only once they have.

Every trigger asks which Keepp page it is for. Sending contacts needs the page to be on Pro or Influencer.

Authentication

OAuth 2.0 authorization code flow with PKCE (S256). The Zapier app is a public client: no client secret is issued or needed.

AuthorizeGEThttps://api.keepp.link/oauth/authorize
TokenPOSThttps://api.keepp.link/oauth/token (authorization_code and refresh_token grants)
DiscoveryGEThttps://api.keepp.link/.well-known/oauth-authorization-server
client_idstringkeepp-zapier
scopestringcontacts:read: read the page's contacts and send new ones to Zapier.
resourcestringhttps://api.keepp.link/zapier. Tokens are minted for this resource and are accepted nowhere else in Keepp.

The person signs in to Keepp with an email code or Google and approves the connection on Keepp’s consent screen. Access tokens last 1 hour; refresh tokens last 90 days from their last use and are replaced on every refresh. A token answers for the person who signed in: every call is checked against the pages they belong to.

Authorization: Bearer <access token>

To disconnect, the page owner chooses Disconnect on Zapier’s card under Connectors in their Keepp dashboard. That switches off every Zap for the page and signs Zapier out, so Zapier asks them to reconnect before any Keepp Zap runs again.

Endpoints

Base URL https://api.keepp.link/zapier. Every response is JSON.

{ "ok": true, "data": … }
{ "ok": false, "error": { "code": "…", "message": "…" } }
GET /me

The signed-in person: { id, email }. Zapier labels the connection with the email.

GET /pages

The pages the person belongs to: [{ id, name, slug }]. Fills the page dropdown.

GET /forms?page=<page id>

The forms on that page: [{ id, title }]. Fills the form dropdown on New Form Response.

GET /contacts?page=<page id>&event=<purchase|booking|form>&formId=<form id>

Up to 3 recent contacts for that trigger, newest first, in the same shape a live one arrives in. Zapier shows them as samples while a Zap is set up. formId is optional.

POST /hooks

Switches a Zap on. Body { page, event, formId?, targetUrl }. targetUrl must be a Zapier hook address (https://hooks.zapier.com/…). Returns { id }.

DELETE /hooks/:id

Switches a Zap off. A Zap already switched off returns { id, archived: false } rather than an error.

How contacts arrive

These are REST hooks. When a contact matches a live Zap’s trigger, page and form, Keepp POSTs it as JSON to the Zap’s targetUrl, within moments. Keepp sends only to Zapier’s own hook addresses. A send that fails is tried 3 times in all, with a growing wait between tries. If Zapier answers 410 Gone, the Zap is switched off on Keepp’s side and nothing more is sent to it.

The contact

Every trigger sends the same shape, plus a part for its own kind.

{
  "id": "8d3f4e6a-1c5f-4b7d-9e2a-3f4c5d6e7f8a",
  "source": "form",
  "email": "sam@example.com",
  "name": "Sam Rivera",
  "phone": "+15550100",
  "tags": ["form-lead", "form:Join the waitlist", "page:mirastudio"],
  "page": "mirastudio",
  "createdAt": "2026-11-08T10:00:00.000Z",
  "form": { "title": "Join the waitlist" },
  "answers": [
    { "label": "Your name", "value": "Sam Rivera" },
    { "label": "Email", "value": "sam@example.com" }
  ]
}
idstringThe purchase, booking or form response id. Use it to deduplicate.
sourceenum"purchase" | "booking" | "form"
emailstringThe person's email address.
namestring?Their name, when they gave one.
phonestring?Their phone number, when a form asked for one.
tagsstring[]Ready-made tags for an email list (below).
pagestringThe page's handle, as in keepp.link/<handle>.
createdAtstringWhen it happened, ISO 8601 in UTC.
purchaseobjectOn a purchase only.
bookingobjectOn a booking only.
formobjectOn a form response only: { title }.
answersobject[]What they answered, as [{ label, value }]: a form's questions, or the questions asked at checkout or when booking.
"purchase": {
  "product": "Glaze workshop",
  "quantity": 1,
  "amount": "$45.00",
  "amountMinorUnits": 4500,
  "currency": "USD"
}
"booking": {
  "offering": "Wheel class",
  "startAt": "2026-11-12T17:00:00.000Z",
  "endAt": "2026-11-12T18:30:00.000Z"
}

Tags

buyerpurchaseBought something.
bookedbookingBooked something.
form-leadformFilled in a form.
product:<title>purchaseThe product they bought.
offering:<name>bookingThe offering they booked.
form:<title>formThe form they filled in.
page:<handle>allThe page it came from, for owners with more than one page.

Errors

  • 401 invalid_token: no token, an expired or revoked one, or one minted for another part of Keepp.
  • 403 insufficient_scope: the token lacks contacts:read.
  • 403 PLAN_REQUIRED: the page isn’t on Pro, so a Zap can’t be switched on for it.
  • 404 CONTACT_SYNC_PAGE_NOT_FOUND: no such page, or the person doesn’t belong to it.
  • 400 CONTACT_SYNC_INVALID_EVENT: the trigger isn’t purchase, booking or form.
  • 400 CONTACT_SYNC_INVALID_FORM: the form is no longer on the page.
  • 400 CONTACT_SYNC_INVALID_HOOK_URL: targetUrl isn’t a Zapier hook address.
  • 429 invalid_request: more than 60 requests in a minute on one token.

Support

Questions about the integration or this API: vas@keepp.link. Keepp’s other APIs, the MCP server and the Agent API, are on the developer docs.