MenuFacile2.0

Endpoint pubbliciDEV

Riferimento di tutti gli endpoint REST V1 read-only del menu.

Tutti gli endpoint pubblici sono read-only e funzionano senza token. Base URL: https://<tenant>.menufacile.it/api/v1.

In caso di successo restituiscono il consueto envelope {success, data, meta}. Per la forma dei body di errore vedi Codici di errore.


GET /menu/{locale?}

Restituisce il menu completo strutturato (settings + tema + sezioni + piatti). È l'endpoint principale per integrare il menu in un sito.

Parametri path

Parametro Tipo Default Descrizione
locale string default_locale del ristorante Codice lingua: it, en, fr, de, es. Locale non supportati ricevono comunque 200 con i contenuti in fallback IT.

Esempio

curl https://ducatarocco.menufacile.it/api/v1/menu/it

Response

{
  "success": true,
  "data": {
    "settings": {
      "id": 1,
      "name": "Duca Tarocco",
      "slug": "ducatarocco",
      "logo_url": "https://ducatarocco.menufacile.it/storage/logos/duca-tarocco.svg",
      "cover_image_url": null,
      "cover_charge_text": "Coperto € 2",
      "allergen_info": "I piatti potrebbero contenere tracce di altri allergeni per contaminazione crociata.",
      "review_url": "https://g.page/r/...",
      "recommended_label": "Più Venduto",
      "business_name": "Ristorante Duca Tarocco S.r.l.",
      "vat_number": "IT01234567890",
      "address": "Via Roma 42, Ragusa",
      "phone": "+39 0932 123456",
      "email": "info@ducatarocco.it",
      "default_locale": "it",
      "supported_locales": ["it", "en"],
      "is_active": true
    },
    "theme": {
      "id": 1,
      "primary_color": "#C0AD8A",
      "secondary_color": "#8A7A5C",
      "accent_color": "#D4A574",
      "background_color": "#2B3C37",
      "text_color": "#F5F5F0",
      "font_family": "Playfair Display",
      "font_url": "/fonts/playfair-display.css",
      "border_radius": "8px",
      "layout_variant": "standard",
      "header_style": "centered",
      "footer_text": "Cucina aperta 19:30 — 23:00"
    },
    "sections": [
      {
        "id": 12,
        "parent_id": null,
        "menu_type": "standard",
        "name": "Antipasti",
        "name_translations": { "it": "Antipasti", "en": "Starters" },
        "notes": "Da condividere a tavola.",
        "display_order": 0,
        "is_active": true,
        "show_subcategories": false,
        "time_visibility_enabled": false,
        "time_start": null,
        "time_end": null,
        "items": [
          {
            "id": 87,
            "category_id": 12,
            "type_id": null,
            "winery_id": null,
            "name": "Caponata della casa",
            "name_translations": { "it": "Caponata della casa", "en": "House caponata" },
            "description": "Melanzane, sedano, capperi, olive",
            "description_translations": { "it": "Melanzane, sedano, capperi, olive", "en": "Eggplant, celery, capers, olives" },
            "price": 9.0,
            "allergens": ["sedano", "solfiti"],
            "is_active": true,
            "is_recommended": true,
            "display_order": 0,
            "winery": null
          }
        ],
        "types": []
      },
      {
        "id": 30,
        "parent_id": null,
        "menu_type": "wine",
        "name": "Carta dei Vini",
        "items": [],
        "types": []
      }
    ]
  },
  "meta": {
    "generated_at": "2026-05-14T11:42:18+00:00",
    "locale": "it"
  }
}

💡 menu_type: solo 2 valori — standard o wine. Le sezioni wine sono sempre in coda al menu (ordine forzato lato API).

💡 Solo sezioni e piatti attivi (is_active: true) sono inclusi nella response: il filtro è applicato server-side, non devi rifarlo nel client.


GET /categories

Lista delle sezioni top-level, ordinate per display_order.

Esempio

curl https://ducatarocco.menufacile.it/api/v1/categories

Response

{
  "success": true,
  "data": [
    {
      "id": 12,
      "parent_id": null,
      "menu_type": "standard",
      "name": "Antipasti",
      "name_translations": { "it": "Antipasti", "en": "Starters" },
      "notes": "Da condividere a tavola.",
      "display_order": 0,
      "is_active": true,
      "show_subcategories": false,
      "time_visibility_enabled": false,
      "time_start": null,
      "time_end": null,
      "items": [ "..." ],
      "types": [ "..." ],
      "children": [ "..." ]
    }
  ],
  "meta": { "generated_at": "..." }
}

Stesso shape sezione del /menu, con in più children[] (eventuali sotto-sezioni) e relazioni items[] / types[] eager-loaded.


GET /categories/{id}

Dettaglio sezione con piatti e sottocategorie incluse.

curl https://ducatarocco.menufacile.it/api/v1/categories/12

Risposta: oggetto Category con stesso shape di sopra (15 campi + items, types, children eager-loaded).

ID inesistente → 404 HTML branded (non JSON), vedi Codici di errore.


GET /items

Lista piatti, supporta filtri e paginazione.

Query parameters

Parametro Tipo Default Descrizione
category_id int Filtra per sezione
type_id int Filtra per sottocategoria
is_recommended bool (0/1) Solo piatti consigliati (oppure solo non consigliati con 0)
search string Ricerca testuale su nome/descrizione
per_page int 50 Numero di item per pagina
locale string default_locale Lingua delle traduzioni

Esempio

curl "https://ducatarocco.menufacile.it/api/v1/items?is_recommended=1&locale=en"

Response

{
  "success": true,
  "data": [
    {
      "id": 87,
      "category_id": 12,
      "type_id": null,
      "winery_id": null,
      "name": "House caponata",
      "name_translations": { "it": "Caponata della casa", "en": "House caponata" },
      "description": "Eggplant, celery, capers, olives",
      "description_translations": { "it": "Melanzane, ...", "en": "Eggplant, ..." },
      "price": 9.0,
      "allergens": ["sedano", "solfiti"],
      "is_active": true,
      "is_recommended": true,
      "display_order": 0,
      "winery": null
    }
  ],
  "meta": {
    "generated_at": "2026-05-14T11:42:18+00:00",
    "locale": "en",
    "total": 141,
    "page": 1,
    "per_page": 10,
    "last_page": 15
  }
}

Per il widget "piatti consigliati" usa direttamente ?is_recommended=1 — vedi la ricetta dedicata.


GET /items/{id}

Dettaglio singolo piatto.

curl https://ducatarocco.menufacile.it/api/v1/items/87

Response: oggetto MenuItem completo (14 campi). Per piatti di tipo vino, winery è eager-loaded con i dati della cantina.

ID inesistente → 404 HTML branded.


GET /restaurant

Dati anagrafici e impostazioni del ristorante (lo stesso oggetto settings esposto da /menu).

curl https://ducatarocco.menufacile.it/api/v1/restaurant

Response

{
  "success": true,
  "data": {
    "id": 1,
    "name": "Duca Tarocco",
    "slug": "ducatarocco",
    "logo_url": "https://ducatarocco.menufacile.it/storage/logos/duca-tarocco.svg",
    "cover_image_url": null,
    "cover_charge_text": "Coperto € 2",
    "allergen_info": "I piatti potrebbero contenere tracce...",
    "review_url": "https://g.page/r/...",
    "recommended_label": "Più Venduto",
    "business_name": "Ristorante Duca Tarocco S.r.l.",
    "vat_number": "IT01234567890",
    "address": "Via Roma 42, Ragusa",
    "phone": "+39 0932 123456",
    "email": "info@ducatarocco.it",
    "default_locale": "it",
    "supported_locales": ["it", "en"],
    "is_active": true
  },
  "meta": { "generated_at": "..." }
}

GET /theme

Configurazione visuale del menu (colori, font, logo, layout).

Response

{
  "success": true,
  "data": {
    "id": 1,
    "primary_color": "#C0AD8A",
    "secondary_color": "#8A7A5C",
    "accent_color": "#D4A574",
    "background_color": "#2B3C37",
    "text_color": "#F5F5F0",
    "font_family": "Playfair Display",
    "font_url": "/fonts/playfair-display.css",
    "border_radius": "8px",
    "layout_variant": "standard",
    "header_style": "centered",
    "footer_text": "Cucina aperta 19:30 — 23:00"
  },
  "meta": { "generated_at": "..." }
}

GET /allergens

Dizionario dei 14 allergeni regolamentati (Reg. UE 1169/2011), tradotti.

Query parameters

Parametro Tipo Default Descrizione
locale string it Lingua delle etichette

Esempio

curl "https://ducatarocco.menufacile.it/api/v1/allergens?locale=en"

Response

{
  "success": true,
  "data": [
    { "key": "cereali_glutine", "name": "Cereals containing gluten" },
    { "key": "crostacei",       "name": "Crustaceans" },
    { "key": "uova",            "name": "Eggs" },
    { "key": "pesce",           "name": "Fish" },
    { "key": "arachidi",        "name": "Peanuts" },
    { "key": "soia",            "name": "Soy" },
    { "key": "latte",           "name": "Milk" },
    { "key": "frutta_guscio",   "name": "Tree nuts" },
    { "key": "sedano",          "name": "Celery" },
    { "key": "senape",          "name": "Mustard" },
    { "key": "sesamo",          "name": "Sesame" },
    { "key": "solfiti",         "name": "Sulfites" },
    { "key": "lupini",          "name": "Lupins" },
    { "key": "molluschi",       "name": "Mollusks" }
  ],
  "meta": { "generated_at": "..." }
}

I key sono stabili (mai cambiano): usali per matchare gli allergeni nei piatti — item.allergens è un array di queste stesse key (es. ["sedano", "solfiti"]). Le key contengono underscore (cereali_glutine, frutta_guscio), non hyphen.


Endpoint admin (autenticati)

Le route POST/PUT/DELETE /api/v1/admin/* esistono e richiedono un token Sanctum con lo scope appropriato:

Gruppo Scope richiesto Endpoint
Scrittura menu menu:write POST/PUT/DELETE /admin/{categories,items,types,wineries}, PUT /admin/settings, PUT /admin/theme
Analytics analytics:read GET /admin/analytics/{overview,items,sections,allergens,insights}

Senza lo scope corretto la risposta è 403 Forbidden con {"message":"Invalid ability provided."}. Tutti gli admin sono limitati a 30 req/min/tenant+IP (vedi Rate limit). Vedi Autenticazione per come generare e usare un token.

ℹ️ La documentazione dettagliata di ogni endpoint admin (payload, response, validazione) è in arrivo. Per il momento questi endpoint sono usati principalmente dal pannello del ristorante; se devi automatizzarli scrivi a info@menufacile.it.

Hai bisogno di aiuto?

Scrivi a info@menufacile.it.