{"openapi":"3.1.0","info":{"title":"Ventamatic — Conector POS (MCP + REST)","version":"1.0.0","description":"Conector del POS Ventamatic: punto de venta, kioscos y vending en Guatemala, con e-factura FEL. Expone la misma capacidad por dos transportes: herramientas MCP para agentes de IA (Claude, ChatGPT) y una API REST para integradores, más webhooks salientes firmados. Autorización OAuth 2.1 (protected resource, RFC 9728 + RFC 8707).","contact":{"name":"Ventamatic","url":"https://ventamatic.com"}},"servers":[{"url":"https://api.ventamatic.com"}],"tags":[{"name":"MCP","description":"Endpoint JSON-RPC para agentes de IA."},{"name":"Webhooks","description":"Gestión de suscripciones de webhook saliente."}],"paths":{"/mcp":{"post":{"tags":["MCP"],"summary":"Endpoint MCP (JSON-RPC 2.0)","description":"Punto único del servidor MCP. Métodos: initialize, tools/list, tools/call, server/discover. Requiere un access token OAuth 2.1 (Bearer) emitido para este recurso. Descubrí el flujo en /.well-known/oauth-protected-resource.","security":[{"oauth2":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Resultado JSON-RPC."},"401":{"description":"Falta token o inválido (WWW-Authenticate apunta al AS)."}}}},"/.well-known/oauth-protected-resource":{"get":{"tags":["MCP"],"summary":"Protected Resource Metadata (RFC 9728)","responses":{"200":{"description":"Documento PRM."}}}},"/api/v1/mcp/webhooks/subscriptions":{"get":{"tags":["Webhooks"],"summary":"Listar suscripciones","security":[{"session":[]}],"responses":{"200":{"description":"Lista (sin secreto)."}}},"post":{"tags":["Webhooks"],"summary":"Crear suscripción","security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewSubscription"}}}},"responses":{"201":{"description":"Creada; el secreto se devuelve UNA vez."},"402":{"description":"El plan no incluye webhooks."},"409":{"description":"Se alcanzó el tope del plan."}}}},"/api/v1/mcp/webhooks/subscriptions/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"tags":["Webhooks"],"summary":"Detalle de suscripción","security":[{"session":[]}],"responses":{"200":{"description":"OK"},"404":{"description":"No existe"}}},"patch":{"tags":["Webhooks"],"summary":"Actualizar (enabled/events/url)","security":[{"session":[]}],"responses":{"200":{"description":"OK"}}},"delete":{"tags":["Webhooks"],"summary":"Eliminar","security":[{"session":[]}],"responses":{"200":{"description":"Borrada"}}}},"/api/v1/mcp/webhooks/subscriptions/{id}/rotate-secret":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"tags":["Webhooks"],"summary":"Rotar secreto","security":[{"session":[]}],"responses":{"200":{"description":"Nuevo secreto (una vez)."}}}},"/api/v1/mcp/webhooks/subscriptions/{id}/deliveries":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"tags":["Webhooks"],"summary":"Log de entregas","security":[{"session":[]}],"responses":{"200":{"description":"Entregas recientes."}}}},"/api/v1/mcp/webhooks/deliveries/{id}/replay":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"tags":["Webhooks"],"summary":"Reencolar una entrega (replay)","security":[{"session":[]}],"responses":{"200":{"description":"Reencolada."}}}}},"webhooks":{"order.created":{"post":{"summary":"Evento order.created","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `order.created`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"order.created"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"order.updated":{"post":{"summary":"Evento order.updated","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `order.updated`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"order.updated"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"order.paid":{"post":{"summary":"Evento order.paid","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `order.paid`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"order.paid"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"order.fulfilled":{"post":{"summary":"Evento order.fulfilled","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `order.fulfilled`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"order.fulfilled"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"order.cancelled":{"post":{"summary":"Evento order.cancelled","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `order.cancelled`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"order.cancelled"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"order.refunded":{"post":{"summary":"Evento order.refunded","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `order.refunded`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"order.refunded"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"payment.created":{"post":{"summary":"Evento payment.created","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `payment.created`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"payment.created"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"payment.completed":{"post":{"summary":"Evento payment.completed","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `payment.completed`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"payment.completed"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"payment.failed":{"post":{"summary":"Evento payment.failed","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `payment.failed`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"payment.failed"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"payment.refunded":{"post":{"summary":"Evento payment.refunded","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `payment.refunded`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"payment.refunded"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"catalog.item.created":{"post":{"summary":"Evento catalog.item.created","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `catalog.item.created`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"catalog.item.created"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"catalog.item.updated":{"post":{"summary":"Evento catalog.item.updated","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `catalog.item.updated`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"catalog.item.updated"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"catalog.item.deleted":{"post":{"summary":"Evento catalog.item.deleted","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `catalog.item.deleted`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"catalog.item.deleted"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"catalog.published":{"post":{"summary":"Evento catalog.published","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `catalog.published`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"catalog.published"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"inventory.count.updated":{"post":{"summary":"Evento inventory.count.updated","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `inventory.count.updated`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"inventory.count.updated"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"inventory.low":{"post":{"summary":"Evento inventory.low","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `inventory.low`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"inventory.low"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"inventory.out_of_stock":{"post":{"summary":"Evento inventory.out_of_stock","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `inventory.out_of_stock`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"inventory.out_of_stock"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"inventory.restocked":{"post":{"summary":"Evento inventory.restocked","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `inventory.restocked`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"inventory.restocked"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"customer.created":{"post":{"summary":"Evento customer.created","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `customer.created`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"customer.created"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"customer.updated":{"post":{"summary":"Evento customer.updated","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `customer.updated`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"customer.updated"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"loyalty.points.accrued":{"post":{"summary":"Evento loyalty.points.accrued","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `loyalty.points.accrued`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"loyalty.points.accrued"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"loyalty.reward.redeemed":{"post":{"summary":"Evento loyalty.reward.redeemed","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `loyalty.reward.redeemed`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"loyalty.reward.redeemed"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"device.online":{"post":{"summary":"Evento device.online","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `device.online`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"device.online"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"device.offline":{"post":{"summary":"Evento device.offline","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `device.offline`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"device.offline"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"device.low_data":{"post":{"summary":"Evento device.low_data","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `device.low_data`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"device.low_data"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"vending.dispensed":{"post":{"summary":"Evento vending.dispensed","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `vending.dispensed`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"vending.dispensed"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"vending.dispense_failed":{"post":{"summary":"Evento vending.dispense_failed","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `vending.dispense_failed`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"vending.dispense_failed"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"fel.certified":{"post":{"summary":"Evento fel.certified","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `fel.certified`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"fel.certified"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"fel.certification_failed":{"post":{"summary":"Evento fel.certification_failed","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `fel.certification_failed`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"fel.certification_failed"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"fel.voided":{"post":{"summary":"Evento fel.voided","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `fel.voided`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"fel.voided"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"channel.order.received":{"post":{"summary":"Evento channel.order.received","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `channel.order.received`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"channel.order.received"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"channel.store.paused":{"post":{"summary":"Evento channel.store.paused","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `channel.store.paused`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"channel.store.paused"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"tenant.connected":{"post":{"summary":"Evento tenant.connected","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `tenant.connected`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"tenant.connected"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"tenant.disconnected":{"post":{"summary":"Evento tenant.disconnected","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `tenant.disconnected`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"tenant.disconnected"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}},"connection.error":{"post":{"summary":"Evento connection.error","description":"Ventamatic hace POST a tu endpoint suscrito cuando ocurre `connection.error`. Verificá la firma con los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` (esquema Standard Webhooks). Respondé 2xx rápido para confirmar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"const":"connection.error"}}}]}}}},"responses":{"2XX":{"description":"Recibido (ack). Cualquier no-2xx dispara reintento con backoff."}}}}},"components":{"securitySchemes":{"oauth2":{"type":"oauth2","description":"OAuth 2.1 Authorization Code + PKCE. El recurso es <base>/mcp.","flows":{"authorizationCode":{"authorizationUrl":"https://api.ventamatic.com/oauth/authorize","tokenUrl":"https://api.ventamatic.com/oauth/token","scopes":{"ventas:leer":"ventas:leer","catalogo:leer":"catalogo:leer","inventario:leer":"inventario:leer","kioskos:leer":"kioskos:leer","pagos:leer":"pagos:leer","ordenes:leer":"ordenes:leer","catalogo:escribir":"catalogo:escribir","inventario:escribir":"inventario:escribir","webhooks:administrar":"webhooks:administrar"}}}},"session":{"type":"http","scheme":"bearer","description":"Sesión del backoffice (JWT) para la API de gestión."}},"schemas":{"WebhookEnvelope":{"type":"object","required":["id","type","timestamp","api_version","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Id único del evento. Clave de deduplicación: los reintentos traen el mismo id."},"type":{"type":"string","description":"Tipo de evento, ej: order.paid."},"timestamp":{"type":"string","format":"date-time"},"api_version":{"type":"string","example":"v1"},"data":{"type":"object","description":"Cuerpo del evento, según su tipo."}}},"NewSubscription":{"type":"object","required":["url","events"],"properties":{"url":{"type":"string","format":"uri","description":"https del endpoint receptor."},"events":{"type":"array","items":{"type":"string","enum":["*","order.created","order.updated","order.paid","order.fulfilled","order.cancelled","order.refunded","payment.created","payment.completed","payment.failed","payment.refunded","catalog.item.created","catalog.item.updated","catalog.item.deleted","catalog.published","inventory.count.updated","inventory.low","inventory.out_of_stock","inventory.restocked","customer.created","customer.updated","loyalty.points.accrued","loyalty.reward.redeemed","device.online","device.offline","device.low_data","vending.dispensed","vending.dispense_failed","fel.certified","fel.certification_failed","fel.voided","channel.order.received","channel.store.paused","tenant.connected","tenant.disconnected","connection.error"]},"minItems":1},"description":{"type":"string"}}}}},"x-mcp-tools":[{"name":"ventamatic_resumen_de_ventas","title":"Resumen de ventas","description":"Devuelve el total vendido, la cantidad de ordenes y el ticket promedio de un rango de fechas. Usala para preguntas como '¿cuánto vendí ayer?', '¿cómo nos fue esta semana?' o para comparar dos periodos llamandola dos veces. Es la tool por defecto para cualquier pregunta sobre cuanto se vendio. NO la uses para saber QUE productos se vendieron: para eso esta ventamatic_productos_mas_vendidos.","inputSchema":{"type":"object","properties":{"from":{"type":"string","description":"Fecha de inicio, inclusive, en formato AAAA-MM-DD. Ejemplo: 2026-07-01"},"to":{"type":"string","description":"Fecha de fin, inclusive, en formato AAAA-MM-DD. Ejemplo: 2026-07-31"}},"required":["from","to"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"ventamatic_ventas_por_hora","title":"Ventas por hora de un dia","description":"Distribucion de las ventas por hora dentro de UN dia concreto. Usala para preguntas sobre horas pico, cuando conviene reforzar personal, o a que hora rinde mas el local. Toma un solo dia, no un rango: si te preguntan por varios dias, llamala una vez por dia o usa ventamatic_resumen_de_ventas para el total del periodo.","inputSchema":{"type":"object","properties":{"date":{"type":"string","description":"El dia a analizar, en formato AAAA-MM-DD. Ejemplo: 2026-07-31"}},"required":["date"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"ventamatic_productos_mas_vendidos","title":"Productos mas vendidos","description":"Ranking de productos por cantidad vendida en un rango. Usala para '¿qué es lo que más se vende?', '¿cuáles son mis mejores platos?' o para decidir que promocionar. Si te preguntan por el margen o la rentabilidad y no por el volumen, usa ventamatic_rentabilidad_por_producto.","inputSchema":{"type":"object","properties":{"from":{"type":"string","description":"Fecha de inicio, inclusive, en formato AAAA-MM-DD. Ejemplo: 2026-07-01"},"to":{"type":"string","description":"Fecha de fin, inclusive, en formato AAAA-MM-DD. Ejemplo: 2026-07-31"},"limit":{"type":"integer","minimum":1,"maximum":100,"description":"Cuantos productos devolver. Por defecto 10."}},"required":["from","to"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"ventamatic_ventas_por_categoria","title":"Ventas por categoria","description":"Total vendido agrupado por categoria del menu o catalogo, en un rango de fechas. Usala para entender que familia de productos sostiene la venta: bebidas contra comida, por ejemplo.","inputSchema":{"type":"object","properties":{"from":{"type":"string","description":"Fecha de inicio, inclusive, en formato AAAA-MM-DD. Ejemplo: 2026-07-01"},"to":{"type":"string","description":"Fecha de fin, inclusive, en formato AAAA-MM-DD. Ejemplo: 2026-07-31"}},"required":["from","to"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"ventamatic_rentabilidad_por_producto","title":"Rentabilidad por producto","description":"Margen y utilidad por producto en un rango. Usala cuando la pregunta sea sobre GANANCIA, no sobre volumen: '¿qué me deja más?', '¿cuál es mi margen?', '¿qué producto conviene empujar?'. Un producto puede vender mucho y dejar poco; no confundas esta tool con ventamatic_productos_mas_vendidos.","inputSchema":{"type":"object","properties":{"from":{"type":"string","description":"Fecha de inicio, inclusive, en formato AAAA-MM-DD. Ejemplo: 2026-07-01"},"to":{"type":"string","description":"Fecha de fin, inclusive, en formato AAAA-MM-DD. Ejemplo: 2026-07-31"}},"required":["from","to"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"ventamatic_ventas_de_kioskos","title":"Ventas de kioskos y vending","description":"Ventas de las maquinas de vending y kioskos de autoservicio en un rango de fechas. Usala solo para preguntas sobre maquinas desatendidas. Para el punto de venta de un restaurante o local atendido, usa ventamatic_resumen_de_ventas.","inputSchema":{"type":"object","properties":{"from":{"type":"string","description":"Fecha de inicio, inclusive, en formato AAAA-MM-DD. Ejemplo: 2026-07-01"},"to":{"type":"string","description":"Fecha de fin, inclusive, en formato AAAA-MM-DD. Ejemplo: 2026-07-31"},"machineId":{"type":"string","description":"Opcional. UUID de una maquina concreta. Si se omite, devuelve todas las del tenant."}},"required":["from","to"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"ventamatic_listar_productos","title":"Listar productos del catálogo","description":"Lista los productos del menú/catálogo con su precio, categoría y estado. Usala para '¿qué productos tengo?', '¿cuánto cuesta X?', o antes de crear/actualizar un producto para ver los ids. Por defecto solo activos; pasá include_inactive=true para ver también los ocultos.","inputSchema":{"type":"object","properties":{"include_inactive":{"type":"boolean","description":"Incluir productos inactivos. Por defecto false."},"limit":{"type":"integer","description":"Cuántos productos devolver (1-500). Por defecto 100."},"offset":{"type":"integer","description":"Desde qué posición (para paginar). Por defecto 0."}},"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"ventamatic_listar_categorias","title":"Listar categorías del catálogo","description":"Lista las categorías del menú/catálogo con sus ids. Usala para ubicar el categoryId antes de crear un producto, o para entender cómo está organizado el menú.","inputSchema":{"type":"object","properties":{},"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"ventamatic_inventario_stock","title":"Existencias de inventario","description":"Lista los ingredientes/insumos con su existencia actual y proveedor. Usala para '¿cuánto stock me queda de X?' o para una foto general del inventario. Para SOLO lo que está por agotarse, usá ventamatic_inventario_bajo.","inputSchema":{"type":"object","properties":{},"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"ventamatic_inventario_bajo","title":"Inventario por debajo del mínimo","description":"Lista los ingredientes que están por debajo de su punto de reorden (los que hay que comprar). Usala para '¿qué tengo que reponer?' o '¿qué se está agotando?'.","inputSchema":{"type":"object","properties":{},"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"ventamatic_ordenes_abiertas","title":"Órdenes abiertas (sin cobrar)","description":"Lista las órdenes abiertas (mesas/cuentas todavía sin pagar). Usala para '¿qué mesas tengo abiertas?' o '¿cuánto hay sin cobrar ahora?'. Para el detalle de una, usá ventamatic_orden_detalle.","inputSchema":{"type":"object","properties":{},"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"ventamatic_orden_detalle","title":"Detalle de una orden","description":"Devuelve el detalle completo de UNA orden por su id: items, modificadores, descuentos, total y estado. Conseguí el id con ventamatic_ordenes_abiertas.","inputSchema":{"type":"object","properties":{"orderId":{"type":"string","description":"UUID de la orden."}},"required":["orderId"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"ventamatic_pagos_transacciones","title":"Pagos por método (efectivo vs tarjeta)","description":"Desglose de lo cobrado por MÉTODO de pago (efectivo, tarjeta, transferencia) en un rango de fechas. El efectivo se reporta NETO de vuelto. Usala para '¿cuánto entró en efectivo vs tarjeta esta semana?' o para conciliar cobros por método. Devuelve una lista [{method, total, count}]. NO devuelve vouchers de tarjeta individuales — solo el total por método.","inputSchema":{"type":"object","properties":{"from":{"type":"string","description":"Fecha de inicio, inclusive, en formato AAAA-MM-DD. Ejemplo: 2026-07-01"},"to":{"type":"string","description":"Fecha de fin, inclusive, en formato AAAA-MM-DD. Ejemplo: 2026-07-31"}},"required":["from","to"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"ventamatic_propinas_por_mesero","title":"Propinas por mesero","description":"Total de propinas (tips) por mesero/servidor en un rango de fechas. Usala para repartir propinas o para '¿cuánto de propina hizo cada uno?'.","inputSchema":{"type":"object","properties":{"from":{"type":"string","description":"Fecha de inicio, inclusive, en formato AAAA-MM-DD. Ejemplo: 2026-07-01"},"to":{"type":"string","description":"Fecha de fin, inclusive, en formato AAAA-MM-DD. Ejemplo: 2026-07-31"}},"required":["from","to"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"ventamatic_crear_producto","title":"Crear un producto","description":"Crea un producto nuevo en el catálogo. Necesitás el categoryId (conseguilo con ventamatic_listar_categorias) y un precio. Es una escritura: requiere que el negocio tenga la escritura habilitada. Podés pasar idempotency_key para que un reintento no cree dos.","inputSchema":{"type":"object","properties":{"categoryId":{"type":"string","description":"UUID de la categoría."},"name":{"type":"string","description":"Nombre del producto."},"price":{"type":"string","description":"Precio de venta, en quetzales. Ejemplo: '25.00'."},"cost":{"type":"string","description":"Costo (opcional)."},"sku":{"type":"string"},"barcode":{"type":"string"},"taxable":{"type":"boolean","description":"¿Grava impuesto? Por defecto true."},"trackStock":{"type":"boolean","description":"¿Descuenta stock al vender? Por defecto false."},"idempotency_key":{"type":"string","description":"Clave para evitar duplicados en reintentos."}},"required":["categoryId","name","price"],"additionalProperties":false},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},{"name":"ventamatic_actualizar_producto","title":"Actualizar un producto","description":"Actualiza un producto existente: precio, nombre, si está activo, existencia, y la ventana de disponibilidad por día/hora (availableDays 0=Dom..6=Sáb, availableFrom/availableTo 'HH:MM'). Conseguí el id con ventamatic_listar_productos. Solo mandá los campos que querés cambiar.","inputSchema":{"type":"object","properties":{"productId":{"type":"string","description":"UUID del producto."},"name":{"type":"string"},"price":{"type":"string","description":"Nuevo precio, en quetzales."},"isActive":{"type":"boolean","description":"Activar/ocultar el producto."},"stockQuantity":{"type":"integer","minimum":0,"description":"Fijar existencia (entero >= 0; si el producto trackea stock)."},"availableDays":{"type":"array","items":{"type":"integer","minimum":0,"maximum":6},"description":"Días disponibles, 0=Dom..6=Sáb. null/omitir = todos."},"availableFrom":{"type":"string","description":"Hora de inicio 'HH:MM' (24h)."},"availableTo":{"type":"string","description":"Hora de fin 'HH:MM' (24h)."},"idempotency_key":{"type":"string"}},"required":["productId"],"additionalProperties":false},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},{"name":"ventamatic_ajustar_inventario","title":"Ajustar inventario","description":"Registra un movimiento de inventario de un ingrediente: compra (purchase), merma (waste), ajuste (adjustment) o transferencia (transfer). REGLA DEL SIGNO: en 'purchase' mandá la cantidad que ENTRÓ (positiva); en 'waste' mandá la cantidad que se PERDIÓ (positiva) y el sistema la RESTA solo; en 'adjustment'/'transfer' el signo manda (positivo suma, negativo resta). Para cargar stock recibido usá type='purchase' con unitCost. Conseguí el ingredientId con ventamatic_inventario_stock.","inputSchema":{"type":"object","properties":{"ingredientId":{"type":"string","description":"UUID del ingrediente/insumo."},"type":{"type":"string","enum":["purchase","waste","adjustment","transfer"],"description":"Tipo de movimiento."},"quantity":{"type":"string","description":"Cantidad, distinta de cero. purchase: positiva (lo que entró). waste: positiva (lo que se perdió; el sistema la resta). adjustment/transfer: con signo ('12' suma, '-3' resta)."},"unitCost":{"type":"string","description":"Costo unitario (para 'purchase' recalcula el costo promedio)."},"reference":{"type":"string","description":"Nota/referencia del movimiento."},"idempotency_key":{"type":"string"}},"required":["ingredientId","type","quantity"],"additionalProperties":false},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},{"name":"ventamatic_webhook_suscribir","title":"Suscribir un webhook","description":"Crea una suscripción de webhook: Ventamatic hará POST firmado a tu URL cuando ocurran los eventos que elijas (ej: 'order.paid', 'inventory.low', o '*' para todos; usá ventamatic_catalogo_eventos para ver la lista). Devuelve un secreto que se muestra UNA sola vez — guardalo para verificar la firma. Requiere plan con webhooks (pro/enterprise).","inputSchema":{"type":"object","properties":{"url":{"type":"string","description":"URL https del endpoint que recibirá los eventos."},"events":{"type":"array","items":{"type":"string"},"description":"Tipos de evento, o ['*'] para todos.","minItems":1},"description":{"type":"string"}},"required":["url","events"],"additionalProperties":false},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},{"name":"ventamatic_webhook_listar","title":"Listar webhooks","description":"Lista las suscripciones de webhook del negocio, con su estado y fallos recientes (sin el secreto).","inputSchema":{"type":"object","properties":{},"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"ventamatic_webhook_entregas","title":"Entregas de un webhook","description":"Log de entregas de una suscripción de webhook: qué evento, estado, intentos y código HTTP. Usala para diagnosticar por qué un integrador no recibe. Conseguí el id con ventamatic_webhook_listar.","inputSchema":{"type":"object","properties":{"id":{"type":"string","description":"UUID de la suscripción."},"limit":{"type":"integer","minimum":1,"maximum":200,"description":"Cuántas entregas devolver. Por defecto 50."}},"required":["id"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"ventamatic_webhook_eliminar","title":"Eliminar un webhook","description":"Borra una suscripción de webhook. Conseguí el id con ventamatic_webhook_listar. Es irreversible.","inputSchema":{"type":"object","properties":{"id":{"type":"string","description":"UUID de la suscripción a borrar."}},"required":["id"],"additionalProperties":false},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false}},{"name":"ventamatic_catalogo_eventos","title":"Catálogo de eventos de webhook","description":"Lista todos los tipos de evento a los que se puede suscribir un webhook, agrupados por dominio.","inputSchema":{"type":"object","properties":{},"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}}],"x-webhook-events":{"orders":["order.created","order.updated","order.paid","order.fulfilled","order.cancelled","order.refunded"],"payments":["payment.created","payment.completed","payment.failed","payment.refunded"],"catalog":["catalog.item.created","catalog.item.updated","catalog.item.deleted","catalog.published"],"inventory":["inventory.count.updated","inventory.low","inventory.out_of_stock","inventory.restocked"],"customers":["customer.created","customer.updated","loyalty.points.accrued","loyalty.reward.redeemed"],"devices":["device.online","device.offline","device.low_data","vending.dispensed","vending.dispense_failed"],"fel":["fel.certified","fel.certification_failed","fel.voided"],"delivery":["channel.order.received","channel.store.paused"],"tenant":["tenant.connected","tenant.disconnected","connection.error"]},"x-plans":{"starter":{"writeEnabled":false,"webhooksEnabled":false,"maxWebhookSubscriptions":0,"maxConnections":2,"toolCallsPerMinute":30,"scopeDomains":["ventas","catalogo","inventario","kioskos","pagos","ordenes"]},"pro":{"writeEnabled":true,"webhooksEnabled":true,"maxWebhookSubscriptions":5,"maxConnections":10,"toolCallsPerMinute":120,"scopeDomains":["ventas","catalogo","inventario","kioskos","pagos","ordenes"]},"enterprise":{"writeEnabled":true,"webhooksEnabled":true,"maxWebhookSubscriptions":50,"maxConnections":100,"toolCallsPerMinute":600,"scopeDomains":["ventas","catalogo","inventario","kioskos","pagos","ordenes"]}}}