Developer community

Build group checkout into your product.

Paywalla exposes a simple, secure API so booking systems, travel tools, event platforms and billing software can create and publish group checkouts on an organization's behalf β€” and let the platform handle splitting, invitations, payment and receipts.

Why integrate

Use cases & intended outcomes

Group checkout shines wherever one purchase is shared by several payers. Here are common integrations and the outcome each unlocks.

πŸŽ‰

Booking & reservation systems

When a customer books a venue, suite or rental for a group, auto-create a group checkout so each guest pays their share to your business directly β€” no more one person fronting the deposit.

🧳

Travel & itinerary platforms

Turn a confirmed itinerary into a collection plan. Publish a checkout per trip, assign amounts per traveler, and let the platform email every participant their pay link.

🏟️

Event & ticketing tools

Sell a table, suite or private experience to several attendees. Each pays their own share; you track group progress and issue individual receipts without a spreadsheet.

🏟️

Clubs, teams & leagues

Collect tournament fees, facility rentals and registration costs across every family in one link instead of chasing each one individually.

🀝

Invoicing & billing software

Add a 'split this invoice' action that creates a group checkout from an existing invoice, so clients can divide a bill among co-payers.

❀️

Nonprofit & fundraising platforms

Let a chapter or committee fund a shared initiative together β€” dues, donations and event costs collected straight to the organization.

🧾

Internal chargebacks & cost recovery

When one team or department fronts a shared cost β€” travel, event, equipment β€” create a group checkout to charge it back to every responsible party, each paying their share straight to the organization with a proper receipt.

Art of the possible

What this can become

Once group checkout is a first-class object in your product, a few new experiences open up β€” the kind that used to require custom payment infrastructure.

  • A reservation system that converts a confirmed booking into a split checkout automatically, so the host never waits on one person.
  • A trip-planner where 'invite the group' triggers collection the instant the itinerary locks β€” every traveler gets a pay link by email.
  • An event platform where a suite or table sponsor sends a single link and each seat is paid for by the person sitting in it.
  • A league management tool where one registration creates one checkout for the whole team's families, with progress everyone can see.
  • A billing product where 'split this invoice' turns a shared bill into per-payer links β€” each payer gets their own receipt.
Who integrates

Applications that might integrate

Booking & reservation systems

Hospitality, venues, vacation rentals and activity providers that already capture a group booking can attach a split-payment checkout to the reservation.

Travel management & itinerary tools

Planners and OTAs that assemble group trips can trigger collection the moment the itinerary is confirmed.

Event ticketing & registration platforms

Tools selling tables, suites, booths or group registrations can let co-attendees split the cost at the point of sale.

Invoicing, ERP & billing software

Accounting and billing products can offer 'split this invoice' as a one-click option for shared or co-funded bills.

Community, club & league management apps

Platforms running memberships and teams can automate collection of shared costs across member households.

Marketplaces & vertical SaaS

Any product serving groups that buy together can embed group checkout as a native payment flow.

Technical overview

Built for trust and reliability

Before you send a single payment request, it's worth knowing how the platform handles money, security and state β€” so you can integrate with confidence.

Direct charges via Stripe Connect

Every organization connects its own Stripe account. Payments are charged directly to that account β€” money never passes through or sits in the platform. The platform fee is taken as Stripe's application_fee_amount.

Webhooks are the source of truth

Payment status is never inferred from a page redirect. Stripe webhooks, verified against the raw body and unique event IDs, confirm every charge β€” so a checkout can't be faked by loading a success page.

Server-side financial operations

Creating, publishing, paying and refunding run in backend functions under a service role. The client never performs or alters a financial operation.

Secure, revocable links

Organizers and participants get high-entropy tokens instead of logins. Links are scoped and can be rotated. Participants never see each other's details.

Immutable at publish

The total, fee snapshot and allocation are locked when a checkout goes live, so what participants were shown is exactly what they pay.

Money stored in minor units

All amounts are integers (cents) in the database to avoid floating-point drift. The API accepts decimal major units (e.g. 1200.00) and converts them.

Row-level security

Each organization's checkouts, participants and contributions are scoped to the owner. API keys are stored as one-way SHA-256 hashes β€” a database read can't recover them.

Idempotent, auditable

Invitations only email never-before-sent participants. Every sensitive action writes an audit event, and financial events carry idempotency keys.

Before you code

Prerequisites & dependencies

The API is the last step. These have to be in place first β€” each lives in the organization's dashboard, not in your code.

  1. 1
    A registered organization owner

    Someone signs up and creates the organization. This account owns the Stripe connection and the API key β€” the API can't exist without it.

    Register β†’ Dashboard
  2. 2
    Completed organization profile

    Business name, support email, address, default currency and refund terms. The support email and address are snapshotted onto participant receipts at publish time, so set them first.

    Dashboard β†’ Settings
  3. 3
    Stripe connected and active

    The owner connects Stripe and finishes onboarding until card payments are active (status 'ready'). The API returns stripe_not_ready until this is done β€” no test charge will go through without it.

    Dashboard β†’ Settings β†’ Stripe
  4. 4
    An API key

    One key per organization, shown only at creation, stored as a one-way SHA-256 hash. Generate it only after the three steps above are complete.

    Dashboard β†’ Settings β†’ External API
  5. 5
    A secrets store on your side

    Keep the key in an env var or secrets manager β€” never in a client app or public repo. This is the only secret you hold; rotate it if it leaks, revoke it if compromised.

    Your infrastructure
The APIs

What exists and how it works

Today the platform exposes two ways to create and publish checkouts: a public, key-authenticated REST endpoint for programmatic automation, and a native MCP server for AI clients (ChatGPT, Claude, Cursor). A session-authenticated key manager and a handful of internal functions power the backbone behind both.

Create-Checkout API

A single POST that creates a draft checkout, adds participants, publishes it (emails the organizer), and invites every participant β€” all in one call. Authenticated with a per-organization API key in the x-api-key header. It returns only a checkout_reference β€” never organizer or participant links β€” so a compromised key can't impersonate anyone.

API key management

Each organization generates a single API key from Settings (Dashboard β†’ Settings β†’ External API). The key is shown once and stored as a one-way SHA-256 hash. It can be rotated (replacing it) or revoked at any time. Key creation, rotation and revocation are session-authenticated β€” they require a signed-in organization owner, never just the key.

The backbone (internal)

Behind the public endpoint: the organizer page handles splitting and reminders, a Stripe-verified webhook reconciles every payment, and per-participant receipt generation runs after each confirmed charge. You don't call these β€” but knowing they exist explains why creation alone is enough to start a full collection flow.

MCP server (AI clients)

The same create-checkout capability, exposed as a native MCP server so an AI assistant can check readiness and publish a checkout on your behalf after you confirm β€” no API key or code required. Authenticated with your Paywalla session over OAuth and scoped to the organizations you own. See the MCP section ↓

How to implement

From zero to your first checkout

Three steps: get a key, call the endpoint, store the reference.

  1. 1
    Set up your organization

    Sign in, complete your organization profile and connect Stripe in Settings until card payments are active.

  2. 2
    Generate an API key

    In Settings β†’ External API, click Generate API key. Copy it once β€” it won't be shown again β€” and store it server-side in a secret or env var.

  3. 3
    POST a checkout

    Send a JSON body to https://group-split-sync.base44.app/functions/createCheckoutApi with your key in the x-api-key header. The platform publishes it and emails everyone.

  4. 4
    Store the reference

    Keep the returned checkout_reference against your booking/order for reconciliation and support.

Examples

Patterns, payloads & code

Copy any block. Amounts are decimal major units (e.g. 1200 means $1,200.00); the API converts to minor units.

cURL
curl -X POST https://group-split-sync.base44.app/functions/createCheckoutApi \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "title": "Weekend cabin rental",
    "target_amount": 1200,
    "currency": "usd",
    "deadline": "2026-10-01",
    "description": "3-night cabin for 6 guests",
    "organizer": { "name": "Morgan Reyes", "email": "morgan@example.com" },
    "participants": [
      { "name": "Alex Kim", "email": "alex@example.com", "assigned_amount": 400 },
      { "name": "Sam Lee", "email": "sam@example.com", "assigned_amount": 400 },
      { "name": "Pat Ng", "email": "pat@example.com", "assigned_amount": 400 }
    ]
  }'
JavaScript (browser/fetch)
// Create + publish a group checkout from a booking confirmation page.
async function createGroupCheckout({ bookingId, total, dueDate, organizer, guests }) {
  const res = await fetch(
    "https://group-split-sync.base44.app/functions/createCheckoutApi",
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "x-api-key": process.env.PAYWALLA_API_KEY
      },
      body: JSON.stringify({
        title: `Booking ${bookingId}`,
        idempotency_key: bookingId,       // makes retries safe: replays, never duplicates
        target_amount: total,            // decimal major units, e.g. 1200
        currency: "usd",
        deadline: dueDate,               // ISO 8601
        organizer,                       // { name, email }
        participants: guests.map(g => ({
          name: g.name,
          email: g.email,
          assigned_amount: g.share       // optional; leave off for an un-split checkout
        }))
      })
    }
  );
  const data = await res.json();

  if (data.status !== "success") {
    // Handle by data.error_code: validation, stripe_not_ready, rate_limited, ...
    throw new Error(`[${data.error_code}] ${data.message}`);
  }

  // Store this against your booking for reconciliation & support.
  return data.checkout_reference;
}
Node.js (server-side)
import crypto from "node:crypto";

// Server-side: keep the key in an env var, never ship it to the browser.
const key = process.env.PAYWALLA_API_KEY;

const res = await fetch("https://group-split-sync.base44.app/functions/createCheckoutApi", {
  method: "POST",
  headers: { "Content-Type": "application/json", "x-api-key": key },
  body: JSON.stringify({
    title: "Reunion dinner β€” Table 12",
    target_amount: 540,
    currency: "usd",
    deadline: new Date(Date.now() + 7 * 86400000).toISOString(),
    organizer: { name: "Dana Patel", email: "dana@example.com" },
    participants: [
      { name: "Riley", email: "riley@example.com" },
      { name: "Jamie", email: "jamie@example.com" }
    ]
  })
});

const body = await res.json();
if (body.status === "success") console.log("Created", body.checkout_reference);
else console.error(body.error_code, body.message);
Success response (200)
{
  "status": "success",
  "checkout_reference": "gc_a1b2c3d4e5f6g7h8"
}
Error response (400)
{
  "status": "error",
  "error_code": "validation",
  "message": "target_amount must be greater than zero; participants[1].email is invalid"
}
Reference

Request reference

The full contract for a create-checkout call β€” headers, limits, every field, and what comes back.

Headers & endpoint
  • POST https://group-split-sync.base44.app/functions/createCheckoutApi
  • x-api-key: YOUR_API_KEY β€” or Authorization: Bearer YOUR_API_KEY
  • Content-Type: application/json
  • Rate limit: 20 requests per 10 seconds per key. Back off and retry on 429.
field
type Β· required Β· notes
title
stringrequired
Human label for the checkout, e.g. 'Weekend cabin rental'.
target_amount
numberrequired
Total to collect in major units (1200 = $1,200.00). Must be greater than zero.
currency
stringoptional
Lowercase ISO 4217 code (e.g. 'usd'). Defaults to the org's default currency, then 'usd'.
deadline
stringrequired
ISO 8601 timestamp. Stored in UTC β€” send UTC to avoid off-by-one due dates across regions.
description
stringoptional
Shown to participants on the pay page.
organizer
objectrequired
{ name, email }. The person who manages the group; receives the organizer link by email.
participants
arrayrequired
1–100 items. Each item: { name, email, assigned_amount?, is_anonymous? }.
participants[].name
stringrequired
Display name for this payer.
participants[].email
stringrequired
Valid email; whitespace is rejected. Their personal pay link is emailed here.
participants[].assigned_amount
numberoptional
This person's share in major units. Omit (or send 0) for an un-split checkout.
participants[].is_anonymous
booleanoptional
Default false. Hides this payer's name in shared group-progress views.
idempotency_key
stringoptional
A unique token per logical checkout (e.g. your booking or order id). Retries that send the same key replay the original checkout_reference instead of creating a duplicate β€” send one on every call.
What you get back β€” and what you don't

A success returns only status and checkout_reference β€” store it against your booking or order for reconciliation and support. The platform deliberately never returns organizer or participant pay links, so a leaked key can't impersonate anyone. When you send an idempotency_key, a retry returns the same reference plus idempotent_replay: true β€” no second checkout, no duplicate emails.

There is no outbound webhook to your system today: the platform emails the organizer and participants directly, and live payment status lives on the organizer page and dashboard. If you need programmatic status, refunds, or reminders, that's the next API β€” tell us you need it.

No sandbox or test key. The API charges the org's live Stripe β€” there's no separate test endpoint. Validate with a small real checkout first, and confirm with the org whether their Stripe is in test mode before automating a high-volume flow.

Errors

Structured error codes

Every error is JSON with status, error_code and message. Branch on error_code in your client.

error_code
HTTP
What it means
missing_key
401
No API key found in the x-api-key (or Authorization: Bearer) header.
invalid_key
401
The key doesn't match any organization, or it has been revoked.
suspended
403
The organization is suspended.
validation
400
One or more required fields are missing or invalid. The message lists them.
stripe_not_ready
409
The organization hasn't completed Stripe onboarding. Complete it in Settings first.
rate_limited
429
Too many requests from this key in a short window. Back off and retry.
server
500
An unexpected error. Retry with backoff; contact support if it persists.
AI-native access

Connect an AI client (MCP)

Paywalla also exposes the same create-checkout capability as a native MCP server, so an AI assistant β€” ChatGPT, Claude or Cursor β€” can check readiness and create a published checkout on your behalf, after you confirm, without writing any code.

What it is

A Streamable HTTP MCP server at /api/mcp on your published domain, authenticated with your Paywalla session over OAuth. It exposes exactly two tools and opts out of every entity, so the AI can't read or write raw records β€” it can only check readiness and create checkouts, scoped to the organizations you own.

The two tools
get_paywalla_readinessRead-only Β· idempotent

Checks whether the signed-in user's organization is ready to create and publish a live checkout β€” profile, Stripe, support email, address and refund terms β€” and lists what's blocking if not. Call this before gathering any participant details. If the user owns more than one organization, it returns the list and requires an explicit choice; it never silently picks the payout org.

create_group_checkoutConsequential Β· idempotent

Creates and immediately publishes a checkout β€” emails the organizer their private management link and every participant their personal pay link. Requires explicit confirmation after a full preview (org, title, total, currency, deadline, organizer, every participant and amount, and a clear statement that it goes live now). Returns only a checkout_reference β€” never organizer or participant links.

When to use it
  • β€œSet up a reunion dinner for 8 and split it 8 ways, due Friday.” The assistant checks readiness, gathers names and emails, previews the full checkout, and publishes it the moment you confirm.
  • β€œCreate a checkout for our ski house β€” 6 couples, $1,800, due Sept 30.” The assistant builds the participant list conversationally and emails everyone their pay link in one step.
  • β€œCan I even use Paywalla yet?” The readiness tool answers before any details are gathered β€” surfacing a missing Stripe setup or address as a clear action item.
How to set it up
  1. 1
    Publish the app

    The MCP server is live only once Paywalla is published. It activates automatically on the next publish.

  2. 2
    Copy the server URL

    Open the Connect page and copy the MCP server URL β€” it's resolved from your published domain, so it's always correct.

    Open /connect
  3. 3
    Add it to your AI client

    In ChatGPT, Claude or Cursor, add a custom MCP server and paste the URL. Step-by-step guides for each client are on the Connect page.

    Open /connect
  4. 4
    Approve the connection

    The client opens Paywalla's consent page. Sign in with your own account and approve the tools. The connection is scoped to your organization and revocable; your API key is never shared with the AI.

Constraints
  • No custom OAuth scopes. Access is granted per-tool on the consent page, scoped to the signed-in user's role and ownership β€” so the AI client can only see and act on organizations you own.
  • Confirmation is enforced by the AI client and the tool's annotations (destructive_hint), not by the server. The tool description mandates a full preview and an explicit affirmative before publishing; a material change requires a new confirmation.
  • The server activates only when the app is published, and the AI client must refresh its tool list after Paywalla ships changes. Changing the exposed tools may require re-authorizing the client.
  • The same Stripe-readiness gate applies: create_group_checkout returns stripe_not_ready if the org hasn't completed onboarding. The readiness tool surfaces that before you try.
  • Multi-org accounts require an explicit choice. The readiness tool returns the list and waits for the user to pick the payout organization β€” the AI never guesses.
  • Watch for prompt injection. If the assistant builds a checkout from a pasted email, invoice or web page, the amount, organization and participant emails came from untrusted text. Verify them in the preview before confirming β€” hidden instructions can't move money, but they can populate the wrong fields.
  • A connection covers every organization you own. Unlike an API key (one per org), an MCP connection acts as your account until you revoke it. Revoke it from Connect when you're done.
Recommendations
  • Always readiness-check first. Call get_paywalla_readiness before gathering details. It tells the assistant what's missing and returns the organization reference the create call needs.
  • Never let the AI guess the organization. For multi-org accounts, have it list them and let the user choose, then pass the chosen merchant_reference to the create call.
  • Require explicit confirmation. The tool is destructive β€” once published, the organizer and every participant are emailed immediately. Treat the conversational preview as the draft.
  • Use a fresh idempotency_key per checkout. The assistant should mint a new key (a UUID works) for each new checkout. Retries with the same key safely replay the same checkout_reference without duplicating or re-sending β€” but reusing a key across different checkouts silently replays the old one.
  • Use the REST API for high-volume automation. MCP is ideal for conversational, one-off or human-in-the-loop checkouts. The key-authenticated REST API above is better when your product creates checkouts programmatically at scale.
Ready to point your AI client at Paywalla?

Copy the server URL and follow the step-by-step guide for ChatGPT, Claude or Cursor.

What your users will see

Messaging & expectations for each audience

A successful call is only the start. Here's who the platform touches, what they're told, and what they should expect next β€” mirror it in your product's copy and support.

The organizer

They created the checkout from your product and own the guest list, the split and the deadline.

  • Expect an email from the platform right after creation carrying their private organizer link β€” their control room for splits, reminders and progress.
  • In your success UI, confirm the checkout is live and show the checkout_reference; tell them a management email is on the way.
  • If they ask who's paid, point them to that organizer link instead of rebuilding progress inside your UI.
  • They can resend invitations and nudge stragglers themselves from the organizer page β€” you don't need to.

The participants

Each guest gets their own pay link by email β€” no account, no app, no shared link.

  • They're emailed a personal invitation with the amount they owe, the group goal, the deadline and a note that payment goes straight to the organization.
  • Don't email participants yourself β€” the platform mints the secure, per-person pay links your copy can't reproduce.
  • After paying they receive a separate receipt email; the pay link keeps working so they can revisit their status.
  • Lost the link? The organizer resends it from the organizer page β€” make that your standard support answer.

The organization

They connected Stripe and receive every payment directly β€” the platform never holds their money.

  • When your API creates a checkout on their behalf, consider a dashboard alert so they know an automated checkout just appeared.
  • They track payouts and disputes in Stripe, and handle refunds through the platform dashboard or organizer link β€” not via this API.
  • Make sure their support email and address are set before you automate β€” both are snapshotted onto receipts at publish time.
  • If Stripe isn't fully onboarded the call fails with stripe_not_ready; surface that as an action item, not a mystery error.
What happens, and when
  1. Right away
    The checkout goes live; the organizer gets their management email and every participant gets a pay-link invitation.
  2. As people pay
    Stripe webhooks confirm each charge, per-person receipts are issued, and the group's collected total updates live.
  3. Near the deadline
    The organizer can send reminders to anyone who hasn't paid, straight from the organizer page.
  4. Funded or due
    Status moves to funded or deadline_reached, and the organizer decides next steps from their dashboard.
Before you ship

Tips & best practices

A few things developers should know about the platform before going live.

Set up the organization fully first

Before integrating, complete your organization profile (name, support email, address, default currency, refund terms) in Settings. Several of these become snapshots on receipts and checkouts at publish time.

Complete and test Stripe before going live

Connect Stripe and finish onboarding until card payments are active. The API will refuse to publish with stripe_not_ready otherwise. Place a small real test checkout end-to-end through the dashboard so you understand the flow before automating it.

Treat the API key like a password

Store it in a secrets manager or server-side env var β€” never in a client app or public repo. Rotate it immediately if it leaks; revoke it if compromised.

Use your own request IDs for correlation

Send a unique reference in your system per call. The API returns a checkout_reference you can store alongside it for reconciliation and support.

Handle structured errors

Parse the status and error_code fields, not just the HTTP code. Retry only idempotent calls (creation is effectively idempotent per key, but avoid duplicate submits on 5xx until you've checked whether a checkout was created).

Respect rate limits

The endpoint caps bursts per key. For high volume, queue and throttle; don't fire a request per user interaction in a tight loop.

Send valid participant data

Every participant needs a valid email and name. Emails with whitespace are rejected to prevent header injection. Dedupe on your side if it matters to your UX.

Let the platform send invitations

Creation publishes and emails the organizer and every participant automatically. Don't try to email participants yourself β€” you don't have their secure pay links, by design.

Mind deadlines and timezones

Pass deadline as an ISO 8601 timestamp. The platform stores it as-is; use UTC to avoid off-by-one due dates across regions.

Refunds and status stay on the platform

Refunds, reminders, share-view toggles and split edits happen through the organizer link and dashboard. If you need them programmatically, tell us β€” that's a likely next API.

Don't expose organizer/participant links

The API deliberately returns only a checkout_reference, never organizer or pay links, so a compromised integration can't impersonate an organizer or pay on someone's behalf.

Start small, then scale

Validate with a single test checkout, confirm the email + receipt flow, then wire it into your real booking or event flow.

One thing to do first: make sure your account is fully set up and Stripe is connected, active and tested with a small real checkout through the dashboard. The API can't publish until Stripe is ready, and it's far easier to understand the flow once you've run it by hand.

Ready to build?

Set up your organization, generate an API key, and create your first checkout by code.