Skip to main content

Create a split yourself

Use this when you already know who is paying and how much — a quote you agreed over the phone, a booking, an invoice you are splitting between named people. You enter the emails and the amounts, and everyone gets a pay link.

It is the opposite way round from hosted checkout, where the buyer decides who to invite and for how much. Pick by who knows the split:

You set it upThe buyer sets it up
UseThis pageHosted checkout
Who is invited is decided byYou, up frontThe buyer, on our page
Started fromThe dashboard, or your own signed-in sessionYour server, with your API key
You need Stripe connected first

Each person's share is charged straight to your own Stripe account, so there has to be one. GET /api/merchants/me shows stripe_charges_enabled: true once you are ready — gate your own checkout on that. See Become a merchant.

Be aware this endpoint only checks that you have started connecting Stripe, not that Stripe has finished approving you. A half-finished account therefore fails later, and passes Stripe's own error message straight back to you instead of a tidy one. Hosted checkout checks properly and gives you Finish Stripe onboarding before accepting checkouts.

From the dashboard​

Go to /merchant/splits/new, add each participant's email and amount, and optionally an order reference. There is no order-total field: the total is the sum of the amounts you enter, shown on the submit button. Every row needs an email and a positive amount before the form will submit. The form does not check the £1 minimum share, so a row under £1 submits and is then rejected by the API with Each share must be at least £1. Then share the generated pay links.

From the API​

POST /api/checkout-splits

Sign in as Owner, Admin or Member and send that session as Authorization: Bearer <supabase token>. A Finance colleague cannot create splits, and sending a merchantId for a business you are not in returns 403 Not your merchant.

Your API key does not work here — it only opens hosted checkout sessions. If you want your server to start a split on its own, that is the page you want.

{
"merchantId": "<your merchant id>",
"orderReference": "ORDER-123",
"currency": "gbp",
"participants": [
{ "email": "[email protected]", "amountMinor": 4000 },
{ "email": "[email protected]", "amountMinor": 4000 },
{ "email": "[email protected]", "amountMinor": 4000 }
]
}
This endpoint takes pence

amountMinor is in pence, so £40.00 is 4000. It must be a whole number of at least 100, because each share must be at least £1. Hosted checkout is the other way round and takes its amount in pounds.

amountMinor is the person's share. Their card is charged that plus SharePay's flat 20p service fee, so a 4000 share is a £40.20 charge, and you receive the £40 less your merchant fee and Stripe's processing fees. See what SharePay charges.

Returns 201 with { id, status: "pending", participants: [...] }. Each entry in participants is:

FieldNotes
idThe participant row's id
emailAs you sent it
amountMinorTheir share, in pence
feeMinorThe SharePay service fee on their charge, in pence. Their card is charged amountMinor + feeMinor
paymentIntentIdThe Stripe payment holding their share
clientSecretOnly needed if you are building your own pay page rather than using ours
payTokenWhat their pay link is built from
The casing changes between endpoints

This create response returns payToken, camelCase. The list and detail endpoints in Refunds, disputes and order status return the same value as pay_token, snake_case. Reading pay_token off the create response gives you undefined.

A 201 also means we have emailed every participant except the creator their invite, with a pay link in it. See what we email your customers.

Request fields​

FieldRequiredNotes
merchantIdYesMust be a merchant the signed-in account owns
orderReferenceYesAny string. It is not unique and nothing dedupes on it. It appears on the Stripe charge description, in participant emails, and in webhook payloads
currencyNoDefaults to gbp. It is not validated here. Anything you send is passed straight to Stripe, so a value other than gbp either opens charges in that currency on a GB account or fails with a raw Stripe error. Send gbp
participantsYesNon-empty array of { email, amountMinor }

Limits and validation​

  • No cap on how many people. Hosted checkout stops at 20; this endpoint does not stop you at all. We place each person's card hold one at a time, and each one is a real call to Stripe, so a long list is slow and every extra name adds to it. Keep it sensible.
  • Each share must be at least £1. amountMinor must be a positive integer of 100 or more, and anything smaller is rejected with 400 Each share must be at least £1. before any Stripe call is made, so nobody is charged and no hold is placed. There is no maximum per share, and no order total to check the sum against: the split's total is whatever the shares add up to.
  • email is only checked for being a non-empty string. It is not validated as an address, and an unreachable one simply means that person never gets their invite.

If your request times out​

Retrying is not safe. Neither way of creating a split can tell a retry apart from a new request, and there is no key you can send to make it. So if a request times out and you simply send it again, you get a second split, and a second card hold on every customer.

If you are not sure whether the first attempt worked, look before you retry: GET /api/checkout-splits lists your splits newest first. Record the returned id against your own order reference as soon as you have it.

Errors​

StatusBodyCause
401Missing or invalid Authorization headerNo Bearer token
401Invalid tokenExpired or bad session token
403{"code":"consent_required","error":"Consent required", ...}The signed-in account has not accepted the current terms or privacy policy
400Validation failedmerchantId or orderReference not strings, or participants missing or empty
400Each participant needs an email and a positive integer amountMinorA participant failed the per-row check
400Each share must be at least £1.A participant's amountMinor is under 100
404Merchant not foundUnknown merchantId
403Not your merchantThe merchantId belongs to another account
400A checkout split needs at least one participantThe participant list arrived empty
400Merchant has no Stripe connected accountYou have not started connecting Stripe
400{"code":"billing_card_required", ...}Your processor (Adyen) needs a card on file in Settings, Billing, in the same mode, before it takes splits
400{"code":"billing_paused", ...}A SharePay bill has been unpaid for 14 days. Pay it in Settings, Billing and splits work again at once
400Stripe's own error messageA card hold could not be placed. Nothing is ever taken on this path, so nobody is charged. We try to release the holds already placed, and the split ends at creation_failed. See creation_failed