{
  "openapi": "3.1.0",
  "info": {
    "title": "Menumigo Public API",
    "version": "1.0.0",
    "summary": "Read-only public data for Menumigo restaurant menus and site content.",
    "description": "An unauthenticated, read-only JSON API intended for AI agents, assistants and integrators. It exposes the same information already published on menumigo.com pages: restaurant menus (categories, items, prices, allergens), the location and cuisine directories, and plan limits. No personal data, account data or analytics is exposed. Responses are cached at the edge; please be considerate with request volume.",
    "contact": {
      "name": "Menumigo",
      "url": "https://menumigo.com",
      "email": "contact@menumigo.com"
    },
    "license": {
      "name": "Data provided for informational use with attribution to menumigo.com"
    }
  },
  "servers": [{ "url": "https://menumigo.com" }],
  "paths": {
    "/api/public/restaurants/{slug}": {
      "get": {
        "operationId": "getRestaurantMenu",
        "summary": "Get a restaurant's public profile and full menu",
        "description": "Returns the restaurant profile, contact details, opening hours and the complete menu: every visible category with its items, prices, currency, EU-14 allergen tags, dietary tags and available translations. The slug is the path segment used by the public menu page at https://menumigo.com/{slug}.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Restaurant slug, e.g. \"my-restaurant\".",
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Restaurant and menu",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Restaurant" }
              }
            }
          },
          "404": {
            "description": "No active restaurant with that slug",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/public/locations": {
      "get": {
        "operationId": "listLocations",
        "summary": "List countries and cities with digital-menu landing pages",
        "responses": {
          "200": {
            "description": "Countries and cities",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "countries": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/Country" }
                    },
                    "cities": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/City" }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/public/cuisines": {
      "get": {
        "operationId": "listCuisines",
        "summary": "List cuisine types with digital-menu landing pages",
        "responses": {
          "200": {
            "description": "Cuisine types",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "cuisines": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/Cuisine" }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/public/plans": {
      "get": {
        "operationId": "listPlans",
        "summary": "List Menumigo subscription plans and their limits",
        "description": "Authoritative plan and limit data, generated from the same constants the application enforces. A limit of null means unlimited.",
        "responses": {
          "200": {
            "description": "Plans",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "pricingUrl": { "type": "string", "format": "uri" },
                    "signUpUrl": { "type": "string", "format": "uri" },
                    "trial": { "type": "string" },
                    "note": { "type": "string" },
                    "plans": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/Plan" }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": { "type": "string" },
          "message": { "type": "string" }
        }
      },
      "Restaurant": {
        "type": "object",
        "properties": {
          "slug": { "type": "string" },
          "name": { "type": "string" },
          "description": { "type": ["string", "null"] },
          "url": { "type": "string", "format": "uri" },
          "updatedAt": { "type": "string", "format": "date-time" },
          "currency": { "type": "string", "examples": ["EUR"] },
          "defaultLanguage": { "type": "string", "examples": ["en"] },
          "languages": { "type": "array", "items": { "type": "string" } },
          "cuisine": { "type": ["string", "null"] },
          "contact": {
            "type": "object",
            "properties": {
              "phone": { "type": ["string", "null"] },
              "address": { "type": ["string", "null"] },
              "city": { "type": ["string", "null"] },
              "postalCode": { "type": ["string", "null"] },
              "country": { "type": ["string", "null"] },
              "latitude": { "type": ["number", "null"] },
              "longitude": { "type": ["number", "null"] }
            }
          },
          "openingHours": {
            "type": ["object", "null"],
            "description": "Map of day abbreviation to opening range, e.g. { \"mon\": \"09:00-18:00\" }.",
            "additionalProperties": { "type": "string" }
          },
          "images": {
            "type": "object",
            "properties": {
              "logo": { "type": ["string", "null"], "format": "uri" },
              "banner": { "type": ["string", "null"], "format": "uri" }
            }
          },
          "ratings": {
            "type": "object",
            "properties": {
              "google": { "$ref": "#/components/schemas/Rating" },
              "tripadvisor": { "$ref": "#/components/schemas/Rating" }
            }
          },
          "categories": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/Category" }
          }
        }
      },
      "Rating": {
        "type": ["object", "null"],
        "properties": {
          "rating": { "type": "number" },
          "reviewCount": { "type": ["integer", "null"] }
        }
      },
      "Translations": {
        "type": "object",
        "description": "Keyed by language code, e.g. { \"pt\": { \"name\": \"...\", \"description\": \"...\" } }.",
        "additionalProperties": {
          "type": "object",
          "properties": {
            "name": { "type": "string" },
            "description": { "type": "string" }
          }
        }
      },
      "Category": {
        "type": "object",
        "properties": {
          "name": { "type": "string" },
          "description": { "type": ["string", "null"] },
          "translations": { "$ref": "#/components/schemas/Translations" },
          "items": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/MenuItem" }
          }
        }
      },
      "MenuItem": {
        "type": "object",
        "properties": {
          "name": { "type": "string" },
          "description": { "type": ["string", "null"] },
          "translations": { "$ref": "#/components/schemas/Translations" },
          "price": { "type": "number" },
          "compareAtPrice": { "type": ["number", "null"] },
          "currency": { "type": "string" },
          "imageUrl": { "type": ["string", "null"], "format": "uri" },
          "isAvailable": { "type": "boolean" },
          "badge": { "type": ["string", "null"] },
          "tags": {
            "type": "array",
            "items": { "type": "string" },
            "description": "Dietary/marketing tags, e.g. vegan, vegetarian, gluten-free, spicy."
          },
          "allergens": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "gluten",
                "crustaceans",
                "eggs",
                "fish",
                "peanuts",
                "soy",
                "milk",
                "nuts",
                "celery",
                "mustard",
                "sesame",
                "sulphites",
                "lupin",
                "molluscs"
              ]
            },
            "description": "EU 14 standard allergens present in the item."
          },
          "nutrition": { "type": ["object", "null"], "additionalProperties": true },
          "variants": {
            "type": ["array", "null"],
            "items": {
              "type": "object",
              "properties": {
                "name": { "type": "string" },
                "price": { "type": "number" }
              }
            }
          }
        }
      },
      "Country": {
        "type": "object",
        "properties": {
          "slug": { "type": "string" },
          "name": { "type": "string" },
          "language": { "type": "string" },
          "cities": { "type": "array", "items": { "type": "string" } },
          "url": { "type": "string", "format": "uri" }
        }
      },
      "City": {
        "type": "object",
        "properties": {
          "slug": { "type": "string" },
          "name": { "type": "string" },
          "country": { "type": "string" },
          "countryName": { "type": "string" },
          "language": { "type": "string" },
          "diningScene": { "type": ["string", "null"] },
          "url": { "type": "string", "format": "uri" }
        }
      },
      "Cuisine": {
        "type": "object",
        "properties": {
          "slug": { "type": "string" },
          "name": { "type": "string" },
          "namePlural": { "type": "string" },
          "tagline": { "type": "string" },
          "url": { "type": "string", "format": "uri" }
        }
      },
      "Plan": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "enum": ["free", "pro"] },
          "name": { "type": "string" },
          "description": { "type": "string" },
          "priceCurrency": { "type": "string", "examples": ["EUR"] },
          "pricing": {
            "type": "object",
            "description": "Amounts in major units (EUR), not cents.",
            "properties": {
              "monthly": { "type": "number" },
              "yearly": { "type": "number" },
              "yearlyPerMonth": { "type": "number" },
              "lifetime": { "type": "number" }
            }
          },
          "limits": {
            "type": "object",
            "description": "null means unlimited.",
            "properties": {
              "restaurants": { "type": ["integer", "null"] },
              "menuItems": { "type": ["integer", "null"] },
              "languages": { "type": ["integer", "null"] },
              "aiGenerationsPerMonth": { "type": ["integer", "null"] },
              "aiTranslationsPerMonth": { "type": ["integer", "null"] }
            }
          },
          "features": { "type": "array", "items": { "type": "string" } },
          "proOnlyFeatures": { "type": "array", "items": { "type": "string" } },
          "showsMenumigoBranding": { "type": "boolean" }
        }
      }
    }
  }
}
