Skip to main content

Cafe (Digital Menus)

The Cafe API powers digital menus: a cafe has groups and categories, and categories contain menu items. These endpoints are available on all plans.

Scopes: reads require cafe.read, creating a cafe requires cafe.create, and deleting a cafe or a group requires cafe.delete. All other writes — profile, theme, groups, categories, items, including deleting a category or an item — require cafe.update. The tables below note the exact scope per endpoint.

:::note Multipart uploads Endpoints that accept images — cafe profile (logo/cover), group images, category images, and item images — expect multipart/form-data rather than JSON. The JSON examples below are for the non-image endpoints. :::


Cafes

Method & pathScopeDescription
GET /cafescafe.readList cafes.
GET /cafes/:idcafe.readGet one cafe.
POST /cafescafe.createCreate a cafe.
PUT /cafes/:idcafe.updateUpdate a cafe.
PUT /cafes/:id/profilecafe.updateUpdate profile (multipart: logo, cover).
PUT /cafes/:id/themecafe.updateUpdate theme/colors.
DELETE /cafes/:idcafe.deleteDelete a cafe.

Create a cafe

FieldTypeRequiredNotes
namestringyesMax 255 chars.
descriptionstringnoMax 2000 chars.
curl -X POST https://api.prolinksqr.com/cafes \
-H "Authorization: Basic key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "name": "Downtown Cafe", "description": "Specialty coffee & brunch" }'

Update a cafe

PUT /cafes/:id
FieldTypeRequiredNotes
namestringnoMax 255 chars.
descriptionstringnoMax 2000 chars.
operating_hoursarrayno[{ "day", "enabled", "ranges": [{ "from", "to" }] }, ...].
facilitiesarraynoArray of strings (e.g. "wifi", "parking").
social_linksarrayno[{ "platform", "url" }, ...].
qr_optionsobjectnoSee QR options. Applied to the cafe's underlying link, not the cafe record itself.

Contact fields (email, address, phone, website) and branding (name, title, subtitle, logo/cover) are set via Update profile below, not this endpoint.

curl -X PUT https://api.prolinksqr.com/cafes/<cafeId> \
-H "Authorization: Basic key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "facilities": ["wifi", "parking"] }'

Update profile

PUT /cafes/:id/profile

Multipart form data. All fields are optional:

FieldTypeNotes
namestring
titlestring
subtitlestring
addressstring
phonestring
emailstring
websitestring
descriptionstring
logofileNew logo image.
coverfileNew cover image.
delete_logobooleanRemove the existing logo (send as "true").
delete_coverbooleanRemove the existing cover (send as "true").

Update theme

FieldTypeRequiredNotes
themeImagestringyesA supported theme key (e.g. modern, coffee, brunch).
primaryColor, secondaryColorstringno
showDietarySectionbooleanno

Groups

Method & pathScopeDescription
GET /cafes/:id/groupscafe.readList groups.
GET /cafes/:id/groups/:groupIdcafe.readGet one group.
POST /cafes/:id/groupscafe.updateCreate a group (multipart: optional image).
PUT /cafes/:id/groups/:groupIdcafe.updateUpdate a group (multipart: optional image).
DELETE /cafes/:id/groups/:groupIdcafe.deleteDelete a group.
PATCH /cafes/:id/groups/reordercafe.updateReorder groups.

Create a group

FieldTypeRequiredNotes
namestringyesMax 255 chars.
visiblebooleannoDefaults to true.
orderintegerno

Reorder groups

{
"orders": [
{ "id": "<groupId>", "order": 0 },
{ "id": "<groupId>", "order": 1 }
]
}

Categories

Method & pathScopeDescription
GET /cafes/:id/categoriescafe.readList categories.
GET /cafes/:id/categories/:categoryIdcafe.readGet one category.
POST /cafes/:id/categoriescafe.updateCreate a category.
PUT /cafes/:id/categories/:categoryIdcafe.updateUpdate a category.
PUT /cafes/:id/categories/:categoryId/imagecafe.updateSet category image (multipart: image).
DELETE /cafes/:id/categories/:categoryIdcafe.updateDelete a category.
PATCH /cafes/:id/categories/reordercafe.updateReorder categories.

Create a category

FieldTypeRequiredNotes
namestringyesMax 255 chars.
descriptionstringnoMax 1000 chars.
group_idstring (UUID)noAssign to a group.
typestringno
orderintegerno
visiblebooleannoDefaults to true.

Category names must be unique (case-insensitive) within a cafe. Creating or renaming a category to a name that already exists returns 400.

curl -X POST https://api.prolinksqr.com/cafes/<cafeId>/categories \
-H "Authorization: Basic key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "name": "Hot Drinks", "visible": true }'

Method & pathScopeDescription
GET /cafes/:id/itemscafe.readList items.
GET /cafes/:id/items/:itemIdcafe.readGet one item.
POST /cafes/:id/itemscafe.updateCreate an item (multipart: optional image).
POST /cafes/:id/items/bulk-insertcafe.updateBulk insert items (JSON).
PUT /cafes/:id/items/:itemIdcafe.updateUpdate an item (multipart: optional image).
DELETE /cafes/:id/items/:itemIdcafe.updateDelete an item.
POST /cafes/:id/items/:itemId/hidecafe.updateHide an item.
POST /cafes/:id/items/:itemId/showcafe.updateShow an item.
PATCH /cafes/:id/items/reordercafe.updateReorder items.

Create an item

Sent as multipart/form-data (so an image file can be attached). Fields:

FieldTypeRequiredNotes
category_idstring (UUID)yesThe category this item belongs to.
namestringyesMax 255 chars.
pricenumberyes≥ 0.
currencystringnoISO code (e.g. USD, EUR). Defaults to USD.
descriptionstringnoMax 2000 chars.
visible, is_featured, is_new, is_recommendedbooleanno
spice_levelstringnoOne of none, mild, medium, hot, extra_hot.
ingredients, tags, allergensstringno
imagefilenoImage upload.
curl -X POST https://api.prolinksqr.com/cafes/<cafeId>/items \
-H "Authorization: Basic key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-F "category_id=<categoryId>" \
-F "name=Cappuccino" \
-F "price=4.50" \
-F "currency=USD" \
-F "image=@cappuccino.jpg"

Reorder items

Unlike reorder groups and reorder categories, which take an orders wrapper object, the items reorder endpoint expects the array directly as the request body — no orders key:

[
{ "id": "<itemId>", "order": 0 },
{ "id": "<itemId>", "order": 1 }
]

Bulk insert items

:::danger Replaces the entire menu This endpoint is not additive. It deletes every existing item, category, and group for the cafe, then inserts the submitted items (auto-creating a "General" group if none of the submitted items specify one). Use it for a full menu import/replace, not for appending a handful of items to an existing menu — use Create an item for that. :::

JSON body with an items array (1–5000 items):

FieldTypeRequiredNotes
namestringyes
pricenumberyes≥ 0.
currencystringyesISO code.
categorystringyesCategory name (lowercased).
groupstringnoGroup name.
descriptionstringno
ingredientsarraynoArray of strings.
curl -X POST https://api.prolinksqr.com/cafes/<cafeId>/items/bulk-insert \
-H "Authorization: Basic key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "name": "Espresso", "price": 3.0, "currency": "USD", "category": "hot drinks" },
{ "name": "Latte", "price": 4.5, "currency": "USD", "category": "hot drinks" }
]
}'