Digitalizar un menú
Un menú plastificado fotografiado en una mesa es el último formato sobre el que alguien querría construir una app de entregas o un comparador de precios, y sin embargo suele ser el único formato que existe. Este endpoint lee esa foto y devuelve cada plato, su descripción y su precio como entradas estructuradas, listas para poblar una base de datos de menú en vez de una hoja de cálculo que alguien tecleó a mano durante la noche.
Ejecútela online
Ejecute esto en nuestros servidores con su cuenta. Las herramientas gratuitas corren en su navegador; esta cobra de su saldo del KIT según el precio de arriba.
El conjunto de datos que nunca se digitalizó
La mayoría de los menús de restaurante existen solo como una tarjeta impresa, una lámina plastificada o una pizarra fotografiada, actualizados a mano cada vez que cambia un precio o un plato y nunca ingresados a ningún sistema más allá del terminal de punto de venta, si acaso. Toda plataforma que quiera listar los platos y precios reales de un restaurante, en vez de un PDF desactualizado de hace dos años, se topa con la misma tarea: convertir la fotografía de un menú en filas de datos.
Qué extrae el endpoint
Lee el nombre del plato, su descripción cuando el menú la incluye, y su precio, agrupando los ítems bajo los encabezados de sección que suele usar un menú, como entradas, platos fuertes o postres. Los diseños de varias columnas, las tipografías distintas para títulos de sección versus ítems, y los precios ubicados al lado o debajo del nombre de un plato forman parte de cómo lucen los menús reales, y la extracción está construida en torno a esa variabilidad y no a una sola plantilla ordenada.
Cómo maneja el desorden de los menús reales
Los menús son uno de los documentos menos estandarizados del uso diario: algunos listan precios con símbolo de moneda, otros asumen que el comensal ya sabe cuál es la moneda, algunos imprimen un solo precio y otros listan tamaños chico y grande uno junto al otro. El endpoint captura lo impreso tal como está impreso, así que un menú con precios por tamaño devuelve ambos precios ligados al mismo plato en vez de elegir uno y descartar el otro.
La solicitud en la práctica
Envía la foto a POST /ocr/menu y recibe un task_id de inmediato, ya que la digitalización corre de forma asíncrona detrás de escena. El menú estructurado llega mediante su webhook firmado o un enlace firmado válido por 24 horas, y una foto demasiado borrosa u oscura para interpretarse tras tres reintentos internos devuelve un error claro sin ningún cobro.
Dónde encaja dentro de un sistema mayor
Las plataformas de entrega lo usan para incorporar la oferta actual de un restaurante sin que un empleado teclee cada línea a mano, los comparadores de precios refrescan sus listados cada vez que un dueño envía una foto actualizada, y los operadores de franquicias estandarizan los datos de menú entre decenas de locales que cada uno imprime su propia tarjeta física.
Qué puede hacer con ella
Incorporación de un restaurante a una plataforma de entregas
Un nuevo restaurante socio envía la foto de su menú impreso y la plataforma completa platos, descripciones y precios sin que el personal retipee la tarjeta.
Mantener listados al día tras un cambio de precios
Un dueño fotografía el menú actualizado tras una revisión de precios, y un sitio comparador refresca su listado en lugar de mostrar precios desactualizados durante meses.
Estandarización de datos entre locales de una franquicia
Un operador de franquicia digitaliza los menús impresos ligeramente distintos de cada sucursal en un catálogo de producto consistente.
Construcción de un archivo de menús buscable
Un blog gastronómico convierte los menús fotografiados de restaurantes reseñados en listados de platos buscables que los lectores pueden explorar por cocina o precio.
Preguntas frecuentes
¿Qué hace una API para digitalizar menús?
Lee la foto de un menú de restaurante y devuelve el nombre, la descripción y el precio de cada plato como datos estructurados, agrupados por sección del menú.
¿Hay plan gratuito?
No hay capa gratuita: las capas gratis se abusan y ralentizan a todos. El acceso funciona con un saldo prepago de ForHosting KIT: se recarga desde $10.00 (no caduca) y cada solicitud se cobra a su precio publicado, así que una llamada sin saldo devuelve HTTP 402. Sin suscripción, sin tokens ni créditos inventados, y una tarea fallida no se cobra.
¿Cuánto cuesta por foto de menú?
$0.010 por solicitud más $0.0575 por imagen, y solo se cobra por tareas que se completan con éxito.
¿Maneja menús con varios precios por plato?
Sí, cuando un menú lista más de un precio para un plato, como tamaños chico y grande, ambos se capturan y se vinculan a ese mismo plato en vez de reducirse a uno solo.
¿Qué pasa si el menú tiene varias columnas o secciones?
Los diseños con varias columnas y encabezados de sección como entradas, platos fuertes o postres son parte normal del diseño de un menú, y la extracción agrupa los ítems bajo su sección correcta.
¿Cómo recibo el menú digitalizado?
Llama a POST /ocr/menu para recibir un task_id de inmediato, y luego obtiene el menú estructurado por webhook firmado o por un enlace firmado válido durante 24 horas.
¿Qué pasa con un menú borroso o una pizarra escrita a mano?
El sistema reintenta internamente hasta tres veces; si la foto sigue sin poder interpretarse con fiabilidad, recibe un error claro y ningún cobro.
¿Puedo digitalizar muchos menús de restaurante por lote?
Sí, cada foto de menú se procesa como su propia tarea asíncrona, así que puede enviar un lote y recoger cada resultado conforme termina.
Para desarrolladores — acceso por API
Todo lo de esta página está disponible por programación. Esta sección es para equipos que quieren integrarlo en sus sistemas; el resto puede usar la herramienta de arriba sin más.
Endpoint de API
¿Prefiere automatizarlo? Un POST autenticado crea la tarea; el resultado llega por webhook o enlace firmado. La misma capacidad también se ejecuta aquí en la web, y pronto desde nuestra app, el email y Telegram.
Llámela desde su stack
curl -X POST https://api.kit.forhosting.com/ocr/menu \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"image":"https://ejemplo.com/imagen.jpg"}'const res = await fetch("https://api.kit.forhosting.com/ocr/menu", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"image": "https://ejemplo.com/imagen.jpg"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/ocr/menu",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"image": "https://ejemplo.com/imagen.jpg"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/ocr/menu", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"image":"https://ejemplo.com/imagen.jpg"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"image":"https://ejemplo.com/imagen.jpg"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/ocr/menu", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Ejemplo de solicitud
{
"image": "https://ejemplo.com/imagen.jpg"
}Ejemplo de respuesta
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "ocr.menu",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}La API es asíncrona: la llamada devuelve un task_id al instante y el resultado llega por webhook. El polling está limitado a 1 req/s por tarea.
Precio
Precio publicado — sin tokens ni créditos inventados. Una tarea fallida no se cobra.
Límites
max_mb | 25 |
max_pages | 10 |
Errores
| HTTP | Código | Significado |
|---|---|---|
401 | unauthorized | API key ausente o inválida. |
402 | insufficient_balance | El saldo no cubre el precio de la tarea. |
404 | unknown_type | El tipo de tarea no existe. |
429 | rate_limited | Demasiadas peticiones. Use el webhook en vez de sondear. |
422 | task_failed | La tarea falló tras 3 reintentos. No se cobra. |