Pop-up posters the menu shows in a modal when it opens, once a day per diner, at most 5.
Every operation comes with its curl and an example response; the keys and ids in the examples are made up. Fields marked with * are required.
get /restaurants/{ref}/promosrequires menu:read listPromos
Every promotion in display order, paused ones included. The menu shows the active ones whose dates include now, in a modal when it opens, once a day per diner.
Parameters Name In Description ref* path The restaurant identifier (the slug in its public URL, e.g. "pizzeria-roma") or its id, as returned by GET /restaurants
Example curl -X GET "https://delimenu.co/api/v1/restaurants/pizzeria-roma/promos" \
-H "Authorization: Bearer dmk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" Response 200 {
"promos" : [
{
"id" : "8c1f2e4a-5b6d-4e7f-9a0b-1c2d3e4f5a6b" ,
"image_url" : "https://firebasestorage.googleapis.com/v0/b/example/o/promo-halloween_1080x1080.webp?alt=media" ,
"image_width" : 864 ,
"image_height" : 1080 ,
"active" : true ,
"starts_at" : "2026-10-25T05:00:00.000Z" ,
"ends_at" : "2026-11-01T04:59:59.000Z" ,
"link" : {
"type" : "url" ,
"url" : "https://www.instagram.com/pizzeriaroma"
}
}
]
} Response fields Field Type Description promos* object[]id* stringimage_url* stringThe resized poster (fits 1080×1080, aspect ratio kept) image_width* number | nullimage_height* number | nullactive* booleanfalse: paused by the owner starts_at* string | nullISO 8601. null: no start ends_at* string | nullISO 8601. null: no end link* any | nullWhat tapping it does: a "View product" or a "More info" button; null: nothing
Errors 401 UNAUTHORIZED — the key is missing, unknown or revoked402 NOT_PREMIUM — the restaurant has no active subscription or trial403 FORBIDDEN — the key lacks the scope this endpoint needs404 NOT_FOUND — no such restaurant in this account, or no such item in it500 INTERNAL — something failed on our side; retry in a momentpost /restaurants/{ref}/promosrequires menu:write createPromo
Downloads the poster at a public https URL (JPG, PNG or WEBP, up to 5 MB) and appends a promotion; takes a few seconds while the image is optimised. Dates are ISO 8601 with offset: the start and the end of the day in the restaurant time zone. At most 5 per restaurant (LIMIT otherwise).
Parameters Name In Description ref* path The restaurant identifier (the slug in its public URL, e.g. "pizzeria-roma") or its id, as returned by GET /restaurants
Body (JSON) Field Type Description image_url* stringPublic https URL of the poster (JPG, PNG or WEBP up to 5 MB). Portrait works best; it is shown whole, never cropped.up to 2048 characters activebooleanfalse pauses the promo without deleting it. Default true. starts_atstring | nullWhen it starts showing (ISO 8601 with offset, start of the day). Absent or null: from now. ends_atstring | nullWhen it stops showing (ISO 8601 with offset, end of the day). Absent or null: no end. linkany | nullWhat tapping the promo does: { type: "product", product_id } shows a "View product" button, { type: "url", url } a "More info" button. null removes it.
Example curl -X POST "https://delimenu.co/api/v1/restaurants/pizzeria-roma/promos" \
-H "Authorization: Bearer dmk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"image_url":"https://example.com/fotos/halloween.jpg","starts_at":"2026-10-25T00:00:00-05:00","ends_at":"2026-10-31T23:59:59-05:00","link":{"type":"url","url":"https://www.instagram.com/pizzeriaroma"}}' Response 201 {
"promos" : [
{
"id" : "8c1f2e4a-5b6d-4e7f-9a0b-1c2d3e4f5a6b" ,
"image_url" : "https://firebasestorage.googleapis.com/v0/b/example/o/promo-halloween_1080x1080.webp?alt=media" ,
"image_width" : 864 ,
"image_height" : 1080 ,
"active" : true ,
"starts_at" : "2026-10-25T05:00:00.000Z" ,
"ends_at" : "2026-11-01T04:59:59.000Z" ,
"link" : {
"type" : "url" ,
"url" : "https://www.instagram.com/pizzeriaroma"
}
}
]
} Response fields Field Type Description promos* object[]id* stringimage_url* stringThe resized poster (fits 1080×1080, aspect ratio kept) image_width* number | nullimage_height* number | nullactive* booleanfalse: paused by the owner starts_at* string | nullISO 8601. null: no start ends_at* string | nullISO 8601. null: no end link* any | nullWhat tapping it does: a "View product" or a "More info" button; null: nothing
Errors 400 VALIDATION — a field is missing or malformed; `issues` names it401 UNAUTHORIZED — the key is missing, unknown or revoked402 NOT_PREMIUM — the restaurant has no active subscription or trial403 FORBIDDEN — the key lacks the scope this endpoint needs404 NOT_FOUND — no such restaurant in this account, or no such item in it500 INTERNAL — something failed on our side; retry in a momentpatch /restaurants/{ref}/promos/{id}requires menu:write updatePromo
Pause or resume it (active), change its dates or its link, or replace its poster (image_url). Only the fields given change; null removes a date or the link.
Parameters Name In Description ref* path The restaurant identifier (the slug in its public URL, e.g. "pizzeria-roma") or its id, as returned by GET /restaurants id* path The promotion id, from GET /restaurants/{ref}/promos
Body (JSON) Field Type Description image_urlstringA new poster, replacing the current oneup to 2048 characters activebooleanfalse pauses the promo without deleting it. Default true. starts_atstring | nullWhen it starts showing (ISO 8601 with offset, start of the day). Absent or null: from now. ends_atstring | nullWhen it stops showing (ISO 8601 with offset, end of the day). Absent or null: no end. linkany | nullWhat tapping the promo does: { type: "product", product_id } shows a "View product" button, { type: "url", url } a "More info" button. null removes it.
Example curl -X PATCH "https://delimenu.co/api/v1/restaurants/pizzeria-roma/promos/8c1f2e4a-5b6d-4e7f-9a0b-1c2d3e4f5a6b" \
-H "Authorization: Bearer dmk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"active":false}' Response 200 {
"promos" : [
{
"id" : "8c1f2e4a-5b6d-4e7f-9a0b-1c2d3e4f5a6b" ,
"image_url" : "https://firebasestorage.googleapis.com/v0/b/example/o/promo-halloween_1080x1080.webp?alt=media" ,
"image_width" : 864 ,
"image_height" : 1080 ,
"active" : false ,
"starts_at" : "2026-10-25T05:00:00.000Z" ,
"ends_at" : "2026-11-01T04:59:59.000Z" ,
"link" : {
"type" : "url" ,
"url" : "https://www.instagram.com/pizzeriaroma"
}
}
]
} Response fields Field Type Description promos* object[]id* stringimage_url* stringThe resized poster (fits 1080×1080, aspect ratio kept) image_width* number | nullimage_height* number | nullactive* booleanfalse: paused by the owner starts_at* string | nullISO 8601. null: no start ends_at* string | nullISO 8601. null: no end link* any | nullWhat tapping it does: a "View product" or a "More info" button; null: nothing
Errors 400 VALIDATION — a field is missing or malformed; `issues` names it401 UNAUTHORIZED — the key is missing, unknown or revoked402 NOT_PREMIUM — the restaurant has no active subscription or trial403 FORBIDDEN — the key lacks the scope this endpoint needs404 NOT_FOUND — no such restaurant in this account, or no such item in it500 INTERNAL — something failed on our side; retry in a momentdelete /restaurants/{ref}/promos/{id}requires menu:write deletePromo
Deletes the promotion and its poster. To stop showing it for a while, PATCH active: false instead.
Parameters Name In Description ref* path The restaurant identifier (the slug in its public URL, e.g. "pizzeria-roma") or its id, as returned by GET /restaurants id* path The promotion id, from GET /restaurants/{ref}/promos
Example curl -X DELETE "https://delimenu.co/api/v1/restaurants/pizzeria-roma/promos/8c1f2e4a-5b6d-4e7f-9a0b-1c2d3e4f5a6b" \
-H "Authorization: Bearer dmk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" Response 200 Response fields Field Type Description promos* object[]id* stringimage_url* stringThe resized poster (fits 1080×1080, aspect ratio kept) image_width* number | nullimage_height* number | nullactive* booleanfalse: paused by the owner starts_at* string | nullISO 8601. null: no start ends_at* string | nullISO 8601. null: no end link* any | nullWhat tapping it does: a "View product" or a "More info" button; null: nothing
Errors 401 UNAUTHORIZED — the key is missing, unknown or revoked402 NOT_PREMIUM — the restaurant has no active subscription or trial403 FORBIDDEN — the key lacks the scope this endpoint needs404 NOT_FOUND — no such restaurant in this account, or no such item in it500 INTERNAL — something failed on our side; retry in a momentput /restaurants/{ref}/promo-orderrequires menu:write reorderPromos
Sets the order the modal shows them in. Pass every promo id exactly once.
Parameters Name In Description ref* path The restaurant identifier (the slug in its public URL, e.g. "pizzeria-roma") or its id, as returned by GET /restaurants
Body (JSON) Field Type Description promo_ids* string[]Every promo id exactly once, in the order the modal shows them
Example curl -X PUT "https://delimenu.co/api/v1/restaurants/pizzeria-roma/promo-order" \
-H "Authorization: Bearer dmk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"promo_ids":["8c1f2e4a-5b6d-4e7f-9a0b-1c2d3e4f5a6b"]}' Response 200 {
"promos" : [
{
"id" : "8c1f2e4a-5b6d-4e7f-9a0b-1c2d3e4f5a6b" ,
"image_url" : "https://firebasestorage.googleapis.com/v0/b/example/o/promo-halloween_1080x1080.webp?alt=media" ,
"image_width" : 864 ,
"image_height" : 1080 ,
"active" : true ,
"starts_at" : "2026-10-25T05:00:00.000Z" ,
"ends_at" : "2026-11-01T04:59:59.000Z" ,
"link" : {
"type" : "url" ,
"url" : "https://www.instagram.com/pizzeriaroma"
}
}
]
} Response fields Field Type Description promos* object[]id* stringimage_url* stringThe resized poster (fits 1080×1080, aspect ratio kept) image_width* number | nullimage_height* number | nullactive* booleanfalse: paused by the owner starts_at* string | nullISO 8601. null: no start ends_at* string | nullISO 8601. null: no end link* any | nullWhat tapping it does: a "View product" or a "More info" button; null: nothing
Errors 400 VALIDATION — a field is missing or malformed; `issues` names it401 UNAUTHORIZED — the key is missing, unknown or revoked402 NOT_PREMIUM — the restaurant has no active subscription or trial403 FORBIDDEN — the key lacks the scope this endpoint needs404 NOT_FOUND — no such restaurant in this account, or no such item in it500 INTERNAL — something failed on our side; retry in a momentRelated articles