Pay for a basket
const url = 'https://example.com/storefront/sites/northgate.shop.getbottle.app/checkout';const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"lines":[{"productId":"019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f","quantity":1,"hasEmpty":true}],"fulfilment":"delivery","postcode":"example","deliveryOptionId":"019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f","customerId":"019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f","name":"example","email":"hello@example.com","phone":"example","address":{"line1":"example","line2":"example","city":"example","postcode":"example"},"wantedOn":"2026-04-15","notes":"example","marketingConsent":false,"ageConfirmed":true,"acceptsTerms":true,"addressId":"019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f","payment":"card","pin":"example"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://example.com/storefront/sites/northgate.shop.getbottle.app/checkout \ --header 'Content-Type: application/json' \ --data '{ "lines": [ { "productId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "quantity": 1, "hasEmpty": true } ], "fulfilment": "delivery", "postcode": "example", "deliveryOptionId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "customerId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "name": "example", "email": "hello@example.com", "phone": "example", "address": { "line1": "example", "line2": "example", "city": "example", "postcode": "example" }, "wantedOn": "2026-04-15", "notes": "example", "marketingConsent": false, "ageConfirmed": true, "acceptsTerms": true, "addressId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "payment": "card", "pin": "example" }'Deliberately unauthenticated. Prices the basket again, checks it can be bought, the address is in the postcode priced, the day is one on offer (the first, when left out), the age box when the shop asks, and makes a Stripe payment page on the business’s own Stripe account. Answers with its address: send the shopper there. Card details are typed into Stripe, never into Bottle. The order is written once Stripe says it was paid, and the shopper comes back to /order/{id} on the shop. The page lasts an hour. Ten tries a minute from one address.
Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Example
northgate.shop.getbottle.appQuery Parameters
Section titled “Query Parameters”Request Bodyrequired
Section titled “Request Bodyrequired”object
object
UUID v7
Example
019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8fUUID v7
Example
019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8fUUID v7
Example
019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8fobject
UUID v7
Example
019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8fResponses
Section titled “Responses”Where to send the shopper
object
UUID v7
Example
{ "checkoutId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f"}Not a shop, or not open. No body.
The basket cannot be bought as it is (basket_problems, with the problems), the address is not in the postcode priced (postcode_changed), the day is not on offer (day_not_offered), or the age box is needed (age_not_confirmed)
object
object
UUID v7
object
Example
{ "error": "basket_problems", "problems": [ { "code": "out_of_stock", "productId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f" } ]}Validation failed
object
object
Example
{ "error": "validation", "issues": [ { "path": "email", "message": "Invalid email" } ]}Too many requests from one address
object
Example
{ "error": "not_found", "message": "Customer not found"}Stripe could not be reached; nothing was charged
object
Example
{ "error": "not_found", "message": "Customer not found"}