> ## Documentation Index
> Fetch the complete documentation index at: https://api-doc.xmenu.it/llms.txt
> Use this file to discover all available pages before exploring further.

# Importazione menu

> Importa o aggiorna la struttura del menu includendo categorie, prodotti e opzioni.

<Badge color="blue" icon="key">`write:menu`</Badge>

<Note>
  Ogni entità include il campo `ext_id`, che deve essere valorizzato con il proprio identificativo univoco.

  Se non esiste già un elemento della stessa entità con questo `ext_id`, ne verrà creato uno nuovo. Se invece l'elemento esiste, il suo contenuto verrà aggiornato.

  L'ambito di univocità di tale ID è interno dell'ambiente definito dal Client ID (`X-Client-Id`), ovvero lo stesso `ext_id` importato da Client ID diversi, genererà elementi distinti.

  Gli `ext_id` di `options` e `option_values` possono essere univoci in tale ambiente o solo all'interno del rispettivo elemento parent (categoria/prodotto per le `options`, opzione per gli `option_values`).
</Note>


## OpenAPI

````yaml openapi-it.json POST /menu/import
openapi: 3.1.0
info:
  title: xMenu API
  description: API Pubblica xMenu - Endpoint REST e notifiche webhook
  version: 1.0.0
servers:
  - url: https://app.xmenu.it/api
    description: xMenu API Production
security: []
paths:
  /menu/import:
    post:
      tags:
        - Importazione menu
      summary: Importazione menu
      description: >-
        Importa o aggiorna la struttura del menu includendo categorie, prodotti,
        opzioni e prezzi utilizzando il sistema di ID esterni. Il sistema
        utilizza ID esterni (ext_id) per identificare le entità. Durante
        l'importazione, se esiste un elemento con lo stesso ext_id, viene
        aggiornato; altrimenti, ne viene creato uno nuovo. L'univocità degli ID
        è circoscritta all'ambiente definito dal Client ID.
      operationId: menuImport
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MenuImportRequest'
      responses:
        '200':
          description: Risposta importazione menu
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MenuImportResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
      security:
        - clientId: []
          clientSecret: []
        - oauth2: []
components:
  schemas:
    MenuImportRequest:
      type: object
      required:
        - pos_uid
        - update_mode
      properties:
        pos_uid:
          type: string
          description: Identificatore punto vendita
        update_mode:
          type: string
          enum:
            - replace
            - merge
          description: |-
            Modalità di aggiornamento:
            - `replace` = Sostituzione completa
            - `merge` = Aggiunta di nuovi elementi
        categories:
          type: array
          items:
            $ref: '#/components/schemas/ImportCategory'
          description: Array di categorie. Obbligatorio se update_mode = replace
        products:
          type: array
          items:
            $ref: '#/components/schemas/ImportProduct'
          description: Array di prodotti. Obbligatorio se update_mode = replace
    MenuImportResponse:
      type: object
      required:
        - success
      properties:
        success:
          type: boolean
          description: >-
            Risultato dell'operazione: `true` se ha avuto successo, `false` se
            fallita
        error:
          type: string
          description: >-
            Codice errore se l'operazione è fallita. Valori possibili:

            - `IMPORT_ERROR` = Errore durante l'importazione (consultare il
            parametro message per i dettagli)


            Vedi [Codici errore](/docs/it/overview/error-codes) per i codici di
            errore generali che possono verificarsi.
        message:
          type: string
          description: Descrizione errore se l'importazione non è andata a buon fine
    ImportCategory:
      type: object
      required:
        - ext_id
      properties:
        ext_id:
          type: string
          description: Identificatore esterno univoco
        name:
          type: string
          description: >-
            Nome categoria. Obbligatorio solo durante la creazione di un nuovo
            elemento
        description:
          type: string
          description: Descrizione categoria
        image:
          type: string
          description: URL immagine
        hidden:
          type: boolean
          description: |-
            Stato visibilità:
            - `false` = Visibile
            - `true` = Archiviata
        position:
          type: integer
          description: Ordine di visualizzazione (inizia da 1)
        options:
          type: array
          items:
            $ref: '#/components/schemas/ImportOption'
          description: Opzioni a livello di categoria
    ImportProduct:
      type: object
      required:
        - ext_id
      properties:
        ext_id:
          type: string
          description: Identificatore esterno univoco
        category_ext_id:
          type: string
          description: >-
            Riferimento esterno categoria padre. Obbligatorio solo durante la
            creazione di un nuovo elemento
        name:
          type: string
          description: >-
            Nome prodotto. Obbligatorio solo durante la creazione di un nuovo
            elemento
        description:
          type: string
          description: Descrizione prodotto
        price:
          type: number
          description: Prezzo base
        prices_table:
          type: object
          description: >-
            Tabella prezzi specifica per location / metodo di consegna, con la
            seguente struttura:

            ```javascript

            {
               "": { // tutte le location
                  "0": prezzo0, // ritiro presso ristorante
                  "1": prezzo1, // consegna a domicilio
                  ... // prezzi per altri metodi di consegna
               },
               "subrestaurantUid1": { // Location 1
                  "0": prezzo0,
                  "1": prezzo1,
                  ...
               },
               ...
            }

            ```


            **Codici metodo di consegna:**

            - `"0"` = Ritiro presso ristorante

            - `"1"` = Consegna a domicilio

            - `"0t"` = Ordinazione al tavolo

            - `"0mt"` = Menu digitale

            - `"20"` = Ritiro presso punto di consegna

            - `"0e-{id}"` = Evento

            - `"dcf-{id}"` = Metodo di consegna personalizzato
          additionalProperties:
            type: object
            additionalProperties:
              type: number
        image:
          type: string
          description: URL immagine
        allergens:
          type: array
          items:
            type: string
          description: |-
            Lista degli allergeni. Valori possibili:
            - `gluten` = 1 - Glutine
            - `crustaceans` = 2 - Crostacei
            - `eggs` = 3 - Uova
            - `fish` = 4 - Pesce
            - `peanuts` = 5 - Arachidi
            - `soya` = 6 - Soia
            - `milk` = 7 - Latte
            - `nuts` = 8 - Frutta a guscio
            - `celery` = 9 - Sedano
            - `mustard` = 10 - Senape
            - `sesame` = 11 - Sesamo
            - `sulphites` = 12 - Solfiti
            - `lupin` = 13 - Lupini
            - `molluscs` = 14 - Molluschi
            - `freezer` = Congelato e surgelato
        symbols:
          type: array
          items:
            type: string
          description: |-
            Lista dei simboli. Valori possibili:
            - `new` = New
            - `bestseller` = Best seller
            - `vegan` = Vegano
            - `vegetarian` = Vegetariano
            - `spicy` = Piccante
            - `pizza` = Pizza
            - `burger` = Panino
            - `chips` = Patatine
            - `icecream` = Gelato
            - `sweets` = Dolci
            - `drink` = Bibita
            - `freshfish` = Pesce fresco
            - `cookedfish` = Pesce cotto
        suggested:
          type: boolean
          description: >-
            Se il prodotto è contrassegnato come consigliato (mostra il badge
            'Consigliato' e mette in risalto il prodotto nel menu)
        price_sale_alert:
          type: boolean
          description: >-
            Se il prodotto è in evidenza (mostrato in risalto quando l'utente
            inizia a comporre il carrello)
        price_sale_badge:
          type: integer
          description: >-
            Testo promozionale mostrato nella scheda prodotto quando
            `price_sale_alert` è `true`. Valori possibili:

            - `0` = In Promozione

            - `1` = Promo del Giorno

            - `2` = Quando ti ricapita di mangiarlo scontato?

            - `3` = Ma perché perderselo?

            - `4` = Quando ti ricapita un'occasione così?

            - `5` = Promo della Settimana

            - `6` = Promo del Mese

            - `7` = Da non crederci!

            - `8` = Speciale Black Friday

            - `9` = L'hai già provato?
        checkout_selling:
          type: boolean
          description: Se il prodotto viene proposto al checkout come cross selling
        hidden:
          type: boolean
          description: |-
            Stato visibilità:
            - `false` = Visibile
            - `true` = Archiviato
        position:
          type: integer
          description: Ordine di visualizzazione
        inherits_options:
          type: string
          enum:
            - sync
            - 'yes'
            - none
          description: >-
            Ereditarietà opzioni dalla categoria:

            - `yes` = Ereditarietà completa — il prodotto mostra solo le opzioni
            della categoria; le opzioni specifiche del prodotto vengono ignorate

            - `sync` = Ereditarietà parziale — il prodotto mostra sia le opzioni
            della categoria che le proprie opzioni specifiche

            - `none` = Nessuna ereditarietà — il prodotto mostra solo le proprie
            opzioni specifiche
        options:
          type: array
          items:
            $ref: '#/components/schemas/ImportOption'
          description: Opzioni specifiche del prodotto
    ImportOption:
      type: object
      required:
        - ext_id
      properties:
        ext_id:
          type: string
          description: Identificatore esterno univoco
        name:
          type: string
          description: >-
            Titolo opzione. Obbligatorio solo durante la creazione di un nuovo
            elemento
        short_name:
          type: string
          description: Titolo breve
        type:
          type: string
          enum:
            - single
            - multiple
          description: |-
            Tipo di selezione:
            - `single` = Scelta singola
            - `multiple` = Scelte multiple consentite
        min_selectable:
          type: integer
          description: Selezioni minime (per tipo `multiple`)
        max_selectable:
          type: integer
          description: Selezioni massime (per tipo `multiple`)
        max_quantity:
          type: integer
          description: Quantità massima per valore
        note:
          type: string
          description: Note
        hidden:
          type: boolean
          description: |-
            Stato visibilità:
            - `false` = Visibile
            - `true` = Archiviata
        position:
          type: integer
          description: Ordine di visualizzazione
        primary:
          type: boolean
          description: |-
            Flag opzione primaria (solo per tipo `single`):
            - `false` = Non primaria
            - `true` = Opzione primaria
        first_default:
          type: boolean
          description: |-
            Comportamento selezione predefinita (solo per tipo `single`):
            - `false` = L'utente deve selezionare
            - `true` = Primo valore usato come predefinito
        show_caption:
          type: boolean
          description: |-
            Impostazione visualizzazione carrello (solo per tipo `single`):
            - `false` = Nascondi nel carrello
            - `true` = Mostra nel carrello
        print_caption:
          type: boolean
          description: |-
            Comportamento stampa:
            - `false` = Ometti dalla stampa ordine
            - `true` = Includi nella stampa
        option_values:
          type: array
          items:
            $ref: '#/components/schemas/ImportOptionValue'
          description: Array di valori opzione
    ImportOptionValue:
      type: object
      required:
        - ext_id
      properties:
        ext_id:
          type: string
          description: Identificatore esterno univoco
        name:
          type: string
          description: >-
            Nome valore. Obbligatorio solo durante la creazione di un nuovo
            elemento
        short_name:
          type: string
          description: Nome breve
        price_operator:
          type: string
          enum:
            - +
            - '-'
            - '*'
            - /
          description: |-
            Operatore modifica prezzo:
            - `+` = Addizione
            - `-` = Sottrazione
            - `*` = Moltiplicazione
            - `/` = Divisione
        price_operand:
          type: number
          description: Importo modifica prezzo
        hidden:
          type: boolean
          description: |-
            Stato visibilità:
            - `false` = Visibile
            - `true` = Archiviato
        checked_default:
          type: boolean
          description: |-
            Flag preselezionato:
            - `false` = Non preselezionato
            - `true` = Preselezionato per impostazione predefinita
        position:
          type: integer
          description: Ordine di visualizzazione
        restrict_to_primary_value_uids:
          type: array
          items:
            type: string
          nullable: true
          description: >-
            UID dei valori dell'opzione principale per cui questo valore è
            disponibile:

            - `null` = Nessuna restrizione (sempre disponibile)

            - `[]` = Restrizione attiva, ma nessun valore principale ammesso
            (mai disponibile)

            - `["uid1", ...]` = Disponibile solo quando è selezionato uno di
            questi valori dell'opzione principale


            Gli UID referenziati devono appartenere all'opzione principale
            all'interno dello stesso prodotto o categoria.
  responses:
    Unauthorized:
      description: Autenticazione fallita.
      content:
        application/json:
          schema:
            oneOf:
              - type: object
                description: >-
                  Formato errore standard (quando si usa autenticazione API Key
                  o Client ID/Secret)
                required:
                  - success
                  - error
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    description: Sempre false per gli errori
                  error:
                    type: string
                    enum:
                      - RESTAURANT_NOT_FOUND
                      - INVALID_KEY
                      - INVALID_AUTH
                    description: Codice errore
                  message:
                    type: string
                    description: Descrizione errore leggibile
              - type: object
                description: >-
                  Formato errore OAuth (quando si usa l'autenticazione Bearer
                  token)
                required:
                  - error
                properties:
                  error:
                    type: string
                    enum:
                      - invalid_token
                      - invalid_request
                    description: Codice errore OAuth (RFC 6749)
                  error_description:
                    type: string
                    description: Descrizione errore leggibile
          examples:
            standard:
              summary: Formato errore standard (API Key / Client ID+Secret)
              value:
                success: false
                error: INVALID_KEY
                message: La chiave API fornita non è valida
            oauth:
              summary: Formato errore OAuth (Bearer token)
              value:
                error: invalid_token
                error_description: Access token non valido o scaduto
    Forbidden:
      description: Autorizzazione fallita - permessi insufficienti o accesso negato.
      content:
        application/json:
          schema:
            oneOf:
              - type: object
                description: >-
                  Formato errore standard (quando si usa autenticazione API Key
                  o Client ID/Secret)
                required:
                  - success
                  - error
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    description: Sempre false per gli errori
                  error:
                    type: string
                    enum:
                      - API_DISABLED
                      - INSUFFICIENT_SCOPE
                      - UNAUTHORIZED
                    description: Codice errore
                  message:
                    type: string
                    description: Descrizione errore leggibile
              - type: object
                description: >-
                  Formato errore OAuth (quando si usa l'autenticazione Bearer
                  token)
                required:
                  - error
                properties:
                  error:
                    type: string
                    enum:
                      - insufficient_scope
                      - invalid_request
                    description: Codice errore OAuth (RFC 6749)
                  error_description:
                    type: string
                    description: Descrizione errore leggibile
          examples:
            standard:
              summary: Formato errore standard (API Key / Client ID+Secret)
              value:
                success: false
                error: API_DISABLED
                message: L'accesso API non è abilitato per il ristorante
            oauth:
              summary: Formato errore OAuth (Bearer token)
              value:
                error: insufficient_scope
                error_description: 'Permessi mancanti richiesti: write:orders'
  securitySchemes:
    clientId:
      type: apiKey
      in: header
      name: X-Client-Id
      description: >-
        Client ID per l'autenticazione API Client (deve essere usato insieme al
        Client Secret)
    clientSecret:
      type: apiKey
      in: header
      name: X-Client-Secret
      description: >-
        Client Secret per l'autenticazione API Client (deve essere usato insieme
        al Client ID)
    oauth2:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: https://app.xmenu.it/oauth/token
          scopes: {}
      description: >-
        Autenticazione OAuth 2.0 utilizzando il flusso client credentials. Il
        token di accesso deve essere incluso nell'header Authorization come
        Bearer token.

````