Boosterpack Forms

Documentation

Add a spam-protected form to any website in under 2 minutes.

Add a form to your site

Copy & paste — works with any HTML page

Perfect if you need a contact form for your website. Use our builder or bring your own HTML.

1
Sign in and head over to /account.
2
Click Create a new form, choose your fields, and set your destination email(s).
  • Each recipient gets a confirmation email — they must confirm before receiving submissions.
  • The first email you enter is the primary recipient (they also confirm new domains).
  • Recipients per form: 1 on Free, up to 5 on Personal, up to 10 on Professional+.
  • You can also add webhook integrations (Slack, Discord, etc.) alongside email.
3
Paste the form and script into your website:
1. Form HTML
Need a real form id? Get one here
<form method="POST" action="https://boosterpackforms.com/api/forms/<FORM_ID>/submit">
  <!-- your fields -->
  <input name="name" placeholder="Name" required />
  <input name="email" type="email" placeholder="Email" required />
  <textarea name="message" placeholder="Message" required></textarea>
  <button type="submit">Send</button>
</form>
2. Embed script
Paste once per page (in <head> or before </body>).
<script src="https://boosterpackforms.com/embed.js" defer></script>
<noscript>
  <p><strong>JavaScript is required</strong> for Boosterpack Forms spam protection (Proof-of-Work). Please enable JavaScript to use this form.</p>
</noscript>
Submission UX (embed.js)
  • On submit, it disables your submit button(s) and shows Sending….
  • On success, it clears the fields and briefly shows Sent! under the form.
  • You can hook into events: bpforms:sending, bpforms:success, bpforms:error.
<form
  method="POST"
  action="https://boosterpackforms.com/api/forms/<FORM_ID>/submit"
  data-bp-forms-success-message="Thanks!"
  data-bp-forms-success-timeout="2500"
  data-bp-forms-success-reset="true"
>
  <!-- your fields -->
</form>

<!-- Defaults: message="Sent!", timeout=2000ms, reset=true -->
4
Visit your site. You'll see an overlay with an Activate form button. Click it to activate the domain. The form goes live once at least one recipient has confirmed their email (from Step 2) and the domain is activated.

Works with any HTML form using method="POST", includes embed.js, and does not upload files.

Create forms via API

For platforms, site builders & automation

Ideal for apps provisioning forms for many end-customers dynamically.

1
Get an API key from /account. Keep it secure on your server.
2
Call POST /api/forms/provision with your API key to create forms programmatically.
curl -X POST "https://boosterpackforms.com/api/forms/provision" \
  -H "Authorization: Bearer $BPF_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "destinationEmails": ["owner@domain.com", "team@domain.com"],
    "webhookUrls": ["https://your-app.com/webhooks/forms", "https://hooks.slack.com/services/T.../B.../xxx"],
    "maxMessagesPerMonth": 5000,
    "receiverSummary": "Contact form for ACME Widgets (B2B SaaS)."
  }'
Provisioning API reference
Auth
  • Send Authorization: Bearer <API_KEY>.
  • Generate API keys in /account and keep them server-side.
Request body (JSON)
  • destinationEmails (optional*): array of email addresses to receive submissions (up to 5 on Personal, up to 10 on Professional+). Each recipient must individually confirm before receiving emails. Required unless webhookUrls is provided.
  • webhookUrls (optional*): array of webhook endpoint URLs. Supports Slack, Discord, Microsoft Teams, Google Chat, Telegram, and generic endpoints (auto-detected from URL). Requires Professional or Business plan.
  • destinationEmails omitted (behavior): if you provide webhookUrls without destinationEmails, the form delivers via webhook only (no email).
  • maxMessagesPerMonth (optional): per-form monthly cap on delivered submissions (email + webhook). If omitted, a server default is used. Strongly recommended for provisioners so a single abused customer site can't spike deliverability/costs.
  • receiverSummary (optional): short description of who receives these submissions / what the form is for (max 2000 chars). Used to improve spam detection context; not shown to end users.

* At least one of destinationEmails or webhookUrls must be provided.

Email confirmation
  • Each recipient email must individually confirm before it starts receiving submissions.
  • When provisioning via API, confirmation emails are not sent immediately. They are sent when a user clicks the Activate form overlay on the embedded site. When updating recipients via the API (PATCH), confirmation emails are sent immediately to newly added addresses.
  • The form becomes active once at least one recipient confirms. Additional recipients start receiving as they confirm.
  • The first email in the array is automatically marked as primary. The primary recipient receives domain activation notifications.
  • Recipients can unsubscribe via a link in each submission email.
Response
  • form.id: the provisioned form id (store this).
  • newWebhookSecrets (if webhooks configured): array of { url, secret, platform } for each webhook. Shown only once — store them securely.
  • urls.submit: where your HTML forms should POST.
  • urls.status: check if the form is active and allowed for the current host.
  • urls.requestActivation: request activation for the current host (sends an activation email and/or webhook event).
  • urls.embed: the embed script URL to include on pages with forms.
Manage a provisioned form
  • Update recipients: PATCH /api/forms/<formId> with JSON { "destinationEmails": ["a@b.com", "c@d.com"] }. New emails receive confirmation requests; removed emails are soft-deleted.
  • Update allowed domains: PATCH /api/forms/<formId> with JSON { "allowedHosts": ["example.com", "*.example.com"] }. Set to null to clear.
  • Disable: PATCH /api/forms/<formId> with JSON { "disable": true }.
  • Enable: PATCH /api/forms/<formId> with JSON { "enable": true }.
  • Delete (soft-delete): DELETE /api/forms/<formId>.

Multiple fields can be combined in a single PATCH request.

Common errors
  • 401 unauthorized: missing/invalid API key.
  • 400 invalid_body: JSON schema validation failed.
  • 403 plan_upgrade_required: provisioning is disabled on your plan.
  • 429 rate_limited: too many provisions in a short window; retry later.
Note: Provisioning creates recipient rows but does not send confirmation emails yet. Confirmation emails are sent when the Activate form overlay is triggered on the embedded site (or when recipients are updated via the API/dashboard). Submissions require a valid PoW solution (embed.js or @boosterpack/react-form handles this automatically) unless you submit manually and include valid PoW fields yourself.
3
Store the returned formId and inject the form action and embed.js into the sites you generate.
4
When the Activate form overlay is triggered on the embedded site, confirmation emails are sent to all recipients. The form goes live once at least one recipient confirms.

React integration

Use the official React package (no embed.js needed)

If you're building with React / Next.js, use @boosterpack/react-form. It handles Proof-of-Work, anti-spam hidden fields, and submission automatically.

Install
npm i @boosterpack/react-form
'use client'

import { BoosterpackForm } from '@boosterpack/react-form'

export function ContactForm() {
  return (
    <BoosterpackForm
      formId='<FORM_ID>'
      // serviceOrigin='http://localhost:3000' // optional for local/staging
      onSuccess={() => {
        // e.g. show a toast
      }}
      onError={(msg) => {
        // e.g. report to Sentry
        console.error(msg)
      }}
    >
      {({ status, error }) => (
        <>
          <input name='name' placeholder='Name' required />
          <input name='email' type='email' placeholder='Email' required />
          <textarea name='message' placeholder='Message' required />

          <button type='submit' disabled={status === 'sending'}>
            {status === 'sending' ? 'Sending…' : 'Send'}
          </button>

          {status === 'success' && <p>Sent. Check your inbox.</p>}
          {status === 'error' && error && <p>{error}</p>}
        </>
      )}
    </BoosterpackForm>
  )
}
Common gotchas
  • If you see not_activated or origin_not_allowed, request activation for your domain (see the Activation tab above).
  • For Next.js App Router, your form component must be a Client Component ('use client') since it uses hooks.
  • File uploads are not supported (forms must contain only text fields).

Custom Webhooks

Send submissions to your own endpoint with HMAC verification

Beyond native integrations, you can point a webhook at any URL you control. Boosterpack Forms sends a JSON payload on every submission and signs it with HMAC-SHA256 so you can verify authenticity.

How it works
  • Add any HTTPS URL as a webhook — via the dashboard or API.
  • We auto-detect known platforms (Slack, Discord, Teams, Google Chat, Telegram) from the URL and format messages natively. All other URLs are treated as generic webhooks.
  • Generic webhooks receive raw JSON with X-BoosterpackForms-Signature and X-BoosterpackForms-Timestamp headers for HMAC-SHA256 verification.
  • Platform webhooks do not include HMAC headers (those platforms don't support them).
  • You can mix platform and generic webhooks on the same form — up to 10 endpoints.
Payload format
  • event: "form.submission" or "form.activation_requested"
  • formId: your form id
  • fields: object of submitted field values (submission only)
  • submittedAt: ISO 8601 timestamp (submission only)
  • meta.host: the originating domain
Delivery
  • POST with Content-Type: application/json
  • Your endpoint must respond 2xx within 5 seconds
  • No automatic retries — if your endpoint is down, the delivery is lost (email delivery is unaffected)
Verifying signatures

Every generic webhook includes X-BoosterpackForms-Timestamp (unix seconds) and X-BoosterpackForms-Signature (sha256=...) headers. The signature is an HMAC-SHA256 digest of timestamp + "." + rawBody, signed with the webhook secret returned when you created the webhook.

import { createHmac, timingSafeEqual } from 'crypto'

function verifyWebhook(rawBody, signatureHeader, timestampHeader, secret) {
  const ts = String(timestampHeader || '').trim()
  const sig = String(signatureHeader || '').trim().replace(/^sha256=/, '')
  if (!ts || !sig) return false

  const signedContent = ts + '.' + rawBody
  const expected = createHmac('sha256', secret).update(signedContent, 'utf8').digest('hex')

  try {
    return timingSafeEqual(Buffer.from(expected, 'hex'), Buffer.from(sig, 'hex'))
  } catch {
    return false
  }
}

// In your webhook handler:
// IMPORTANT: rawBody must be the raw JSON string/bytes exactly as received.
const ok = verifyWebhook(
  rawBody,
  req.headers['x-boosterpackforms-signature'],
  req.headers['x-boosterpackforms-timestamp'],
  WEBHOOK_SECRET,
)
if (!ok) return res.status(401).send('Invalid signature')

Under the hood

Security, privacy, and billing — what happens behind the scenes

Invisible spam protection

Submissions pass through silent background checks — proof-of-work, honeypots, timing analysis, and AI scoring. Spam is blocked before delivery, and your visitors never see a CAPTCHA.

Nothing stored — ever

Submissions are forwarded and immediately discarded — never stored. Email addresses are encrypted at rest (AES-256-GCM), never plain text. No breach risk, no DPA needed, simplified GDPR/CCPA compliance.

Domain activation

Forms only accept submissions from approved domains. The first time a form loads on a new site, the owner confirms it via email — preventing anyone from using your form ID on their own site.

Recipient confirmation

Every email recipient must confirm before receiving submissions — no one gets subscribed without consent. Anyone can unsubscribe at any time from any form.

Delivered-only billing

Your quota only counts messages that pass all spam checks and are actually delivered to you. Blocked spam never touches your limit — you only pay for legitimate submissions.

Webhooks & integrations

Send submissions to Slack, Discord, Teams, Telegram, or any custom URL. Platforms are auto-detected and formatted natively — custom endpoints receive HMAC-signed JSON.