App integration · All integrations

Connect Stripe to Formfy

You collect payment in Stripe, then manually email the client a waiver or intake form, wait for a signature, then schedule the appointment. For clinics, fitness studios, and service agencies this cycle runs dozens of times a week. A receptionist copies email addresses, attaches PDFs, and chases signatures — all while matching paperwork to the right transaction. At volume, things get lost. An unsigned waiver attached to a paid booking is a liability that only surfaces when something goes wrong.

Formfy's public REST API lets your server call POST /api/v1/forms/{id}/send the moment Stripe fires checkout.session.completed. The client receives their intake form by email or SMS before they've closed the payment confirmation tab — and Formfy delivers the signed PDF to your system the moment they complete it.

The workflow at a glance

Trigger

A customer completes a Stripe payment (checkout.session.completed fires)

Action

Your server calls Formfy's sendForm API with the customer's email or phone number

Result

Client signs the intake form; the signed PDF lands in your Formfy dashboard and your webhook endpoint automatically

Step-by-step: connect Stripe to Formfy

Wire Stripe checkout webhooks to Formfy's sendForm API and automatically deliver intake, consent, or waiver forms to every paying customer.

  1. Generate a Formfy API key

    Open the Formfy dashboard, navigate to Settings → API Keys, and click Create key. Save the fk_live_… token to a password manager — Formfy shows it once. Use fk_test_… during development and testing so you do not consume plan send-credits against real clients before the integration is live.

  2. Create or locate your Formfy intake form

    In Formfy, build or choose the intake, consent, or waiver form you want to send after payment. Use POST /api/v1/forms to programmatically create a form from a template, or copy the form id from the dashboard URL. You will pass this id to the sendForm endpoint in the next step.

    POST/api/v1/formsSee in the OpenAPI spec →

  3. Register a Stripe webhook for checkout.session.completed

    In your Stripe dashboard, go to Developers → Webhooks → Add endpoint. Point it at your server route — for example /api/stripe-webhook — and select checkout.session.completed. Stripe POSTs a HMAC-signed payload there every time a payment succeeds. Verify the Stripe-Signature header in your handler before processing to block spoofed requests.

  4. Call Formfy's sendForm endpoint from your handler

    Once you have verified the Stripe event, extract the customer email from event.data.object.customer_details.email and POST /api/v1/forms/{id}/send with your Bearer token. Formfy queues the delivery and the client receives the form link by email — or SMS if you pass a phone number — within seconds of payment clearing.

    POST/api/v1/forms/{id}/sendSee in the OpenAPI spec →

  5. Subscribe to Formfy's form.signed event

    POST /api/v1/webhooks with event_types: ["form.signed"] and your callback URL. When the client signs, Formfy delivers a payload containing signer_email, submission_id, and signed_at to your endpoint. Store the submission_id alongside the Stripe payment_intent so you can reconcile signed paperwork to the right payment in a single query.

    POST/api/v1/webhooksSee in the OpenAPI spec →

  6. Download the signed PDF for your records

    After form.signed fires, call GET /api/v1/forms/{id}/signed-pdf to retrieve the completed document. Attach it to the Stripe customer record, push it to your document storage, or forward it to your front desk. The file includes a full signing audit trail — timestamp, IP address, and signer identity — suitable for both compliance and client recordkeeping.

    GET/api/v1/forms/{id}/signed-pdfSee in the OpenAPI spec →

  7. Rotate your webhook secret on schedule

    Quarterly — or after any suspected credential leak — POST /api/v1/webhooks/{id}/rotate-secret to get a fresh Formfy signing secret. Update the value in your environment variables or secrets manager alongside your Stripe webhook secret in the same deployment to prevent a gap where deliveries arrive without a valid signature.

    POST/api/v1/webhooks/{id}/rotate-secretSee in the OpenAPI spec →

Send a Formfy intake form after a Stripe checkout.session.completed event

After verifying Stripe-Signature, extract the customer email and call Formfy's sendForm endpoint. The client receives the form link within seconds of payment clearing.

curl -X POST https://formfy.ai/api/v1/forms/frm_YOUR_FORM_ID/send \
  -H "Authorization: Bearer fk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "client@example.com",
    "message": "Thanks for your payment — please complete your intake form before your appointment."
  }'

Frequently asked questions

Does Formfy have a built-in Stripe connector?

Formfy does not have a point-and-click Stripe connector today. Instead, you wire the two systems via Formfy's public REST API: when Stripe fires checkout.session.completed to your server, your handler calls POST /api/v1/forms/{id}/send with the customer's email. Setup takes roughly 15 minutes and works without a third-party automation platform — you only need a server-side webhook route and a Formfy API key.

Which Stripe events should I use to trigger a form send?

checkout.session.completed is the most reliable trigger for one-time payments and fires immediately after the customer pays. For recurring subscriptions, customer.subscription.created fires when a plan activates. For invoice-driven workflows, invoice.paid covers both initial and renewal charges. Choose the event that best aligns with when you want the client to receive their intake or consent form.

How do I match a signed Formfy form back to its Stripe payment?

When you call POST /api/v1/forms/{id}/send, store the Stripe PaymentIntent or session ID in your own database keyed on recipient email plus the timestamp of the send call. When form.signed fires, the payload includes submission_id — look that up against your stored record to link the signed document to the originating payment without any extra Formfy configuration.

Can Formfy send forms by SMS after a Stripe payment?

Yes. POST /api/v1/forms/{id}/send accepts a phone field alongside or instead of email. Pass the customer's mobile number in E.164 format — for example +14805550123 — and Formfy delivers the form link via SMS. Recipients can open and sign the form on any mobile browser without downloading an app or creating a Formfy account.

What happens if the client never signs the intake form?

Formfy fires a form.expired event when an unsigned form times out. Add "form.expired" to the event_types array in your POST /api/v1/webhooks subscription alongside "form.signed". Use the expiry event to trigger a follow-up in your system — flag the Stripe customer, alert your front desk, or queue a reminder — so no unsigned intake form quietly disappears after a paid booking.

How do I verify the Formfy webhook signature in my Stripe handler?

Formfy signs every delivery with HMAC-SHA256 using a secret returned when you create the subscription via POST /api/v1/webhooks. The computed signature arrives in the X-Formfy-Signature header. In your handler, recompute HMAC-SHA256(secret, raw_body) and compare it to the header value before processing. The pattern is identical to Stripe's own Stripe-Signature verification — you can reuse the same HMAC utility in the same route.

Is the Formfy API available on the free trial?

Yes. The Formfy public REST API is available on every paid plan and during the 15-day free trial. Generate a fk_test_… key during the trial to prototype the full Stripe → Formfy → signed PDF flow before upgrading. Rate limits scale with your plan tier — check the X-RateLimit-Remaining and X-RateLimit-Reset response headers in any API call to monitor your current quota.

Can I send a different intake form for each Stripe product?

Yes. Maintain a map of Stripe product_id or price_id to Formfy form_id on your server. When checkout.session.completed fires, look up the product the customer purchased and call POST /api/v1/forms/{form_id}/send. A fitness membership, a spa treatment, and a consulting package can each route to their own intake or consent form with no extra Formfy configuration beyond that lookup table.

Ready to wire Stripe into Formfy?

Spin up an API key, run your first webhook, and route signed forms wherever your team already works.