10 operations. Every schema and example on this page is generated from the platform contract.
Every drop for the authenticated store, newest first, each with its items, windows and live counters. Also returns whether the store can run a drop at all, and if not, why.
Include drops whose collection date has passed.
The short code in the shareable link: /d/{code}
The full link the merchant pastes into her bio.
draftscheduledcancelledComputed at read time. Never sent by a client.
draftscheduledliveclosedcollectedcancelledCopied from the menu item at read time, never stored twice.
How many were put up.
How many are still available. Never negative.
null = no limit.
null = no cap on orders in this window.
Why a drop cannot open. Say this to the merchant, do not refuse blankly.
no_addoncollect_offno_paymentsunavailablecurl -G "https://www.membber.com/api/v1/drops" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
--data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066"import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.GET("/api/v1/drops", {
params: { query: { store_id: "6659c139-0000-4000-8000-d0c500000066" } },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.listBatchDrops(
query: .init(storeId: "6659c139-0000-4000-8000-d0c500000066")
).ok.body.json
print(response){
"drops": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"store_id": "6659c139-0000-4000-8000-d0c500000066",
"code": "EXAMPLE10",
"share_url": "https://example.com/image.jpg",
"name": "Example name",
"description": "Added at the front desk",
"status": "draft",
"state": "draft",
"opens_at": "<opens_at>",
"closes_at": "<closes_at>",
"collection_date": "<collection_date>",
"timezone": "Europe/London",
"checkout_ttl_seconds": 1,
"menu_visible_before_open": true,
"show_stock_count": true,
"max_per_customer": 1,
"items": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"menu_item_id": "ca65a6e7-0000-4000-8000-d0c5000000ca",
"name": "Example name",
"price_pence": 1500,
"image_url": "https://example.com/image.jpg",
"quantity": 1,
"remaining": 1,
"max_per_order": 1,
"sold_out_at": "<sold_out_at>",
"sort_order": 1,
"allergens": [
"<allergen>"
],
"allergens_missing": true
}
],
"windows": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"starts_at": "<starts_at>",
"ends_at": "<ends_at>",
"max_orders": 1,
"orders_remaining": 1
}
],
"orders_count": 1,
"units_sold": 1,
"units_total": 1,
"gross_pence": 1500,
"blockers": [
"<blocker>"
],
"created_at": "<created_at>",
"updated_at": "<updated_at>"
}
],
"live_drop_id": "68f0d418-0000-4000-8000-d0c500000068",
"drops_live": true,
"blocked_reason": "no_addon",
"reachable_customers": -9007199254740991
}/api/v1/dropsCreates a DRAFT drop for the authenticated store. A draft is invisible to customers and has no link until it is scheduled. Send a `client_token` to make the create idempotent.
Send the same token on a retry to get the SAME drop back instead of a duplicate.
ISO instant. The drop opens itself at this minute.
ISO instant, or null to close when it sells out.
YYYY-MM-DD in the store timezone.
Basket hold, in seconds. Defaults to 300 (5 minutes).
null = no limit.
The short code in the shareable link: /d/{code}
The full link the merchant pastes into her bio.
draftscheduledcancelledComputed at read time. Never sent by a client.
draftscheduledliveclosedcollectedcancelledCopied from the menu item at read time, never stored twice.
How many were put up.
How many are still available. Never negative.
null = no limit.
null = no cap on orders in this window.
curl -X POST "https://www.membber.com/api/v1/drops" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
-H "Content-Type: application/json" \
-d '{
"store_id": "6659c139-0000-4000-8000-d0c500000066",
"name": "Example name",
"opens_at": "<opens_at>",
"collection_date": "<collection_date>"
}'import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.POST("/api/v1/drops", {
body: {
store_id: "6659c139-0000-4000-8000-d0c500000066",
name: "Example name",
opens_at: "<opens_at>",
collection_date: "<collection_date>"
},
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.createBatchDrop(
body: .json(.init(
storeId: "6659c139-0000-4000-8000-d0c500000066",
name: "Example name",
opensAt: "<opens_at>",
collectionDate: "<collection_date>"
))
).ok.body.json
print(response){
"drop": {
"id": "00000d1b-0000-4000-8000-d0c500000000",
"store_id": "6659c139-0000-4000-8000-d0c500000066",
"code": "EXAMPLE10",
"share_url": "https://example.com/image.jpg",
"name": "Example name",
"description": "Added at the front desk",
"status": "draft",
"state": "draft",
"opens_at": "<opens_at>",
"closes_at": "<closes_at>",
"collection_date": "<collection_date>",
"timezone": "Europe/London",
"checkout_ttl_seconds": 1,
"menu_visible_before_open": true,
"show_stock_count": true,
"max_per_customer": 1,
"items": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"menu_item_id": "ca65a6e7-0000-4000-8000-d0c5000000ca",
"name": "Example name",
"price_pence": 1500,
"image_url": "https://example.com/image.jpg",
"quantity": 1,
"remaining": 1,
"max_per_order": 1,
"sold_out_at": "<sold_out_at>",
"sort_order": 1,
"allergens": [
"<allergen>"
],
"allergens_missing": true
}
],
"windows": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"starts_at": "<starts_at>",
"ends_at": "<ends_at>",
"max_orders": 1,
"orders_remaining": 1
}
],
"orders_count": 1,
"units_sold": 1,
"units_total": 1,
"gross_pence": 1500,
"blockers": [
"<blocker>"
],
"created_at": "<created_at>",
"updated_at": "<updated_at>"
}
}The drop with its items, windows, live counters and anything blocking it going live.
The short code in the shareable link: /d/{code}
The full link the merchant pastes into her bio.
draftscheduledcancelledComputed at read time. Never sent by a client.
draftscheduledliveclosedcollectedcancelledCopied from the menu item at read time, never stored twice.
How many were put up.
How many are still available. Never negative.
null = no limit.
null = no cap on orders in this window.
curl -G "https://www.membber.com/api/v1/drops/b11f386a-0000-4000-8000-d0c5000000b1" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
--data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066"import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.GET("/api/v1/drops/{dropId}", {
params: { path: { dropId: "b11f386a-0000-4000-8000-d0c5000000b1" }, query: { store_id: "6659c139-0000-4000-8000-d0c500000066" } },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.getBatchDrop(
path: .init(dropId: "b11f386a-0000-4000-8000-d0c5000000b1"),
query: .init(storeId: "6659c139-0000-4000-8000-d0c500000066")
).ok.body.json
print(response){
"drop": {
"id": "00000d1b-0000-4000-8000-d0c500000000",
"store_id": "6659c139-0000-4000-8000-d0c500000066",
"code": "EXAMPLE10",
"share_url": "https://example.com/image.jpg",
"name": "Example name",
"description": "Added at the front desk",
"status": "draft",
"state": "draft",
"opens_at": "<opens_at>",
"closes_at": "<closes_at>",
"collection_date": "<collection_date>",
"timezone": "Europe/London",
"checkout_ttl_seconds": 1,
"menu_visible_before_open": true,
"show_stock_count": true,
"max_per_customer": 1,
"items": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"menu_item_id": "ca65a6e7-0000-4000-8000-d0c5000000ca",
"name": "Example name",
"price_pence": 1500,
"image_url": "https://example.com/image.jpg",
"quantity": 1,
"remaining": 1,
"max_per_order": 1,
"sold_out_at": "<sold_out_at>",
"sort_order": 1,
"allergens": [
"<allergen>"
],
"allergens_missing": true
}
],
"windows": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"starts_at": "<starts_at>",
"ends_at": "<ends_at>",
"max_orders": 1,
"orders_remaining": 1
}
],
"orders_count": 1,
"units_sold": 1,
"units_total": 1,
"gross_pence": 1500,
"blockers": [
"<blocker>"
],
"created_at": "<created_at>",
"updated_at": "<updated_at>"
}
}Edits a drop, including one that is currently selling: adding stock, reordering items, adding a window or closing early are all expected mid-drop. Moving `status` from draft to scheduled is what makes it go live at its opening minute; that is refused while any item is missing its allergens, and the refusal names the item.
draftscheduledISO instant. The drop opens itself at this minute.
ISO instant, or null to close when it sells out.
YYYY-MM-DD in the store timezone.
Basket hold, in seconds. Defaults to 300 (5 minutes).
null = no limit.
The short code in the shareable link: /d/{code}
The full link the merchant pastes into her bio.
draftscheduledcancelledComputed at read time. Never sent by a client.
draftscheduledliveclosedcollectedcancelledCopied from the menu item at read time, never stored twice.
How many were put up.
How many are still available. Never negative.
null = no limit.
null = no cap on orders in this window.
curl -X PATCH "https://www.membber.com/api/v1/drops/b11f386a-0000-4000-8000-d0c5000000b1" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
-H "Content-Type: application/json" \
-d '{
"store_id": "6659c139-0000-4000-8000-d0c500000066"
}'import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.PATCH("/api/v1/drops/{dropId}", {
params: { path: { dropId: "b11f386a-0000-4000-8000-d0c5000000b1" } },
body: {
store_id: "6659c139-0000-4000-8000-d0c500000066"
},
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.updateBatchDrop(
path: .init(dropId: "b11f386a-0000-4000-8000-d0c5000000b1"),
body: .json(.init(
storeId: "6659c139-0000-4000-8000-d0c500000066"
))
).ok.body.json
print(response){
"drop": {
"id": "00000d1b-0000-4000-8000-d0c500000000",
"store_id": "6659c139-0000-4000-8000-d0c500000066",
"code": "EXAMPLE10",
"share_url": "https://example.com/image.jpg",
"name": "Example name",
"description": "Added at the front desk",
"status": "draft",
"state": "draft",
"opens_at": "<opens_at>",
"closes_at": "<closes_at>",
"collection_date": "<collection_date>",
"timezone": "Europe/London",
"checkout_ttl_seconds": 1,
"menu_visible_before_open": true,
"show_stock_count": true,
"max_per_customer": 1,
"items": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"menu_item_id": "ca65a6e7-0000-4000-8000-d0c5000000ca",
"name": "Example name",
"price_pence": 1500,
"image_url": "https://example.com/image.jpg",
"quantity": 1,
"remaining": 1,
"max_per_order": 1,
"sold_out_at": "<sold_out_at>",
"sort_order": 1,
"allergens": [
"<allergen>"
],
"allergens_missing": true
}
],
"windows": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"starts_at": "<starts_at>",
"ends_at": "<ends_at>",
"max_orders": 1,
"orders_remaining": 1
}
],
"orders_count": 1,
"units_sold": 1,
"units_total": 1,
"gross_pence": 1500,
"blockers": [
"<blocker>"
],
"created_at": "<created_at>",
"updated_at": "<updated_at>"
}
}Cancels the drop. Any paid order is refunded and every affected person is told once, however many orders they hold. A drop with paid orders requires `confirm_refunds: true`, so nobody cancels fifty people without being shown the number first. Requires the refund permission.
The short code in the shareable link: /d/{code}
The full link the merchant pastes into her bio.
draftscheduledcancelledComputed at read time. Never sent by a client.
draftscheduledliveclosedcollectedcancelledCopied from the menu item at read time, never stored twice.
How many were put up.
How many are still available. Never negative.
null = no limit.
null = no cap on orders in this window.
How many orders will be refunded.
How many PEOPLE, which is fewer if anyone ordered twice.
curl -X POST "https://www.membber.com/api/v1/drops/b11f386a-0000-4000-8000-d0c5000000b1/cancel" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
-H "Content-Type: application/json" \
-d '{
"store_id": "6659c139-0000-4000-8000-d0c500000066"
}'import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.POST("/api/v1/drops/{dropId}/cancel", {
params: { path: { dropId: "b11f386a-0000-4000-8000-d0c5000000b1" } },
body: {
store_id: "6659c139-0000-4000-8000-d0c500000066"
},
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.cancelBatchDrop(
path: .init(dropId: "b11f386a-0000-4000-8000-d0c5000000b1"),
body: .json(.init(
storeId: "6659c139-0000-4000-8000-d0c500000066"
))
).ok.body.json
print(response){
"drop": {
"id": "00000d1b-0000-4000-8000-d0c500000000",
"store_id": "6659c139-0000-4000-8000-d0c500000066",
"code": "EXAMPLE10",
"share_url": "https://example.com/image.jpg",
"name": "Example name",
"description": "Added at the front desk",
"status": "draft",
"state": "draft",
"opens_at": "<opens_at>",
"closes_at": "<closes_at>",
"collection_date": "<collection_date>",
"timezone": "Europe/London",
"checkout_ttl_seconds": 1,
"menu_visible_before_open": true,
"show_stock_count": true,
"max_per_customer": 1,
"items": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"menu_item_id": "ca65a6e7-0000-4000-8000-d0c5000000ca",
"name": "Example name",
"price_pence": 1500,
"image_url": "https://example.com/image.jpg",
"quantity": 1,
"remaining": 1,
"max_per_order": 1,
"sold_out_at": "<sold_out_at>",
"sort_order": 1,
"allergens": [
"<allergen>"
],
"allergens_missing": true
}
],
"windows": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"starts_at": "<starts_at>",
"ends_at": "<ends_at>",
"max_orders": 1,
"orders_remaining": 1
}
],
"orders_count": 1,
"units_sold": 1,
"units_total": 1,
"gross_pence": 1500,
"blockers": [
"<blocker>"
],
"created_at": "<created_at>",
"updated_at": "<updated_at>"
},
"orders_to_refund": 1,
"people_to_tell": 1,
"refund_pence": 1500
}Replaces the drop menu with the given items, chosen from the store menu that already exists. Raising a quantity mid-drop puts stock back on sale immediately. Lowering it can never go below what is already sold, and the refusal says how many that is. An item omitted here is removed from the drop, which is refused if any of it has sold.
The short code in the shareable link: /d/{code}
The full link the merchant pastes into her bio.
draftscheduledcancelledComputed at read time. Never sent by a client.
draftscheduledliveclosedcollectedcancelledCopied from the menu item at read time, never stored twice.
How many were put up.
How many are still available. Never negative.
null = no limit.
null = no cap on orders in this window.
curl -X PUT "https://www.membber.com/api/v1/drops/b11f386a-0000-4000-8000-d0c5000000b1/items" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
-H "Content-Type: application/json" \
-d '{
"store_id": "6659c139-0000-4000-8000-d0c500000066",
"items": [
{
"menu_item_id": "ca65a6e7-0000-4000-8000-d0c5000000ca",
"quantity": 1
}
]
}'import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.PUT("/api/v1/drops/{dropId}/items", {
params: { path: { dropId: "b11f386a-0000-4000-8000-d0c5000000b1" } },
body: {
store_id: "6659c139-0000-4000-8000-d0c500000066",
items: [
{
menu_item_id: "ca65a6e7-0000-4000-8000-d0c5000000ca",
quantity: 1
}
]
},
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.setBatchDropItems(
path: .init(dropId: "b11f386a-0000-4000-8000-d0c5000000b1"),
body: .json(.init(
storeId: "6659c139-0000-4000-8000-d0c500000066",
items: [.init(
menuItemId: "ca65a6e7-0000-4000-8000-d0c5000000ca",
quantity: 1
)]
))
).ok.body.json
print(response){
"drop": {
"id": "00000d1b-0000-4000-8000-d0c500000000",
"store_id": "6659c139-0000-4000-8000-d0c500000066",
"code": "EXAMPLE10",
"share_url": "https://example.com/image.jpg",
"name": "Example name",
"description": "Added at the front desk",
"status": "draft",
"state": "draft",
"opens_at": "<opens_at>",
"closes_at": "<closes_at>",
"collection_date": "<collection_date>",
"timezone": "Europe/London",
"checkout_ttl_seconds": 1,
"menu_visible_before_open": true,
"show_stock_count": true,
"max_per_customer": 1,
"items": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"menu_item_id": "ca65a6e7-0000-4000-8000-d0c5000000ca",
"name": "Example name",
"price_pence": 1500,
"image_url": "https://example.com/image.jpg",
"quantity": 1,
"remaining": 1,
"max_per_order": 1,
"sold_out_at": "<sold_out_at>",
"sort_order": 1,
"allergens": [
"<allergen>"
],
"allergens_missing": true
}
],
"windows": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"starts_at": "<starts_at>",
"ends_at": "<ends_at>",
"max_orders": 1,
"orders_remaining": 1
}
],
"orders_count": 1,
"units_sold": 1,
"units_total": 1,
"gross_pence": 1500,
"blockers": [
"<blocker>"
],
"created_at": "<created_at>",
"updated_at": "<updated_at>"
}
}Replaces the drop collection windows. A drop owns its own windows for one date rather than inheriting the store's standing weekly hours. Windows can be added while the drop is selling. Removing a window that people have already booked into is refused, and the refusal says how many.
The short code in the shareable link: /d/{code}
The full link the merchant pastes into her bio.
draftscheduledcancelledComputed at read time. Never sent by a client.
draftscheduledliveclosedcollectedcancelledCopied from the menu item at read time, never stored twice.
How many were put up.
How many are still available. Never negative.
null = no limit.
null = no cap on orders in this window.
curl -X PUT "https://www.membber.com/api/v1/drops/b11f386a-0000-4000-8000-d0c5000000b1/windows" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
-H "Content-Type: application/json" \
-d '{
"store_id": "6659c139-0000-4000-8000-d0c500000066",
"windows": [
{
"starts_at": "<starts_at>",
"ends_at": "<ends_at>"
}
]
}'import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.PUT("/api/v1/drops/{dropId}/windows", {
params: { path: { dropId: "b11f386a-0000-4000-8000-d0c5000000b1" } },
body: {
store_id: "6659c139-0000-4000-8000-d0c500000066",
windows: [
{
starts_at: "<starts_at>",
ends_at: "<ends_at>"
}
]
},
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.setBatchDropWindows(
path: .init(dropId: "b11f386a-0000-4000-8000-d0c5000000b1"),
body: .json(.init(
storeId: "6659c139-0000-4000-8000-d0c500000066",
windows: [.init(
startsAt: "<starts_at>",
endsAt: "<ends_at>"
)]
))
).ok.body.json
print(response){
"drop": {
"id": "00000d1b-0000-4000-8000-d0c500000000",
"store_id": "6659c139-0000-4000-8000-d0c500000066",
"code": "EXAMPLE10",
"share_url": "https://example.com/image.jpg",
"name": "Example name",
"description": "Added at the front desk",
"status": "draft",
"state": "draft",
"opens_at": "<opens_at>",
"closes_at": "<closes_at>",
"collection_date": "<collection_date>",
"timezone": "Europe/London",
"checkout_ttl_seconds": 1,
"menu_visible_before_open": true,
"show_stock_count": true,
"max_per_customer": 1,
"items": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"menu_item_id": "ca65a6e7-0000-4000-8000-d0c5000000ca",
"name": "Example name",
"price_pence": 1500,
"image_url": "https://example.com/image.jpg",
"quantity": 1,
"remaining": 1,
"max_per_order": 1,
"sold_out_at": "<sold_out_at>",
"sort_order": 1,
"allergens": [
"<allergen>"
],
"allergens_missing": true
}
],
"windows": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"starts_at": "<starts_at>",
"ends_at": "<ends_at>",
"max_orders": 1,
"orders_remaining": 1
}
],
"orders_count": 1,
"units_sold": 1,
"units_total": 1,
"gross_pence": 1500,
"blockers": [
"<blocker>"
],
"created_at": "<created_at>",
"updated_at": "<updated_at>"
}
}Public. Everything a buyer needs to decide: what is in it, how many are left, when it opens, when to collect, and the allergens the seller declared. Returns the drop even before it opens so the page can count down; the menu itself is withheld while the seller has chosen to hide it.
scheduledliveclosedcollectedcancelledcurl -G "https://www.membber.com/api/v1/drops/public/EXAMPLE10" \
-H "Authorization: Bearer $MEMBBER_TOKEN"import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.GET("/api/v1/drops/public/{dropCode}", {
params: { path: { dropCode: "EXAMPLE10" } },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.getPublicBatchDrop(
path: .init(dropCode: "EXAMPLE10")
).ok.body.json
print(response){
"drop": {
"id": "00000d1b-0000-4000-8000-d0c500000000",
"code": "EXAMPLE10",
"name": "Example name",
"description": "Added at the front desk",
"state": "scheduled",
"opens_at": "<opens_at>",
"closes_at": "<closes_at>",
"collection_date": "<collection_date>",
"timezone": "Europe/London",
"checkout_ttl_seconds": 1,
"max_per_customer": 1,
"items": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"menu_item_id": "ca65a6e7-0000-4000-8000-d0c5000000ca",
"name": "Example name",
"description": "Added at the front desk",
"price_pence": 1500,
"image_url": "https://example.com/image.jpg",
"sold_out": true,
"remaining": 1,
"in_other_baskets": 1,
"max_per_order": 1,
"allergens": [
"<allergen>"
],
"ingredients": "<ingredients>"
}
],
"windows": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"starts_at": "<starts_at>",
"ends_at": "<ends_at>",
"full": true
}
],
"store": {
"code": "EXAMPLE10",
"name": "Example name",
"logo_url": "https://example.com/image.jpg",
"primary_color": "<primary_color>"
}
}
}Public. Holds stock the moment it goes in the basket, not at payment, and starts the countdown. Sets the basket to the given quantity rather than adding to it, so a retry or a double tap converges instead of stacking. Send 0 to remove. Returns which limit bound if you got less than you asked for.
nonestockmax_per_ordermax_per_customerwindow_fullreleasedcurl -X POST "https://www.membber.com/api/v1/drops/public/EXAMPLE10/hold" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
-H "Content-Type: application/json" \
-d '{
"cart_token": "<cart_token>",
"item_id": "7e22b9c7-0000-4000-8000-d0c50000007e",
"quantity": 1
}'import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.POST("/api/v1/drops/public/{dropCode}/hold", {
params: { path: { dropCode: "EXAMPLE10" } },
body: {
cart_token: "<cart_token>",
item_id: "7e22b9c7-0000-4000-8000-d0c50000007e",
quantity: 1
},
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.holdBatchDropCart(
path: .init(dropCode: "EXAMPLE10"),
body: .json(.init(
cartToken: "<cart_token>",
itemId: "7e22b9c7-0000-4000-8000-d0c50000007e",
quantity: 1
))
).ok.body.json
print(response){
"granted": 1,
"bound_by": "none",
"remaining": 1,
"expires_at": "<expires_at>"
}Public. Releases everything this basket holds, so it goes back on sale immediately rather than waiting for the countdown. Called when someone empties their basket or leaves.
curl -X POST "https://www.membber.com/api/v1/drops/public/EXAMPLE10/release" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
-H "Content-Type: application/json" \
-d '{
"drop_code": "EXAMPLE10",
"cart_token": "<cart_token>"
}'import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.POST("/api/v1/drops/public/{dropCode}/release", {
params: { path: { dropCode: "EXAMPLE10" } },
body: {
drop_code: "EXAMPLE10",
cart_token: "<cart_token>"
},
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.releaseBatchDropCart(
path: .init(dropCode: "EXAMPLE10"),
body: .json(.init(
dropCode: "EXAMPLE10",
cartToken: "<cart_token>"
))
).ok.body.json
print(response){
"released": 1
}