API y agentes
Antonysia Helados publica su carta como datos, no solo como página. Si estás escribiendo un agente, un bot o una integración, esto es todo lo que hace falta: dos endpoints públicos, sin credenciales, de solo lectura.
La misma página en Markdown: /developers.md. Especificación: /openapi.json. Guía para agentes: /llms.txt.
Cuándo usar esta API
Sirve para contestar, con los números que cobra el sitio: qué sabores hay y cuáles son veganos, cuánto sale un pote o un combo, cuánto cuesta el envío y desde qué monto es sin cargo, si el local está abierto en este momento, si una localidad entra en la zona de reparto, y cuánto sale un pedido armado antes de hacerlo.
No sirve para crear pedidos ni para cobrar: no hay endpoint público que escriba nada. Un pedido se arma en la página de inicio y se confirma por WhatsApp con una persona. Tampoco somos un marketplace, no vendemos otras marcas, no hacemos envíos fuera del radio de 9 km y no hay venta mayorista publicada.
Autenticación
Ninguna. No hay API keys, no hay tokens y no hay registro, porque no hay nada que proteger: los dos endpoints devuelven la misma carta que cualquiera lee en la página, no reciben datos personales y no escriben en ningún lado. Pedir una credencial para leer un precio público sería un trámite sin contrapartida.
Por el mismo motivo no hay entorno de pruebas aparte: como ninguna llamada tiene efecto, producción es el sandbox. Podés golpear los endpoints todo lo que necesites mientras respetes la cuota de abajo.
Endpoints
| Método y ruta | Qué devuelve |
|---|---|
GET /api/v1/catalogo | La carta entera en un solo JSON: negocio, sabores, potes, promos, adicionales, medios de pago, envío, zona y horario con la hora de Buenos Aires. |
GET /.well-known/mcp | El manifiesto del servidor MCP: nombre, versión del protocolo, transporte y herramientas. |
POST /api/v1/mcp | El servidor MCP: JSON-RPC 2.0 sobre Streamable HTTP. Acepta initialize, ping, tools/list y tools/call. |
Cualquier página del sitio acepta además Accept: text/markdown y contesta la misma URL en Markdown en vez de HTML, con Vary: Accept.
Empezar en un minuto
La carta completa:
curl -s https://www.antonysiahelados.com.ar/api/v1/catalogo
El handshake de MCP y la lista de herramientas:
curl -s https://www.antonysiahelados.com.ar/api/v1/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Cotizar un pedido con las mismas reglas que cobra la página:
curl -s https://www.antonysiahelados.com.ar/api/v1/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{
"name":"cotizar_pedido",
"arguments":{"potes":[{"tamano":"k050","sabores":["Rocher","Pistacho Italiano"]}],"entrega":"envio"}}}'
Herramientas MCP
| Herramienta | Para qué |
|---|---|
listar_sabores | Los sabores con descripción, con filtro por categoría o solo veganos. |
consultar_precios | Potes, combos, adicionales, envío, umbral de envío gratis y mínimo. |
estado_del_local | Si está abierto ahora, en hora de Buenos Aires, y cuándo vuelve a abrir. |
zona_de_entrega | Si una localidad o dirección entra en el radio de reparto. |
cotizar_pedido | Subtotal, envío y total de un pedido armado. No lo crea ni lo reserva. |
Versionado y deprecación
La versión va en la ruta: /api/v1/… es la forma canónica, y toda respuesta trae la cabecera API-Version: 1.
- Las rutas sin versión (
/api/catalogoy/api/mcp) son alias permanentes de la v1. Siguen funcionando y no tienen retiro previsto. - Un cambio compatible (un campo nuevo, un sabor nuevo, un precio distinto) se hace sobre la v1 sin avisar. Tratá los objetos como extensibles: campos nuevos pueden aparecer en cualquier momento.
- Un cambio incompatible (sacar un campo, cambiar un tipo, renombrar una herramienta) estrena
/api/v2/…. La v1 no se rompe el mismo día. - El retiro se avisa en las respuestas, no solo en esta página: una ruta deprecada empieza a contestar
Deprecation(RFC 9745) con la fecha en que quedó obsoleta,Sunset(RFC 8594) con la fecha en que deja de responder, y unLinkconrel="deprecation"apuntando al aviso. Entre el primerDeprecationy elSunsethay como mínimo 180 días.
Hoy ninguna ruta está deprecada, así que ninguna respuesta trae esas cabeceras.
Cuotas
60 pedidos por minuto y por IP, contados por endpoint. Cada respuesta declara cuánto queda, en las dos formas del draft de la IETF, para que no haya que descubrir el límite chocándolo:
| Cabecera | Qué dice |
|---|---|
RateLimit-Limit | La cuota de la ventana: 60. |
RateLimit-Remaining | Cuántos pedidos quedan en la ventana en curso. |
RateLimit-Reset | Segundos hasta que la ventana se renueva. |
RateLimit-Policy | La política declarada, p. ej. "catalogo";q=60;w=60. |
RateLimit | El estado en campo estructurado, p. ej. "catalogo";r=59;t=60. |
Retry-After | Solo en el 429: cuántos segundos esperar. |
Una salvedad honesta: el contador vive en la memoria de la instancia que atiende y /api/v1/catalogo se cachea cinco minutos en el CDN, así que los números son una guía para autolimitarse, no un saldo exacto. El Retry-After del 429 sí es exacto.
Errores
Todo error de la API se contesta en application/problem+json (RFC 9457) con el status HTTP correcto (nunca un 200 con un error adentro) y nunca en HTML. Además de los campos de la RFC (type, title, status, detail, instance), cada error trae code, que es estable y está pensado para un switch, y pista, que dice cómo salir del error:
{
"type": "https://www.antonysiahelados.com.ar/developers#error-ruta-no-encontrada",
"title": "La ruta no existe",
"status": 404,
"detail": "No hay ningún endpoint en /api/sabores.",
"code": "ruta_no_encontrada",
"pista": "Los endpoints publicados están en https://www.antonysiahelados.com.ar/openapi.json. El catálogo completo es GET /api/v1/catalogo.",
"documentacion": "https://www.antonysiahelados.com.ar/developers",
"instance": "/api/sabores"
}
code | Status | Cuándo y qué hacer |
|---|---|---|
ruta_no_encontrada | 404 | Esa ruta no existe bajo /api/. El cuerpo lista los endpoints que sí existen: corregí la ruta, no reintentes. |
metodo_no_permitido | 405 | La ruta existe pero no con ese método. La cabecera Allow de la misma respuesta dice cuáles acepta. |
cuerpo_invalido | 400 | El cuerpo no es un JSON-RPC 2.0 válido, o llegó un lote (el protocolo ya no los admite). Arreglá el cuerpo, no reintentes igual. |
cuota_excedida | 429 | Se pasó la cuota. Esperá los segundos de Retry-After y reintentá; mirá las cabeceras RateLimit para no volver a chocarla. |
El endpoint MCP es la excepción prevista por su propia especificación: un error de protocolo se contesta como error JSON-RPC ({"jsonrpc":"2.0","id":…,"error":{"code":…,"message":…}}) con status 200, porque es lo que un cliente MCP espera. Los errores que no son de protocolo (cuota, método) salen igual en problem+json.
Cosas que conviene saber
- Los precios están en pesos argentinos, como enteros, sin centavos. El campo
monedalo dice:ARS. - El horario se calcula en hora de Buenos Aires (
America/Argentina/Buenos_Aires), no en la del servidor ni en la tuya.abiertoAhoracaduca: no lo caches más de unos minutos. - CORS abierto (
Access-Control-Allow-Origin: *) y sin cookies: podés llamar desde el navegador. - El nombre del sabor es la clave.
cotizar_pedidovalida contra la carta: mandá los nombres exactos que devuelvelistar_sabores. - Los precios cambian. No los copies a tu código: leelos del catálogo, que sale de la misma fuente que cobra el sitio.
Contacto técnico
Si algo de acá no funciona como está escrito, o necesitás un dato que la API no da, el canal es el mismo de siempre: WhatsApp +54 9 11 6241-9013. No hay soporte por correo electrónico.
Armar mi pedido