{"openapi":"3.0.0","paths":{"/v1/me":{"get":{"description":"Devuelve los permisos efectivos otorgados por el Personal Access Token autenticado.","operationId":"MeController_getMe","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponseDto"}}}},"401":{"description":"Token inválido, revocado o expirado"}},"security":[{"PAT":[]}],"summary":"Obtener permisos efectivos del token","tags":["me"]}},"/v1/me/projects":{"get":{"operationId":"MeController_listProjects","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"PAT":[]}],"summary":"Listar projects de la company autenticada. Útil para que el CLI elija project context.","tags":["me"]}},"/v1/me/token":{"delete":{"description":"Marca el PAT con el que se autenticó esta request como revocado. Próximas requests con el mismo token devolverán 401.","operationId":"MeController_revokeCurrentToken","parameters":[],"responses":{"204":{"description":""},"401":{"description":"Token inválido, revocado o expirado"}},"security":[{"PAT":[]}],"summary":"Revocar el token actualmente autenticado (logout server-side)","tags":["me"]}},"/v1/messages":{"post":{"description":"The `message` object is discriminated by `type`: text, image, video, audio, document, sticker, location, contacts, reaction, template, buttons, list, cta_url, catalog, carousel or flow. Not every channel carries every type — an unsupported combination returns 422 MESSAGE_TYPE_NOT_SUPPORTED_FOR_CHANNEL listing what the channel does accept. Pick a ready-to-send body from the examples below.","operationId":"PublicMessagesController_send","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageDto"},"examples":{"text":{"summary":"text — free-form message","description":"Only reaches a recipient whose last inbound message is under 24 hours old.","value":{"channel":"whatsapp","to":"+5491155555555","message":{"type":"text","body":"Hola Juan, ¿pudiste revisar la propuesta?","preview_url":true}}},"image":{"summary":"image — by public URL","description":"Use `media_id` instead of `link` for an uploaded file.","value":{"channel":"whatsapp","to":"+5491155555555","message":{"type":"image","link":"https://cdn.example.com/promo.png","caption":"Promo de marzo"}}},"video":{"summary":"video — by public URL","value":{"channel":"whatsapp","to":"+5491155555555","message":{"type":"video","link":"https://cdn.example.com/demo.mp4","caption":"Cómo activar tu cuenta"}}},"audio":{"summary":"audio — voice note","description":"Omit `voice` or set it to false to send a plain audio file.","value":{"channel":"whatsapp","to":"+5491155555555","message":{"type":"audio","link":"https://cdn.example.com/nota.ogg","voice":true}}},"document":{"summary":"document — by uploaded media_id","value":{"channel":"whatsapp","to":"+5491155555555","message":{"type":"document","media_id":"1234567890123456","filename":"factura-A-1042.pdf","caption":"Tu factura de marzo"}}},"sticker":{"summary":"sticker — WebP","value":{"channel":"whatsapp","to":"+5491155555555","message":{"type":"sticker","link":"https://cdn.example.com/gracias.webp"}}},"location":{"summary":"location — map pin (WhatsApp only)","value":{"channel":"whatsapp","to":"+5491155555555","message":{"type":"location","latitude":-33.4489,"longitude":-70.6693,"name":"Sucursal Centro","address":"Av. Libertador 1234, Santiago"}}},"contacts":{"summary":"contacts — share a vCard (WhatsApp only)","value":{"channel":"whatsapp","to":"+5491155555555","message":{"type":"contacts","contacts":[{"name":{"formatted_name":"Camila Rojas","first_name":"Camila","last_name":"Rojas"},"phones":[{"phone":"+56912345678","type":"WORK"}],"emails":[{"email":"camila@example.com","type":"WORK"}],"org":{"company":"Keebai","title":"Account Manager"}}]}}},"reaction":{"summary":"reaction — emoji on a previous message","description":"Send an empty `emoji` to clear a reaction.","value":{"channel":"whatsapp","to":"+5491155555555","message":{"type":"reaction","message_id":"wamid.HBgLNTQ5MTE1NTU1NTU1FQIAERgSN0EyRjc4","emoji":"👍"}}},"template":{"summary":"template — approved template (WhatsApp only)","description":"The only type that reaches a closed 24-hour window.","value":{"channel":"whatsapp","to":"+5491155555555","message":{"type":"template","name":"welcome_v2","language":"es","variables":{"nombre":"Juan","monto":"1500"}}}},"template_with_flow":{"summary":"template — with a Flow button","description":"Binds a Flow to one of the template FLOW buttons. `flow_token` is echoed back on the whatsapp.flow.response webhook.","value":{"channel":"whatsapp","to":"+5491155555555","message":{"type":"template","name":"encuesta_post_visita","language":"es","variables":{"nombre":"Juan"},"flow":{"flow_token":"csat-8f21c4","button_index":0,"flow_action_data":{"ticket_id":"A-1042"}}}}},"buttons":{"summary":"buttons — up to 3 quick replies","value":{"channel":"whatsapp","to":"+5491155555555","message":{"type":"buttons","body_text":"¿Confirmas tu reserva para el viernes a las 21:00?","buttons":[{"id":"confirm","title":"Confirmar"},{"id":"reschedule","title":"Reprogramar"},{"id":"cancel","title":"Cancelar"}],"header":{"type":"text","text":"Restaurante La Mela"},"footer_text":"Responde antes de las 18:00"}}},"list":{"summary":"list — tappable menu","value":{"channel":"whatsapp","to":"+5491155555555","message":{"type":"list","body_text":"Elige el horario que te acomode.","button_text":"Ver horarios","sections":[{"title":"Viernes 2","rows":[{"id":"fri-20","title":"20:00","description":"Mesa junto a la ventana"},{"id":"fri-21","title":"21:00","description":"Salón principal"}]},{"title":"Sábado 3","rows":[{"id":"sat-20","title":"20:00"}]}],"footer_text":"Restaurante La Mela"}}},"cta_url":{"summary":"cta_url — button that opens a link","value":{"channel":"whatsapp","to":"+5491155555555","message":{"type":"cta_url","body_text":"Dejaste productos en tu carrito. Retoma la compra cuando quieras.","display_text":"Ir al carrito","url":"https://tienda.example.com/checkout/abc123","footer_text":"El carrito expira en 24 horas"}}},"catalog":{"summary":"catalog — open the Meta catalog (WhatsApp only)","value":{"channel":"whatsapp","to":"+5491155555555","message":{"type":"catalog","body_text":"Mira nuestro catálogo de otoño.","thumbnail_product_retailer_id":"SKU-1042","footer_text":"Envíos a todo el país"}}},"carousel":{"summary":"carousel — media cards with their own buttons","description":"Meta rejects .webp images on carousel headers.","value":{"channel":"whatsapp","to":"+5491155555555","message":{"type":"carousel","body_text":"Novedades de la semana","cards":[{"header":{"type":"image","link":"https://cdn.example.com/producto-1.png"},"body_text":"Zapatillas running — 20% off","action":{"display_text":"Ver","url":"https://tienda.example.com/p/1"}},{"header":{"type":"image","link":"https://cdn.example.com/producto-2.png"},"body_text":"Mochila urbana — 15% off","action":{"display_text":"Ver","url":"https://tienda.example.com/p/2"}}]}}},"flow":{"summary":"flow — published WhatsApp Flow (WhatsApp only)","description":"Create and publish the Flow first with POST /v1/flows. Needs an open 24-hour window; outside it, attach the Flow to a template instead.","value":{"channel":"whatsapp","to":"+5491155555555","message":{"type":"flow","flow_id":"1234567890123456","flow_token":"reserva-8f21c4","flow_cta":"Reservar","body_text":"Reserva tu mesa en menos de un minuto.","header_text":"Restaurante La Mela","footer_text":"Cupos limitados","flow_action":"navigate","flow_action_payload":{"screen":"WELCOME","data":{"customer_name":"Juan"}}}}},"reply_to_message":{"summary":"text — quoting a previous message","description":"Any type accepts `context` to render as a quoted reply.","value":{"channel":"whatsapp","to":"+5491155555555","context":{"message_id":"wamid.HBgLNTQ5MTE1NTU1NTU1FQIAERgSN0EyRjc4"},"message":{"type":"text","body":"Sí, ese mismo pedido."}}},"instagram":{"summary":"text — on Instagram instead of WhatsApp","description":"The recipient is the Instagram-scoped id of the sender, not a phone number.","value":{"channel":"instagram","to":"17841400000000000","message":{"type":"text","body":"¡Gracias por escribirnos!"}}},"pick_channel_explicitly":{"summary":"text — picking one of several channels","description":"Needed only when the project has more than one active channel of that type.","value":{"channel":"whatsapp","to":"+5491155555555","channel_id":"665f1a2b3c4d5e6f70819234","meta_data":{"order_id":"A-1042"},"message":{"type":"text","body":"Hola Juan"}}}}}}},"responses":{"202":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SingleSendResponse"}}}}},"security":[{"PAT":[]}],"summary":"Send a message on any connected channel","tags":["messages"]}},"/v1/messages/mark-read":{"post":{"description":"WhatsApp Cloud API only.","operationId":"PublicMessagesController_markRead","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkReadDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkReadResponse"}}}}},"security":[{"PAT":[]}],"summary":"Mark a received message as read (optionally show typing)","tags":["messages"]}},"/v1/messages/raw":{"post":{"description":"WhatsApp Cloud API only.","operationId":"PublicMessagesController_sendRaw","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendRawDto"}}}},"responses":{"202":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SingleSendResponse"}}}}},"security":[{"PAT":[]}],"summary":"Escape hatch: forward a raw Meta Graph API body to /{phone_number_id}/messages","tags":["messages"]}},"/v1/messages/bulk":{"post":{"description":"WhatsApp Cloud API only. Runs as an asynchronous job.","operationId":"PublicMessagesController_sendBulk","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendBulkDto"}}}},"responses":{"202":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDispatchResponse"}}}}},"security":[{"PAT":[]}],"summary":"Schedule a bulk template broadcast to many recipients","tags":["messages"]}},"/v1/messages/bulk/{broadcastId}":{"get":{"operationId":"PublicMessagesController_getBulkStatus","parameters":[{"name":"broadcastId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkStatusResponse"}}}}},"security":[{"PAT":[]}],"summary":"Status of a previously scheduled bulk broadcast","tags":["messages"]}},"/v1/media/upload":{"post":{"operationId":"PublicMediaController_uploadMedia","parameters":[],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/UploadMediaDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaUploadResponse"}}}}},"security":[{"PAT":[]}],"summary":"Upload a media file to WhatsApp. Returns a media_id usable in send-{image,video,audio,document,sticker} endpoints.","tags":["media"]}},"/v1/media/{mediaId}":{"get":{"operationId":"PublicMediaController_getMedia","parameters":[{"name":"mediaId","required":true,"in":"path","schema":{"type":"string"}},{"name":"phone_number_id","required":true,"in":"query","schema":{"example":"100000000000001","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaMetadataResponse"}}}}},"security":[{"PAT":[]}],"summary":"Get WhatsApp media metadata","tags":["media"]},"delete":{"operationId":"PublicMediaController_deleteMedia","parameters":[{"name":"mediaId","required":true,"in":"path","schema":{"type":"string"}},{"name":"phone_number_id","required":true,"in":"query","schema":{"example":"100000000000001","type":"string"}}],"responses":{"204":{"description":""}},"security":[{"PAT":[]}],"summary":"Delete a previously uploaded WhatsApp media","tags":["media"]}},"/v1/media/{mediaId}/download":{"get":{"operationId":"PublicMediaController_downloadMedia","parameters":[{"name":"mediaId","required":true,"in":"path","schema":{"type":"string"}},{"name":"phone_number_id","required":true,"in":"query","schema":{"example":"100000000000001","type":"string"}}],"responses":{"200":{"description":"Contenido binario del media.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}}},"security":[{"PAT":[]}],"summary":"Download the binary contents of a WhatsApp media","tags":["media"]}},"/v1/flows":{"post":{"description":"Registers the Flow at Meta and uploads its Flow JSON. The Flow starts in draft: publish it before sending it to real recipients.","operationId":"PublicFlowsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFlowDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Create a WhatsApp Flow","tags":["flows"]},"get":{"operationId":"PublicFlowsController_list","parameters":[{"name":"channel_id","required":false,"in":"query","description":"Keebai channel id. Optional when the tenant has exactly one active channel of the given type; required to disambiguate otherwise.","schema":{"example":"665f1a2b3c4d5e6f70819234","type":"string"}},{"name":"skip","required":false,"in":"query","schema":{"minimum":0,"default":0,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":100,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"List the WhatsApp Flows of the project","tags":["flows"]}},"/v1/flows/{id}":{"get":{"operationId":"PublicFlowsController_getById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Get a WhatsApp Flow by id","tags":["flows"]},"put":{"description":"Sending flow_data re-uploads the Flow JSON at Meta. A published Flow must be republished for the change to reach recipients.","operationId":"PublicFlowsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateFlowDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Update a WhatsApp Flow","tags":["flows"]},"delete":{"description":"Meta only allows deleting Flows that are still in draft.","operationId":"PublicFlowsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"PAT":[]}],"summary":"Delete a WhatsApp Flow","tags":["flows"]}},"/v1/flows/{id}/publish":{"post":{"description":"Meta validates the Flow JSON on publish. A published Flow can no longer be edited — create a new version instead.","operationId":"PublicFlowsController_publish","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Publish a WhatsApp Flow","tags":["flows"]}},"/v1/templates":{"get":{"operationId":"PublicTemplatesController_list","parameters":[{"name":"page","required":false,"in":"query","schema":{"default":0,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"maximum":100,"default":50,"type":"number"}},{"name":"status","required":false,"in":"query","schema":{"default":"APPROVED","type":"string","enum":["PENDING","IN_REVIEW","REJECTED","APPROVED","PAUSED","DISABLED","IN_APPEAL"]}},{"name":"channel_id","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedTemplatesResponse"}}}}},"security":[{"PAT":[]}],"summary":"Listar templates aprobados de la company","tags":["templates"]},"post":{"operationId":"PublicTemplatesController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTemplateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTemplateDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear un template de WhatsApp y enviarlo a Meta para aprobación","tags":["templates"]}},"/v1/templates/{id}":{"patch":{"operationId":"PublicTemplatesController_update","parameters":[{"name":"id","required":true,"in":"path","description":"ObjectId del template","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTemplateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTemplateDto"}}}}},"security":[{"PAT":[]}],"summary":"Editar un template existente","tags":["templates"]}},"/v1/webhooks":{"post":{"description":"Devuelve el secret raw UNA SOLA VEZ. Guárdalo de inmediato — no se puede recuperar.","operationId":"PublicWebhooksController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreatedResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear una subscripción de webhook saliente","tags":["webhooks"]},"get":{"operationId":"PublicWebhooksController_list","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar subscripciones de webhooks de la company","tags":["webhooks"]}},"/v1/webhooks/{id}":{"get":{"operationId":"PublicWebhooksController_getById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener una subscripción","tags":["webhooks"]},"patch":{"operationId":"PublicWebhooksController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Actualizar una subscripción","tags":["webhooks"]},"delete":{"operationId":"PublicWebhooksController_delete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"PAT":[]}],"summary":"Eliminar una subscripción","tags":["webhooks"]}},"/v1/webhooks/{id}/rotate-secret":{"post":{"operationId":"PublicWebhooksController_rotateSecret","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreatedResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Rotar el secret. El secret anterior queda inválido inmediatamente.","tags":["webhooks"]}},"/v1/webhooks/{id}/test":{"post":{"operationId":"PublicWebhooksController_test","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestWebhookDto"}}}},"responses":{"202":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookTestAcceptedResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Disparar un evento sintético hacia la URL configurada (para pruebas).","tags":["webhooks"]}},"/v1/webhooks/{id}/deliveries":{"get":{"operationId":"PublicWebhooksController_listDeliveries","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"maximum":200,"default":50,"type":"number"}},{"name":"cursor","required":false,"in":"query","description":"Cursor de paginación (delivery id).","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Historial de deliveries de la subscripción.","tags":["webhooks"]}},"/v1/channels":{"get":{"operationId":"PublicChannelsController_list","parameters":[{"name":"type","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicChannelListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar canales activos de la company.","tags":["channels"]}},"/v1/channels/{id}":{"get":{"operationId":"PublicChannelsController_getById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicChannelResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener un canal por id.","tags":["channels"]}},"/v1/channels/whatsapp/connect":{"post":{"operationId":"PublicChannelsController_initiateWhatsappConnect","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatsappConnectRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicConnectSessionResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Inicia un flow de conexión de WhatsApp Business desde el CLI. Devuelve una URL del portal donde el usuario completa el embedded signup.","tags":["channels"]}},"/v1/channels/whatsapp/connect/{sessionId}":{"get":{"operationId":"PublicChannelsController_pollWhatsappConnect","parameters":[{"name":"sessionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicConnectSessionPollResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Polling: estado de la sesión de conexión. Cuando status=completed devuelve el canal creado.","tags":["channels"]}},"/v1/channels/whatsapp/connect/{sessionId}/qr-stream":{"get":{"operationId":"PublicChannelsController_streamWhatsappQrConnect","parameters":[{"name":"sessionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Stream SSE. Eventos: qr | connecting | connected | failed | disconnected.","content":{"text/event-stream":{"schema":{"type":"string"}}}}},"security":[{"PAT":[]}],"summary":"Stream SSE de eventos de pairing por QR (events: qr | connecting | connected | failed | disconnected). Sólo para sesiones iniciadas con mode=qr.","tags":["channels"]}},"/v1/whatsapp/numbers":{"get":{"operationId":"PublicWhatsappNumbersController_list","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"PAT":[]}],"summary":"Lista los números de WhatsApp Business conectados a la company.","tags":["whatsapp"]}},"/v1/knowledge/tree":{"get":{"operationId":"PublicKnowledgeController_getTree","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeTreeResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener el árbol completo de carpetas y documentos de la base de conocimientos.","tags":["knowledge"]}},"/v1/knowledge/folders":{"post":{"operationId":"PublicKnowledgeController_createFolder","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFolderDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeNodeDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear una carpeta en la base de conocimientos.","tags":["knowledge"]}},"/v1/knowledge/documents":{"post":{"operationId":"PublicKnowledgeController_createDocument","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDocumentDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeNodeDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear un documento desde markdown. El contenido se convierte a BlockNote y se reindexa para búsquedas.","tags":["knowledge"]}},"/v1/knowledge/nodes/{id}":{"delete":{"operationId":"PublicKnowledgeController_deleteNode","parameters":[{"name":"id","required":true,"in":"path","description":"ObjectId del nodo a eliminar.","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"PAT":[]}],"summary":"Eliminar un nodo (carpeta o documento). Si es carpeta, elimina sus descendientes.","tags":["knowledge"]}},"/v1/knowledge/search":{"post":{"operationId":"PublicKnowledgeController_search","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchKnowledgeDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchKnowledgeResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Buscar en la base de conocimientos por full-text, vector o híbrido.","tags":["knowledge"]}},"/v1/knowledge/assignments":{"post":{"operationId":"PublicKnowledgeController_assign","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignKnowledgeDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignKnowledgeResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Asignar nodos de la base de conocimientos a todos los workers de un asistente.","tags":["knowledge"]}},"/v1/contacts":{"get":{"description":"Devuelve los contactos de la company del token, del más reciente al más antiguo. El listado no filtra por project y siempre excluye los contactos fusionados y el canal playground.","operationId":"PublicContactsController_list","parameters":[{"name":"search","required":false,"in":"query","description":"Búsqueda full-text sobre nombre, apellido, usuario, teléfono y email.","schema":{"type":"string"}},{"name":"phone","required":false,"in":"query","description":"Filtrar por teléfono exacto","schema":{"type":"string"}},{"name":"channel_id","required":false,"in":"query","description":"ObjectId del canal","schema":{"type":"string"}},{"name":"channel_type","required":false,"in":"query","schema":{"type":"string","enum":["web","whatsapp","whatsapp_qr","facebook","messenger","instagram","tiktok","telegram","email","phone"]}},{"name":"date_from","required":false,"in":"query","description":"Fecha ISO 8601. Filtra por última actividad del contacto.","schema":{"type":"string"}},{"name":"date_to","required":false,"in":"query","description":"Fecha ISO 8601","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"minimum":0,"default":0,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicContactListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar contactos","tags":["contacts"]},"post":{"description":"La company y el project se toman del token; enviarlos en el body devuelve 400. Un contacto ya existente con el mismo user_id y canal devuelve 400.","operationId":"PublicContactsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicContactCreateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicContactEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear un contacto","tags":["contacts"]}},"/v1/contacts/{id}":{"get":{"operationId":"PublicContactsController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicContactEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener detalle de un contacto","tags":["contacts"]},"patch":{"description":"Actualización parcial. Enviar una cadena vacía no limpia el campo, y custom_fields se mergea con lo existente.","operationId":"PublicContactsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicContactUpdateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicContactEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Actualizar un contacto","tags":["contacts"]},"delete":{"description":"Borra el contacto y su historial de logs. Es permanente y no borra las conversaciones asociadas.","operationId":"PublicContactsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Contacto eliminado"}},"security":[{"PAT":[]}],"summary":"Eliminar un contacto","tags":["contacts"]}},"/v1/crm/customers":{"get":{"description":"Devuelve los clientes de la company del token. El listado no filtra por project.","operationId":"PublicCustomersController_list","parameters":[{"name":"search","required":false,"in":"query","description":"Búsqueda libre por nombre o email","schema":{"type":"string"}},{"name":"phone","required":false,"in":"query","description":"Filtrar por teléfono exacto","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"minimum":0,"default":0,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCustomerListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar clientes","tags":["crm-customers"]},"post":{"description":"La company y el project se toman del token; enviarlos en el body devuelve 400.","operationId":"PublicCustomersController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCustomerCreateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCustomerEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear un cliente","tags":["crm-customers"]}},"/v1/crm/customers/{id}":{"get":{"operationId":"PublicCustomersController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCustomerEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener detalle de un cliente","tags":["crm-customers"]},"patch":{"operationId":"PublicCustomersController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCustomerUpdateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCustomerEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Actualizar un cliente","tags":["crm-customers"]},"delete":{"operationId":"PublicCustomersController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Cliente eliminado"}},"security":[{"PAT":[]}],"summary":"Eliminar un cliente","tags":["crm-customers"]}},"/v1/crm/tickets":{"get":{"description":"Devuelve los tickets de la company del token. El listado no filtra por project.","operationId":"PublicTicketsController_list","parameters":[{"name":"keyword","required":false,"in":"query","description":"Búsqueda libre sobre el ticket","schema":{"type":"string"}},{"name":"pipeline_id","required":false,"in":"query","description":"Filtrar por pipeline","schema":{"type":"string"}},{"name":"stage_ids","required":false,"in":"query","description":"Ids de etapa separados por coma","schema":{"type":"string"}},{"name":"tag_ids","required":false,"in":"query","description":"Ids de tag separados por coma","schema":{"type":"string"}},{"name":"chat_user_id","required":false,"in":"query","description":"Filtrar por chat user (contacto)","schema":{"type":"string"}},{"name":"assigned_to","required":false,"in":"query","description":"Filtrar por usuario asignado","schema":{"type":"string"}},{"name":"categories","required":false,"in":"query","description":"Categorías separadas por coma","schema":{"type":"string"}},{"name":"channel_ids","required":false,"in":"query","description":"Ids de canal separados por coma","schema":{"type":"string"}},{"name":"completed","required":false,"in":"query","description":"'true' devuelve sólo cerrados, 'false' sólo abiertos","schema":{"type":"string"}},{"name":"date_from","required":false,"in":"query","description":"Fecha de creación desde (YYYY-MM-DD)","schema":{"type":"string"}},{"name":"date_to","required":false,"in":"query","description":"Fecha de creación hasta (YYYY-MM-DD)","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"minimum":0,"default":0,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTicketListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar tickets","tags":["crm-tickets"]},"post":{"description":"La company y el project se toman del token; enviarlos en el body devuelve 400.","operationId":"PublicTicketsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTicketCreateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTicketEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear un ticket","tags":["crm-tickets"]}},"/v1/crm/tickets/{id}":{"get":{"operationId":"PublicTicketsController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTicketEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener detalle de un ticket","tags":["crm-tickets"]},"patch":{"operationId":"PublicTicketsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTicketUpdateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTicketUpdateResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Actualizar un ticket","tags":["crm-tickets"]},"delete":{"operationId":"PublicTicketsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Ticket eliminado"}},"security":[{"PAT":[]}],"summary":"Eliminar un ticket","tags":["crm-tickets"]}},"/v1/crm/tickets/{id}/stage":{"post":{"description":"Mueve el ticket a la etapa indicada dentro de su pipeline y devuelve el estado resultante.","operationId":"PublicTicketsController_moveStage","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTicketStageDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTicketStageChangeResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Mover un ticket de etapa","tags":["crm-tickets"]}},"/v1/crm/tasks":{"get":{"description":"Devuelve las tareas de la company del token.","operationId":"PublicTasksController_list","parameters":[{"name":"status","required":false,"in":"query","description":"Filtrar por estado exacto","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"minimum":0,"default":0,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTaskListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar tareas","tags":["crm-tasks"]},"post":{"description":"La company se toma del token; enviarla en el body devuelve 400.","operationId":"PublicTasksController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTaskCreateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTaskEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear una tarea","tags":["crm-tasks"]}},"/v1/crm/tasks/{id}":{"get":{"operationId":"PublicTasksController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTaskEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener detalle de una tarea","tags":["crm-tasks"]},"patch":{"operationId":"PublicTasksController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTaskUpdateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTaskEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Actualizar una tarea","tags":["crm-tasks"]},"delete":{"operationId":"PublicTasksController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Tarea eliminada"}},"security":[{"PAT":[]}],"summary":"Eliminar una tarea","tags":["crm-tasks"]}},"/v1/crm/notes":{"get":{"description":"Devuelve las notas de la company del token.","operationId":"PublicNotesController_list","parameters":[{"name":"chat_user","required":false,"in":"query","description":"Filtrar por chat user (contacto)","schema":{"type":"string"}},{"name":"ticket_id","required":false,"in":"query","description":"Filtrar por ticket","schema":{"type":"string"}},{"name":"type","required":false,"in":"query","schema":{"type":"string","enum":["note","call","email","meeting"]}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"minimum":0,"default":0,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicNoteListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar notas","tags":["crm-notes"]},"post":{"description":"La company, el project y el autor se toman del token; enviarlos en el body devuelve 400.","operationId":"PublicNotesController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicNoteCreateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicNoteEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear una nota","tags":["crm-notes"]}},"/v1/crm/notes/{id}":{"get":{"operationId":"PublicNotesController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicNoteEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener detalle de una nota","tags":["crm-notes"]},"patch":{"operationId":"PublicNotesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicNoteUpdateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicNoteEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Actualizar una nota","tags":["crm-notes"]},"delete":{"operationId":"PublicNotesController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Nota eliminada"}},"security":[{"PAT":[]}],"summary":"Eliminar una nota","tags":["crm-notes"]}},"/v1/ecommerce/products":{"get":{"description":"Devuelve los productos de la company del token, ordenados por nombre. Incluye tanto los cargados en Keebai como los sincronizados desde una integración.","operationId":"PublicEcommerceController_listProducts","parameters":[{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"minimum":0,"default":0,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Búsqueda full-text sobre el catálogo","schema":{"type":"string"}},{"name":"type","required":false,"in":"query","description":"Origen del producto: interno o el de una integración","schema":{"type":"string"}},{"name":"category","required":false,"in":"query","description":"ObjectId de la categoría","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicProductListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar productos del catálogo","tags":["ecommerce"]}},"/v1/ecommerce/products/{id}":{"get":{"operationId":"PublicEcommerceController_getProduct","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicProductEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener detalle de un producto","tags":["ecommerce"]}},"/v1/ecommerce/carts":{"get":{"description":"Devuelve los carritos de la company, incluidos los abandonados. Filtrable por origen, integración y estado de recuperación.","operationId":"PublicEcommerceController_listCarts","parameters":[{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"minimum":0,"default":0,"type":"number"}},{"name":"source","required":false,"in":"query","description":"Origen del carrito","schema":{"type":"string"}},{"name":"integration_id","required":false,"in":"query","description":"ObjectId de la integración de origen","schema":{"type":"string"}},{"name":"recovery_status","required":false,"in":"query","description":"Estado de recuperación del carrito abandonado","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCartListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar carritos","tags":["ecommerce"]}},"/v1/ecommerce/carts/{id}":{"get":{"operationId":"PublicEcommerceController_getCart","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCartEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener detalle de un carrito","tags":["ecommerce"]}},"/v1/ecommerce/sales":{"get":{"description":"Devuelve las ventas de la company, filtrables por estado, estado de pago, contacto y rango de fechas.","operationId":"PublicEcommerceController_listSales","parameters":[{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"minimum":0,"default":0,"type":"number"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["completed","cancelled","refunded"]}},{"name":"payment_status","required":false,"in":"query","schema":{"type":"string","enum":["pending","paid","partially_paid","refunded"]}},{"name":"chat_user_id","required":false,"in":"query","description":"Filtrar por contacto","schema":{"type":"string"}},{"name":"from","required":false,"in":"query","description":"Fecha ISO 8601, inclusive","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","description":"Fecha ISO 8601, inclusive","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Búsqueda libre sobre la venta","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicSaleListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar ventas","tags":["ecommerce"]}},"/v1/ecommerce/sales/{id}":{"get":{"operationId":"PublicEcommerceController_getSale","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicSaleEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener detalle de una venta","tags":["ecommerce"]}},"/v1/loyalty/programs":{"get":{"description":"Devuelve los programas de la company del token, del más nuevo al más viejo. El campo rules solo trae poblada la variante que corresponde al type del programa.","operationId":"PublicLoyaltyController_listPrograms","parameters":[{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"minimum":0,"default":0,"type":"number"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["draft","active","archived"]}},{"name":"type","required":false,"in":"query","schema":{"type":"string","enum":["points","stamps","tiers"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicProgramListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar programas de fidelidad","tags":["loyalty"]}},"/v1/loyalty/programs/{id}":{"get":{"operationId":"PublicLoyaltyController_getProgram","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicProgramEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener un programa de fidelidad","tags":["loyalty"]}},"/v1/loyalty/templates":{"get":{"description":"Devuelve los templates del programa indicado, de la versión más nueva a la más vieja. El diseño de la tarjeta se edita desde el portal; acá es de solo lectura.","operationId":"PublicLoyaltyController_listTemplates","parameters":[{"name":"program_id","required":true,"in":"query","description":"ObjectId del programa cuyos templates se listan. Los templates siempre se consultan por programa","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTemplateListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar templates de wallet de un programa","tags":["loyalty"]}},"/v1/loyalty/templates/{id}":{"get":{"operationId":"PublicLoyaltyController_getTemplate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTemplateEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener un template de wallet","tags":["loyalty"]}},"/v1/loyalty/memberships":{"get":{"description":"Devuelve las membresías de la company, filtrables por programa, cliente, teléfono, nombre o estado. El saldo de puntos puede leerse 0 si el programa vence puntos y ya pasó el plazo.","operationId":"PublicLoyaltyController_listMemberships","parameters":[{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"minimum":0,"default":0,"type":"number"}},{"name":"program_id","required":false,"in":"query","description":"ObjectId del programa","schema":{"type":"string"}},{"name":"customer_id","required":false,"in":"query","description":"Identificador del cliente elegido por el integrador al inscribir","schema":{"type":"string"}},{"name":"phone","required":false,"in":"query","description":"Teléfono del cliente. Busca por subsecuencia de dígitos, así que +56 9 1234 5678 matchea con 912345678","schema":{"type":"string"}},{"name":"name","required":false,"in":"query","description":"Búsqueda parcial por nombre","schema":{"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["active","suspended","revoked"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicMembershipListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar membresías","tags":["loyalty"]},"post":{"description":"Crea la membresía y le asigna un serial. Los datos del cliente se copian tal cual y no se vuelven a resolver contra el CRM. Inscribir dos veces al mismo customer.id en el mismo programa devuelve 409.","operationId":"PublicLoyaltyController_enrollMembership","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicMembershipEnrollDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicMembershipEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Inscribir un cliente en un programa","tags":["loyalty"]}},"/v1/loyalty/memberships/{id}":{"get":{"operationId":"PublicLoyaltyController_getMembership","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicMembershipEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener una membresía","tags":["loyalty"]}},"/v1/loyalty/memberships/{id}/ledger":{"get":{"description":"Historial de acumulaciones, canjes y ajustes, del más nuevo al más viejo. Cada entrada guarda el saldo resultante en balance_after.","operationId":"PublicLoyaltyController_listLedger","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"minimum":0,"default":0,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicLedgerListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar los movimientos de una membresía","tags":["loyalty"]},"post":{"description":"Acumula, canjea o ajusta el saldo, y actualiza el pase en la wallet del cliente. La métrica la decide el tipo del programa, no el request. El saldo nunca baja de cero.","operationId":"PublicLoyaltyController_recordLedgerEntry","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicLedgerRecordDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicLedgerEntryEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Registrar un movimiento de puntos o sellos","tags":["loyalty"]}},"/v1/loyalty/memberships/{id}/passes/google":{"post":{"description":"Devuelve el link para agregar la tarjeta a Google Wallet. Llamarlo de nuevo sobre la misma membresía reutiliza el pase existente.","operationId":"PublicLoyaltyController_issueGooglePass","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicGooglePassDto"}}}}},"security":[{"PAT":[]}],"summary":"Emitir el pase de Google Wallet","tags":["loyalty"]}},"/v1/loyalty/memberships/{id}/passes/apple/link":{"post":{"description":"Devuelve un link público de descarga del .pkpass, apto para QR o para mandar por WhatsApp. Requiere que las credenciales de Apple Wallet estén cargadas; si no, responde 400.","operationId":"PublicLoyaltyController_issueApplePassLink","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApplePassLinkDto"}}}}},"security":[{"PAT":[]}],"summary":"Emitir el link de descarga del pase de Apple Wallet","tags":["loyalty"]}},"/v1/loyalty/memberships/{id}/passes/notify":{"post":{"description":"Manda un push a los dispositivos que tienen el pase agregado. Las membresías sin pase registrado cuentan como skipped, no como error.","operationId":"PublicLoyaltyController_notifyPass","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPassNotifyDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPassNotifyResultDto"}}}}},"security":[{"PAT":[]}],"summary":"Notificar al cliente en su wallet","tags":["loyalty"]}},"/v1/loyalty/memberships/{id}/passes/notifications":{"get":{"description":"Historial de los mensajes mandados a la wallet, del más nuevo al más viejo, con a cuántos dispositivos llegó cada uno.","operationId":"PublicLoyaltyController_listPassNotifications","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPassNotificationListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar las notificaciones enviadas a una membresía","tags":["loyalty"]}},"/v1/assistants":{"get":{"operationId":"PublicAssistantsController_list","parameters":[{"name":"q","required":false,"in":"query","description":"Filtro por nombre (búsqueda parcial, case-insensitive).","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":100,"default":25,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedAssistantsResponse"}}}}},"security":[{"PAT":[]}],"summary":"Listar y buscar asistentes activos de la company.","tags":["assistants"]},"post":{"description":"El asistente nace con un bloque de personalidad y uno de politica de respuesta ya adjuntos y vacios, porque sin ellos no responde nada util. Un modelo no soportado devuelve 400 INVALID_MODEL.","operationId":"PublicAssistantsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAssistantCreateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAssistantEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear un asistente","tags":["assistants"]}},"/v1/assistants/{id}":{"get":{"description":"Devuelve el asistente con su modelo, sus nodos de conocimiento y las referencias ordenadas a los bloques que arman su prompt. Las referencias solo traen ids: la metadata de cada bloque se lee en GET /v1/assistants/{id}/blocks.","operationId":"PublicAssistantsController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAssistantEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener un asistente","tags":["assistants"]},"patch":{"description":"Actualiza solo los campos presentes en el body. Los bloques no se tocan por aca: se manejan con los endpoints de /blocks.","operationId":"PublicAssistantsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAssistantUpdateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAssistantEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Actualizar un asistente","tags":["assistants"]},"delete":{"description":"Borra el asistente de forma permanente. Sus bloques sobreviven y quedan en el catalogo: esto desarma el cableado, no limpia lo que habia detras.","operationId":"PublicAssistantsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"PAT":[]}],"summary":"Eliminar un asistente","tags":["assistants"]}},"/v1/assistants/{id}/blocks":{"get":{"description":"Devuelve los bloques cableados al asistente en orden de prompt, con su metadata y sin contenido. Es el paso del medio: asistente, sus bloques, y despues el contenido de uno. Incluye los archivados, que siguen rindiendo en el prompt.","operationId":"PublicAssistantsController_listBlocks","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAttachedBlockListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar los bloques de un asistente","tags":["assistants"]},"put":{"description":"Fija la lista completa de bloques de una sola vez. Es la unica forma de reordenar o de fijar versiones. Los bloques que no aparezcan en el body quedan desadjuntados.","operationId":"PublicAssistantsController_setBlocks","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAssistantBlocksSetDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAssistantEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Reemplazar los bloques de un asistente","tags":["assistants"]},"post":{"description":"Falla si el bloque es de otra company, o si dejaria al asistente con dos bloques de identidad del mismo tipo.","operationId":"PublicAssistantsController_attachBlock","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockRefDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAssistantEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Adjuntar un bloque a un asistente","tags":["assistants"]}},"/v1/assistants/{id}/blocks/{blockId}":{"delete":{"description":"Saca el bloque del prompt del asistente. El bloque no se toca y sigue en el catalogo.","operationId":"PublicAssistantsController_detachBlock","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"blockId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAssistantEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Desadjuntar un bloque de un asistente","tags":["assistants"]}},"/v1/blocks":{"get":{"description":"Devuelve todos los bloques del proyecto, esten adjuntos a un asistente o no, con metadata y sin contenido. Un mismo bloque se puede reusar en varios asistentes.","operationId":"PublicBlocksController_list","parameters":[{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"minimum":0,"default":0,"type":"number"}},{"name":"type","required":false,"in":"query","schema":{"type":"string","enum":["personification","objective","response_format","steps","cases_possible","do_not","product_info","store_info","reservation_info","tables_info","tags","response_policy"]}},{"name":"family","required":false,"in":"query","schema":{"type":"string","enum":["identity","instructions","information"]}},{"name":"include_archived","required":false,"in":"query","description":"Incluye los bloques archivados. Un bloque archivado sigue rindiendo en el prompt de los asistentes que lo tienen adjunto.","schema":{"default":false,"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar bloques del proyecto","tags":["blocks"]}},"/v1/blocks/personification":{"post":{"description":"Quien es el asistente: nombre, rol, tono y trato. Es un bloque de identidad, asi que un asistente no puede tener dos.","operationId":"PublicBlocksController_createPersonification","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockCreateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear un bloque de personalidad","tags":["blocks"]}},"/v1/blocks/objective":{"post":{"description":"Que tiene que lograr el asistente en la conversacion y como se sabe que lo logro. Bloque de identidad, uno por asistente.","operationId":"PublicBlocksController_createObjective","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockCreateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear un bloque de objetivo","tags":["blocks"]}},"/v1/blocks/response-format":{"post":{"description":"Largo, uso de emojis y reglas de formato de los mensajes. Bloque de identidad, uno por asistente.","operationId":"PublicBlocksController_createResponseFormat","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockCreateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear un bloque de formato de respuesta","tags":["blocks"]}},"/v1/blocks/steps":{"post":{"description":"El procedimiento que sigue el asistente, en orden. Escribi cada paso en una linea que empiece con un numero para que quede como lista numerada.","operationId":"PublicBlocksController_createSteps","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockCreateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear un bloque de pasos","tags":["blocks"]}},"/v1/blocks/cases-possible":{"post":{"description":"Situaciones que se pueden dar y como responder a cada una. A diferencia de los pasos, no tienen orden entre si.","operationId":"PublicBlocksController_createCasesPossible","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockCreateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear un bloque de casos posibles","tags":["blocks"]}},"/v1/blocks/do-not":{"post":{"description":"Lo que el asistente no debe hacer nunca. Una restriccion por linea, con su motivo si ayuda.","operationId":"PublicBlocksController_createDoNot","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockCreateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear un bloque de restricciones","tags":["blocks"]}},"/v1/blocks/response-policy":{"post":{"description":"Cuando el asistente decide no responder y cuando reacciona en vez de contestar.","operationId":"PublicBlocksController_createResponsePolicy","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockCreateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear un bloque de politica de respuesta","tags":["blocks"]}},"/v1/blocks/{id}":{"get":{"description":"Tipo, familia, nombre y cual es su version vigente. Sin contenido: para eso esta GET /v1/blocks/{id}/content.","operationId":"PublicBlocksController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener la metadata de un bloque","tags":["blocks"]},"patch":{"description":"Solo el nombre y el flag de archivado. El contenido no se edita por aca.","operationId":"PublicBlocksController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockUpdateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Renombrar o archivar un bloque","tags":["blocks"]},"delete":{"description":"Archiva el bloque, no lo borra: su historial sobrevive y se puede desarchivar. Los asistentes que lo tengan adjunto lo siguen usando.","operationId":"PublicBlocksController_archive","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"PAT":[]}],"summary":"Archivar un bloque","tags":["blocks"]}},"/v1/blocks/{id}/content":{"get":{"description":"Devuelve el contenido de la version vigente. Los bloques libres vuelven como texto en content; los de catalogo, que solo edita el portal, vuelven como payload estructurado.","operationId":"PublicBlocksController_getContent","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockContentEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Leer el contenido de un bloque","tags":["blocks"]},"put":{"description":"Reemplaza el contenido creando una version nueva y dejandola vigente; la anterior queda en el historial. Solo acepta los siete tipos libres: los de catalogo devuelven 409 BLOCK_TYPE_NOT_WRITABLE.","operationId":"PublicBlocksController_saveContent","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockContentDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockContentEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Guardar el contenido de un bloque","tags":["blocks"]}},"/v1/blocks/{id}/versions":{"get":{"description":"Versiones de la mas nueva a la mas vieja, sin los contenidos. Sirve para elegir un version_id que inspeccionar o restaurar.","operationId":"PublicBlocksController_listVersions","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"minimum":0,"default":0,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockVersionListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar el historial de un bloque","tags":["blocks"]}},"/v1/blocks/{id}/versions/{versionId}":{"get":{"description":"El contenido de una version historica, para revisarla antes de restaurarla.","operationId":"PublicBlocksController_getVersion","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"versionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockContentEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Leer el contenido de una version","tags":["blocks"]}},"/v1/blocks/{id}/versions/{versionId}/restore":{"post":{"description":"Vuelve a una version anterior copiandola como version nueva y vigente. No pisa ni borra nada del historial.","operationId":"PublicBlocksController_restoreVersion","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"versionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlockContentEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Restaurar una version","tags":["blocks"]}},"/v1/functions":{"get":{"description":"Devuelve las funciones de webhook de la company. Las funciones son de company, no de proyecto. Los valores de headers y de query string vuelven enmascarados; las claves se ven.","operationId":"PublicFunctionsController_list","parameters":[{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"minimum":0,"default":0,"type":"number"}},{"name":"active_only","required":false,"in":"query","description":"Devuelve solo las funciones activas.","schema":{"default":false,"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicFunctionListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar funciones de webhook","tags":["functions"]},"post":{"description":"Crea una funcion que el asistente puede llamar. La URL tiene que ser https publica: se rechazan loopback, rangos privados, hosts internos del cluster y placeholders en el host.","operationId":"PublicFunctionsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicFunctionCreateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicFunctionEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear una funcion de webhook","tags":["functions"]}},"/v1/functions/{id}":{"get":{"description":"Incluye que bloques la referencian, que es lo que hay que desvincular antes de poder borrarla.","operationId":"PublicFunctionsController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicFunctionEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener una funcion de webhook","tags":["functions"]},"put":{"description":"Actualiza solo los campos presentes. Dentro de context, omitir headers o params preserva los guardados y mandarlos los reemplaza enteros. Devolver el '***' de una lectura da 400 en vez de pisar la credencial.","operationId":"PublicFunctionsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicFunctionUpdateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicFunctionEnvelopeDto"}}}}},"security":[{"PAT":[]}],"summary":"Actualizar una funcion de webhook","tags":["functions"]},"delete":{"description":"Falla con 409 AGENT_TOOL_IN_USE mientras algun bloque la referencie, y el error dice cuales.","operationId":"PublicFunctionsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"PAT":[]}],"summary":"Eliminar una funcion de webhook","tags":["functions"]}},"/v1/scheduling/branches":{"get":{"operationId":"PublicBranchesController_list","parameters":[{"name":"search","required":false,"in":"query","description":"Búsqueda libre por nombre","schema":{"type":"string"}},{"name":"skip","required":false,"in":"query","schema":{"minimum":0,"default":0,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBranchListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar sucursales activas del tenant","tags":["scheduling-branches"]}},"/v1/scheduling/branches/{id}":{"get":{"operationId":"PublicBranchesController_getById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBranchResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener detalle de una sucursal","tags":["scheduling-branches"]}},"/v1/scheduling/services":{"get":{"operationId":"PublicServicesController_list","parameters":[{"name":"branchId","required":false,"in":"query","description":"Filtrar por sucursal","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","schema":{"type":"string"}},{"name":"status","required":false,"in":"query","description":"Estado del servicio (active/inactive)","schema":{"type":"string"}},{"name":"skip","required":false,"in":"query","schema":{"minimum":0,"default":0,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PublicServiceResponseDto"}}}}}},"security":[{"PAT":[]}],"summary":"Listar servicios disponibles del tenant","tags":["scheduling-services"]}},"/v1/scheduling/services/{id}":{"get":{"operationId":"PublicServicesController_getById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicServiceResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener detalle de un servicio","tags":["scheduling-services"]}},"/v1/scheduling/professionals":{"get":{"operationId":"PublicProfessionalsController_list","parameters":[{"name":"branchId","required":false,"in":"query","description":"Filtrar por sucursal","schema":{"type":"string"}},{"name":"serviceId","required":false,"in":"query","description":"Filtrar por servicio prestado","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","schema":{"type":"string"}},{"name":"status","required":false,"in":"query","description":"Estado (active/inactive/on_leave)","schema":{"type":"string"}},{"name":"skip","required":false,"in":"query","schema":{"minimum":0,"default":0,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PublicProfessionalResponseDto"}}}}}},"security":[{"PAT":[]}],"summary":"Listar profesionales del tenant","tags":["scheduling-professionals"]}},"/v1/scheduling/professionals/{id}":{"get":{"operationId":"PublicProfessionalsController_getById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicProfessionalResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener detalle de un profesional","tags":["scheduling-professionals"]}},"/v1/scheduling/availability":{"get":{"description":"Retorna los slots libres para un servicio en una fecha puntual.","operationId":"PublicAvailabilityController_byDate","parameters":[{"name":"serviceId","required":true,"in":"query","description":"Servicio (requerido)","schema":{"type":"string"}},{"name":"date","required":true,"in":"query","description":"Fecha en formato YYYY-MM-DD","schema":{"example":"2026-05-02","type":"string"}},{"name":"branchId","required":false,"in":"query","description":"Sucursal (default: primera del tenant)","schema":{"type":"string"}},{"name":"professionalId","required":false,"in":"query","description":"Profesional específico","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAvailabilityResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Disponibilidad por fecha específica","tags":["scheduling-availability"]}},"/v1/scheduling/availability/range":{"get":{"description":"Retorna los slots libres día a día entre `from` y `to` (inclusive).","operationId":"PublicAvailabilityController_byRange","parameters":[{"name":"serviceId","required":true,"in":"query","description":"Servicio (requerido)","schema":{"type":"string"}},{"name":"from","required":true,"in":"query","description":"Fecha desde (YYYY-MM-DD)","schema":{"type":"string"}},{"name":"to","required":true,"in":"query","description":"Fecha hasta (YYYY-MM-DD, máximo 14 días desde from)","schema":{"type":"string"}},{"name":"branchId","required":false,"in":"query","schema":{"type":"string"}},{"name":"professionalId","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAvailabilityRangeResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Disponibilidad por rango de fechas (máximo 14 días)","tags":["scheduling-availability"]}},"/v1/scheduling/availability/next":{"get":{"description":"Busca los próximos slots libres a partir de `fromDate` (default: hoy) recorriendo hasta `maxDays` días.","operationId":"PublicAvailabilityController_next","parameters":[{"name":"serviceId","required":true,"in":"query","description":"Servicio (requerido)","schema":{"type":"string"}},{"name":"branchId","required":false,"in":"query","schema":{"type":"string"}},{"name":"professionalId","required":false,"in":"query","schema":{"type":"string"}},{"name":"fromDate","required":false,"in":"query","description":"Fecha desde (YYYY-MM-DD)","schema":{"type":"string"}},{"name":"maxDays","required":false,"in":"query","schema":{"minimum":1,"maximum":60,"default":14,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":20,"default":5,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAvailabilityResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Próximas horas disponibles más cercanas","tags":["scheduling-availability"]}},"/v1/scheduling/appointments/{id}":{"get":{"operationId":"PublicAppointmentsController_getById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAppointmentResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener detalle de una cita","tags":["scheduling-appointments"]}},"/v1/scheduling/appointments":{"post":{"description":"Crea una nueva cita en estado pendiente con datos del cliente embebidos.","operationId":"PublicAppointmentsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAppointmentCreateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAppointmentResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear una cita","tags":["scheduling-appointments"]}},"/v1/scheduling/appointments/{id}/confirm":{"post":{"description":"Sólo permite confirmar citas en estado `pending`. Devuelve 409 en caso contrario.","operationId":"PublicAppointmentsController_confirm","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAppointmentResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Confirmar una cita","tags":["scheduling-appointments"]}},"/v1/scheduling/appointments/{id}/cancel":{"post":{"description":"Marca la cita como cancelada con la razón opcional indicada.","operationId":"PublicAppointmentsController_cancel","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelAppointmentDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAppointmentResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Suspender (cancelar) una cita","tags":["scheduling-appointments"]}},"/v1/tenants":{"post":{"operationId":"PublicTenantsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantCreateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTenantResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Crear un tenant (cliente final del developer).","tags":["tenants"]},"get":{"operationId":"PublicTenantsController_list","parameters":[{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"cursor","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTenantListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar tenants.","tags":["tenants"]}},"/v1/tenants/{id}":{"get":{"operationId":"PublicTenantsController_getById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTenantResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Obtener tenant por id.","tags":["tenants"]},"patch":{"operationId":"PublicTenantsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantUpdateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTenantResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Editar tenant.","tags":["tenants"]},"delete":{"operationId":"PublicTenantsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"PAT":[]}],"summary":"Soft-delete del tenant.","tags":["tenants"]}},"/v1/tenants/{id}/whatsapp-configs":{"get":{"operationId":"PublicTenantsController_listWhatsappConfigs","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTenantWhatsappConfigListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar canales WhatsApp asociados al tenant.","tags":["tenants"]}},"/v1/tenants/{id}/setup-links":{"post":{"operationId":"PublicTenantsController_createSetupLink","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupLinkCreateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicSetupLinkResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Generar un setup link para el tenant.","tags":["tenants"]},"get":{"operationId":"PublicTenantsController_listSetupLinks","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicSetupLinkListResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Listar setup links del tenant.","tags":["tenants"]}},"/v1/tenants/{id}/setup-links/{linkId}":{"patch":{"operationId":"PublicTenantsController_updateSetupLink","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"linkId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupLinkUpdateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicSetupLinkResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Editar config de setup link (no rota el token).","tags":["tenants"]},"delete":{"operationId":"PublicTenantsController_revokeSetupLink","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"linkId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"PAT":[]}],"summary":"Revocar setup link. Token deja de ser válido.","tags":["tenants"]}},"/v1/setup/links/{token}":{"get":{"operationId":"PublicSetupController_getLink","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicSetupLinkConfigResponseDto"}}}}},"summary":"Config pública del setup link. Sin auth: el token del link autoriza.","tags":["setup"]}},"/v1/setup/links/{token}/start":{"post":{"operationId":"PublicSetupController_start","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartSetupLinkRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicStartSetupLinkResponseDto"}}}}},"summary":"Inicia el flujo de conexión (Embedded Signup, Coexistence o QR). Sin persistencia intermedia: el state HMAC firmado correlaciona el callback.","tags":["setup"]}},"/v1/setup/links/{token}/complete":{"post":{"operationId":"PublicSetupController_complete","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompleteSetupLinkRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCompleteSetupLinkResponseDto"}}}}},"summary":"Cierra el flujo Embedded Signup iniciado vía Facebook JS SDK. Recibe code + waba_id + phone_number_id, verifica state HMAC y crea el Channel.","tags":["setup"]}},"/v1/setup/links/{token}/qr-stream":{"get":{"operationId":"PublicSetupController_qrStream","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}},{"name":"pending_id","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Stream SSE. Eventos: qr | connecting | connected | failed | disconnected.","content":{"text/event-stream":{"schema":{"type":"string"}}}}},"summary":"SSE proxy del pairing QR. Reusa wa_qr_sessions de api-client.","tags":["setup"]}},"/v1/setup/links/{token}/attach-channel":{"post":{"operationId":"PublicSetupController_attachChannel","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachChannelRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAttachChannelResponseDto"}}}}},"summary":"Tras QR connect: aplica dev_tenant_id al Channel ya creado por api-client.","tags":["setup"]}},"/v1/auth/cli/select-project":{"post":{"operationId":"CliSessionController_selectProject","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SelectProjectRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCliSelectProjectResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Cambia el project activo de la session CLI y emite un JWT nuevo. Sólo aceptable con un JWT del CLI (no con PAT).","tags":["cli-session"]}},"/v1/auth/cli/me":{"get":{"operationId":"CliSessionController_me","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCliMeResponseDto"}}}}},"security":[{"PAT":[]}],"summary":"Datos de la session CLI actual (user, company, current project). Útil para `keebai whoami`.","tags":["cli-session"]}}},"info":{"title":"Keebai Public API","description":"Superficie pública REST autenticada con Personal Access Tokens (PAT).","version":"1.0.0","contact":{}},"tags":[],"servers":[{"url":"https://api.keebai.com","description":"Production"}],"components":{"securitySchemes":{"PAT":{"scheme":"bearer","bearerFormat":"kbai_pk_<hex>","type":"http","description":"Personal Access Token con prefijo `kbai_pk_`. Generar desde el portal con permiso `developer.manage_tokens`."}},"schemas":{"MeResponseDto":{"type":"object","properties":{"permissions":{"description":"Permisos efectivos del token: intersección entre los scopes del token y los permisos actuales del usuario.","example":["conversations.read","contacts.read"],"type":"array","items":{"type":"string"}}},"required":["permissions"]},"TextMessagePayloadDto":{"type":"object","properties":{"type":{"type":"string","enum":["text"]},"body":{"type":"string","example":"Hola, tu pedido va en camino.","maxLength":4096},"preview_url":{"type":"boolean","description":"Render a link preview for the first URL in the body."}},"required":["type","body"]},"ImageMessagePayloadDto":{"type":"object","properties":{"link":{"type":"string","description":"Public HTTPS URL to the file."},"media_id":{"type":"string","description":"Previously-uploaded media id (POST /v1/media/upload)."},"type":{"type":"string","enum":["image"]},"caption":{"type":"string","maxLength":1024}},"required":["type"]},"VideoMessagePayloadDto":{"type":"object","properties":{"link":{"type":"string","description":"Public HTTPS URL to the file."},"media_id":{"type":"string","description":"Previously-uploaded media id (POST /v1/media/upload)."},"type":{"type":"string","enum":["video"]},"caption":{"type":"string","maxLength":1024}},"required":["type"]},"AudioMessagePayloadDto":{"type":"object","properties":{"link":{"type":"string","description":"Public HTTPS URL to the file."},"media_id":{"type":"string","description":"Previously-uploaded media id (POST /v1/media/upload)."},"type":{"type":"string","enum":["audio"]},"voice":{"type":"boolean","description":"Send as a voice note (PTT) instead of an audio file."}},"required":["type"]},"DocumentMessagePayloadDto":{"type":"object","properties":{"link":{"type":"string","description":"Public HTTPS URL to the file."},"media_id":{"type":"string","description":"Previously-uploaded media id (POST /v1/media/upload)."},"type":{"type":"string","enum":["document"]},"filename":{"type":"string","maxLength":240},"caption":{"type":"string","maxLength":1024}},"required":["type"]},"StickerMessagePayloadDto":{"type":"object","properties":{"link":{"type":"string","description":"Public HTTPS URL to the file."},"media_id":{"type":"string","description":"Previously-uploaded media id (POST /v1/media/upload)."},"type":{"type":"string","enum":["sticker"]}},"required":["type"]},"LocationMessagePayloadDto":{"type":"object","properties":{"type":{"type":"string","enum":["location"]},"latitude":{"type":"number","example":-33.4489},"longitude":{"type":"number","example":-70.6693},"name":{"type":"string","maxLength":1000},"address":{"type":"string","maxLength":1000}},"required":["type","latitude","longitude"]},"ContactNameDto":{"type":"object","properties":{"formatted_name":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"}},"required":["formatted_name"]},"ContactPhoneDto":{"type":"object","properties":{"phone":{"type":"string"},"type":{"type":"string"},"wa_id":{"type":"string"}},"required":["phone"]},"ContactEmailDto":{"type":"object","properties":{"email":{"type":"string"},"type":{"type":"string"}},"required":["email"]},"ContactUrlDto":{"type":"object","properties":{"url":{"type":"string"},"type":{"type":"string"}},"required":["url"]},"ContactOrgDto":{"type":"object","properties":{"company":{"type":"string"},"department":{"type":"string"},"title":{"type":"string"}}},"ContactCardDto":{"type":"object","properties":{"name":{"$ref":"#/components/schemas/ContactNameDto"},"phones":{"type":"array","items":{"$ref":"#/components/schemas/ContactPhoneDto"}},"emails":{"type":"array","items":{"$ref":"#/components/schemas/ContactEmailDto"}},"urls":{"type":"array","items":{"$ref":"#/components/schemas/ContactUrlDto"}},"org":{"$ref":"#/components/schemas/ContactOrgDto"},"birthday":{"type":"string","example":"1990-03-24"}},"required":["name"]},"ContactsMessagePayloadDto":{"type":"object","properties":{"type":{"type":"string","enum":["contacts"]},"contacts":{"minItems":1,"maxItems":20,"type":"array","items":{"$ref":"#/components/schemas/ContactCardDto"}}},"required":["type","contacts"]},"ReactionMessagePayloadDto":{"type":"object","properties":{"type":{"type":"string","enum":["reaction"]},"message_id":{"type":"string","description":"Provider message id (wamid.* on WhatsApp) to react to."},"emoji":{"type":"string","description":"Emoji to send as reaction. Empty string clears a previous reaction.","example":"👍"}},"required":["type","message_id","emoji"]},"TemplateFlowButtonDto":{"type":"object","properties":{"flow_token":{"type":"string","description":"Opaque correlation id echoed back on the flow response webhook. Must be unique per send.","example":"srv-9f2c41"},"button_index":{"type":"number","description":"Zero-based index of the FLOW button in the template.","default":0},"flow_action_data":{"type":"object","description":"Initial screen data handed to the Flow when it opens. Only used when the template button was created with flow_action=navigate.","example":{"ticket_id":"A-1"}}},"required":["flow_token"]},"TemplateMessagePayloadDto":{"type":"object","properties":{"type":{"type":"string","enum":["template"]},"name":{"type":"string","example":"welcome_v2"},"language":{"type":"string","example":"es"},"variables":{"type":"object","example":{"nombre":"Juan","monto":"1500"},"description":"Named template variables (Meta parameter_name)."},"flow":{"$ref":"#/components/schemas/TemplateFlowButtonDto"}},"required":["type","name","language"]},"InteractiveHeaderDto":{"type":"object","properties":{"type":{"type":"string","enum":["text"]},"text":{"type":"string","maxLength":60}},"required":["type","text"]},"InteractiveButtonDto":{"type":"object","properties":{"id":{"type":"string","maxLength":256},"title":{"type":"string","maxLength":20}},"required":["id","title"]},"ButtonsMessagePayloadDto":{"type":"object","properties":{"body_text":{"type":"string","maxLength":1024},"header":{"$ref":"#/components/schemas/InteractiveHeaderDto"},"footer_text":{"type":"string","maxLength":60},"type":{"type":"string","enum":["buttons"]},"buttons":{"minItems":1,"maxItems":3,"type":"array","items":{"$ref":"#/components/schemas/InteractiveButtonDto"}}},"required":["body_text","type","buttons"]},"InteractiveListRowDto":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string","maxLength":24},"description":{"type":"string","maxLength":72}},"required":["id","title"]},"InteractiveListSectionDto":{"type":"object","properties":{"title":{"type":"string","maxLength":24},"rows":{"minItems":1,"maxItems":10,"type":"array","items":{"$ref":"#/components/schemas/InteractiveListRowDto"}}},"required":["rows"]},"ListMessagePayloadDto":{"type":"object","properties":{"body_text":{"type":"string","maxLength":1024},"header":{"$ref":"#/components/schemas/InteractiveHeaderDto"},"footer_text":{"type":"string","maxLength":60},"type":{"type":"string","enum":["list"]},"button_text":{"type":"string","maxLength":20,"description":"Label of the button that opens the list."},"sections":{"minItems":1,"maxItems":10,"type":"array","items":{"$ref":"#/components/schemas/InteractiveListSectionDto"}}},"required":["body_text","type","button_text","sections"]},"CtaUrlMessagePayloadDto":{"type":"object","properties":{"body_text":{"type":"string","maxLength":1024},"header":{"$ref":"#/components/schemas/InteractiveHeaderDto"},"footer_text":{"type":"string","maxLength":60},"type":{"type":"string","enum":["cta_url"]},"display_text":{"type":"string","maxLength":20},"url":{"type":"string"}},"required":["body_text","type","display_text","url"]},"CatalogMessagePayloadDto":{"type":"object","properties":{"body_text":{"type":"string","maxLength":1024},"header":{"$ref":"#/components/schemas/InteractiveHeaderDto"},"footer_text":{"type":"string","maxLength":60},"type":{"type":"string","enum":["catalog"]},"thumbnail_product_retailer_id":{"type":"string","description":"Retailer id of the product used as the catalog thumbnail."}},"required":["body_text","type"]},"CarouselCardHeaderDto":{"type":"object","properties":{"type":{"type":"string","enum":["image","video"]},"link":{"type":"string","description":"Public HTTPS URL of the card media. Meta rejects .webp images on carousel headers."}},"required":["type","link"]},"CarouselCardActionDto":{"type":"object","properties":{"display_text":{"type":"string","maxLength":20},"url":{"type":"string"}},"required":["display_text","url"]},"CarouselCardDto":{"type":"object","properties":{"header":{"$ref":"#/components/schemas/CarouselCardHeaderDto"},"body_text":{"type":"string","maxLength":1024},"action":{"$ref":"#/components/schemas/CarouselCardActionDto"}},"required":["header","action"]},"CarouselMessagePayloadDto":{"type":"object","properties":{"body_text":{"type":"string","maxLength":1024},"header":{"$ref":"#/components/schemas/InteractiveHeaderDto"},"footer_text":{"type":"string","maxLength":60},"type":{"type":"string","enum":["carousel"]},"cards":{"minItems":1,"maxItems":10,"type":"array","items":{"$ref":"#/components/schemas/CarouselCardDto"}}},"required":["body_text","type","cards"]},"FlowActionPayloadDto":{"type":"object","properties":{"screen":{"type":"string","description":"Name of the first screen to open, as declared in the Flow JSON.","example":"WELCOME"},"data":{"type":"object","description":"Initial data injected into that screen.","example":{"customer_name":"Juan"}}},"required":["screen"]},"FlowMessagePayloadDto":{"type":"object","properties":{"type":{"type":"string","enum":["flow"]},"flow_id":{"type":"string","description":"Meta Flow id, as returned by POST /v1/flows.","example":"1234567890123456"},"flow_token":{"type":"string","description":"Opaque correlation id echoed back on the flow response webhook. Must be unique per send.","example":"srv-9f2c41"},"flow_cta":{"type":"string","description":"Label of the button that opens the Flow.","maxLength":20,"example":"Reservar"},"flow_action":{"type":"string","enum":["navigate","data_exchange"],"default":"navigate","description":"`navigate` opens the screen named in flow_action_payload; `data_exchange` hands control to the Flow endpoint."},"flow_action_payload":{"description":"Required when flow_action is `navigate`.","allOf":[{"$ref":"#/components/schemas/FlowActionPayloadDto"}]},"mode":{"type":"string","enum":["draft","published"],"default":"published","description":"Send a Flow that has not been published yet. Draft mode only reaches numbers listed as testers on the WABA."},"body_text":{"type":"string","maxLength":1024},"header_text":{"type":"string","maxLength":60},"footer_text":{"type":"string","maxLength":60}},"required":["type","flow_id","flow_token","flow_cta","body_text"]},"MessageContextDto":{"type":"object","properties":{"message_id":{"type":"string","description":"Provider message id (wamid.* on WhatsApp) this message quotes as a reply."}},"required":["message_id"]},"SendMessageDto":{"type":"object","properties":{"channel":{"type":"string","enum":["whatsapp","whatsapp_qr","instagram","messenger"],"example":"whatsapp","description":"Channel the message is delivered through."},"channel_id":{"type":"string","example":"665f1a2b3c4d5e6f70819234","description":"Keebai channel id. Optional when the tenant has exactly one active channel of the given type; required to disambiguate otherwise."},"phone_number_id":{"type":"string","example":"100000000000001","description":"WhatsApp-only alias for channel_id: the Meta phone_number_id of the sending number. Ignored on other channels."},"to":{"type":"string","example":"+5491155555555","description":"Recipient. E.164 phone number on whatsapp and whatsapp_qr; the Meta-scoped id (IGSID / PSID) on instagram and messenger."},"context":{"$ref":"#/components/schemas/MessageContextDto"},"meta_data":{"type":"object","description":"Free-form metadata persisted with the message. Returned on webhooks for correlation."},"message":{"oneOf":[{"$ref":"#/components/schemas/TextMessagePayloadDto"},{"$ref":"#/components/schemas/ImageMessagePayloadDto"},{"$ref":"#/components/schemas/VideoMessagePayloadDto"},{"$ref":"#/components/schemas/AudioMessagePayloadDto"},{"$ref":"#/components/schemas/DocumentMessagePayloadDto"},{"$ref":"#/components/schemas/StickerMessagePayloadDto"},{"$ref":"#/components/schemas/LocationMessagePayloadDto"},{"$ref":"#/components/schemas/ContactsMessagePayloadDto"},{"$ref":"#/components/schemas/ReactionMessagePayloadDto"},{"$ref":"#/components/schemas/TemplateMessagePayloadDto"},{"$ref":"#/components/schemas/ButtonsMessagePayloadDto"},{"$ref":"#/components/schemas/ListMessagePayloadDto"},{"$ref":"#/components/schemas/CtaUrlMessagePayloadDto"},{"$ref":"#/components/schemas/CatalogMessagePayloadDto"},{"$ref":"#/components/schemas/CarouselMessagePayloadDto"},{"$ref":"#/components/schemas/FlowMessagePayloadDto"}],"discriminator":{"propertyName":"type","mapping":{"text":"#/components/schemas/TextMessagePayloadDto","image":"#/components/schemas/ImageMessagePayloadDto","video":"#/components/schemas/VideoMessagePayloadDto","audio":"#/components/schemas/AudioMessagePayloadDto","document":"#/components/schemas/DocumentMessagePayloadDto","sticker":"#/components/schemas/StickerMessagePayloadDto","location":"#/components/schemas/LocationMessagePayloadDto","contacts":"#/components/schemas/ContactsMessagePayloadDto","reaction":"#/components/schemas/ReactionMessagePayloadDto","template":"#/components/schemas/TemplateMessagePayloadDto","buttons":"#/components/schemas/ButtonsMessagePayloadDto","list":"#/components/schemas/ListMessagePayloadDto","cta_url":"#/components/schemas/CtaUrlMessagePayloadDto","catalog":"#/components/schemas/CatalogMessagePayloadDto","carousel":"#/components/schemas/CarouselMessagePayloadDto","flow":"#/components/schemas/FlowMessagePayloadDto"}}}},"required":["channel","to","message"]},"SingleSendResponse":{"type":"object","properties":{"message_id":{"type":"string","description":"Meta message_id (wamid.*) of the sent WhatsApp message."},"status":{"type":"string","example":"sent"},"sent_at":{"type":"string","description":"ISO-8601 timestamp of the dispatch."}},"required":["message_id","status","sent_at"]},"MarkReadDto":{"type":"object","properties":{"channel_id":{"type":"string","example":"665f1a2b3c4d5e6f70819234","description":"Keebai channel id. Optional when the tenant has exactly one active channel of the given type; required to disambiguate otherwise."},"phone_number_id":{"type":"string","example":"100000000000001","description":"WhatsApp-only alias for channel_id: the Meta phone_number_id of the sending number. Ignored on other channels."},"message_id":{"type":"string","description":"Meta message_id (wamid.*) to mark as read."},"typing_indicator":{"type":"string","enum":["text","off"]}},"required":["message_id"]},"MarkReadResponse":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]},"SendRawDto":{"type":"object","properties":{"channel_id":{"type":"string","example":"665f1a2b3c4d5e6f70819234","description":"Keebai channel id. Optional when the tenant has exactly one active channel of the given type; required to disambiguate otherwise."},"phone_number_id":{"type":"string","example":"100000000000001","description":"WhatsApp-only alias for channel_id: the Meta phone_number_id of the sending number. Ignored on other channels."},"body":{"type":"object","description":"Raw Meta Graph API messages body. Sent as-is to /{phone_number_id}/messages. Use only when POST /v1/messages has no matching type."},"meta_data":{"type":"object","description":"Free-form metadata persisted with the message. Returned on webhooks for correlation."}},"required":["body"]},"BulkRecipientDto":{"type":"object","properties":{"to":{"type":"string","example":"+5491155555555"},"variables":{"type":"object","example":{"nombre":"Juan"}},"meta_data":{"type":"object","description":"Free-form metadata persisted with the message. Returned on webhooks for correlation."}},"required":["to"]},"SendBulkDto":{"type":"object","properties":{"channel_id":{"type":"string","example":"665f1a2b3c4d5e6f70819234","description":"Keebai channel id. Optional when the tenant has exactly one active channel of the given type; required to disambiguate otherwise."},"phone_number_id":{"type":"string","example":"100000000000001","description":"WhatsApp-only alias for channel_id: the Meta phone_number_id of the sending number. Ignored on other channels."},"template_name":{"type":"string","example":"welcome_v2"},"language":{"type":"string","example":"es"},"campaign_name":{"type":"string","example":"Onboarding marzo 2026"},"recipients":{"minItems":1,"maxItems":5000,"type":"array","items":{"$ref":"#/components/schemas/BulkRecipientDto"}}},"required":["template_name","language","recipients"]},"BulkDispatchResponse":{"type":"object","properties":{"broadcast_id":{"type":"string"},"status":{"type":"string","example":"scheduled"},"total_recipients":{"type":"number"},"scheduled_at":{"type":"string","nullable":true}},"required":["broadcast_id","status","total_recipients"]},"BulkStatusResponse":{"type":"object","properties":{"broadcast_id":{"type":"string"},"status":{"type":"string"},"total_recipients":{"type":"number"},"sent":{"type":"number"},"failed":{"type":"number"},"pending":{"type":"number"},"started_at":{"type":"string","nullable":true},"completed_at":{"type":"string","nullable":true}},"required":["broadcast_id","status","total_recipients","sent","failed","pending"]},"UploadMediaDto":{"type":"object","properties":{"phone_number_id":{"type":"string","example":"100000000000001"},"type":{"type":"string","example":"image/png"},"filename":{"type":"string"}},"required":["phone_number_id","type"]},"MediaUploadResponse":{"type":"object","properties":{"media_id":{"type":"string"},"mime_type":{"type":"string"},"size":{"type":"number"}},"required":["media_id","mime_type","size"]},"MediaMetadataResponse":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"mime_type":{"type":"string"},"file_size":{"type":"number"},"sha256":{"type":"string"},"messaging_product":{"type":"string"}},"required":["id","url","mime_type","file_size"]},"CreateFlowDto":{"type":"object","properties":{"channel_id":{"type":"string","example":"665f1a2b3c4d5e6f70819234","description":"Keebai channel id. Optional when the tenant has exactly one active channel of the given type; required to disambiguate otherwise."},"phone_number_id":{"type":"string","example":"100000000000001","description":"WhatsApp-only alias for channel_id: the Meta phone_number_id of the sending number. Ignored on other channels."},"name":{"type":"string","example":"reserva-mesa","maxLength":100},"description":{"type":"string","maxLength":500},"categories":{"type":"array","default":["OTHER"],"items":{"type":"string","enum":["OTHER","SIGN_UP","SIGN_IN","APPOINTMENT_BOOKING","LEAD_GENERATION","CONTACT_US","CUSTOMER_SUPPORT","SURVEY"]}},"flow_data":{"type":"object","description":"Flow JSON as defined by Meta (version, screens, routing_model). Uploaded as the Flow asset on create.","example":{"version":"7.0","screens":[{"id":"WELCOME","title":"Reserva","terminal":true,"layout":{"type":"SingleColumnLayout","children":[]}}]}},"metadata":{"type":"object","description":"Free-form metadata stored alongside the Flow in Keebai."}},"required":["name","flow_data"]},"FlowResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Keebai flow id."},"channel_id":{"type":"string","description":"Keebai channel this Flow belongs to."},"name":{"type":"string"},"description":{"type":"string","nullable":true},"meta_flow_id":{"type":"string","nullable":true,"description":"Meta Flow id. Use it as `flow_id` when sending a message of type `flow`. Null until Meta accepts the Flow."},"categories":{"type":"array","items":{"type":"string","enum":["OTHER","SIGN_UP","SIGN_IN","APPOINTMENT_BOOKING","LEAD_GENERATION","CONTACT_US","CUSTOMER_SUPPORT","SURVEY"]}},"status":{"type":"string","enum":["draft","published","archived"]},"flow_data":{"type":"object","description":"Flow JSON currently stored in Keebai."},"metadata":{"type":"object"},"created_at":{"type":"string","format":"date-time","nullable":true},"updated_at":{"type":"string","format":"date-time","nullable":true}},"required":["id","channel_id","name","categories","status"]},"FlowListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FlowResponseDto"}}},"required":["data"]},"UpdateFlowDto":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"description":{"type":"string","maxLength":500},"categories":{"type":"array","items":{"type":"string","enum":["OTHER","SIGN_UP","SIGN_IN","APPOINTMENT_BOOKING","LEAD_GENERATION","CONTACT_US","CUSTOMER_SUPPORT","SURVEY"]}},"flow_data":{"type":"object","description":"Replacement Flow JSON. Re-uploaded as the Flow asset at Meta."},"metadata":{"type":"object"}}},"PublicTemplateDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"language":{"type":"string"},"status":{"type":"string"},"category":{"type":"string"},"parameter_format":{"type":"string"},"variables":{"type":"array","items":{"type":"string"}}},"required":["id","name","language","status","category","variables"]},"PaginatedTemplatesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PublicTemplateDto"}},"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"}},"required":["items","page","limit","total"]},"TemplateButtonDto":{"type":"object","properties":{"type":{"type":"string","enum":["QUICK_REPLY","URL","PHONE_NUMBER","FLOW","VOICE_CALL","COPY_CODE","OTP"]},"text":{"type":"string","maxLength":25},"url":{"type":"string"},"phone_number":{"type":"string"},"example":{"type":"array","items":{"type":"string"}},"flow_id":{"type":"string"},"flow_action":{"type":"string","enum":["navigate","data_exchange"]},"coupon_code":{"type":"string"},"otp_type":{"type":"string","enum":["COPY_CODE","ONE_TAP","ZERO_TAP"]},"autofill_text":{"type":"string"},"package_name":{"type":"string"},"signature_hash":{"type":"string"}},"required":["type","text"]},"NamedParamDto":{"type":"object","properties":{"param_name":{"type":"string","example":"nombre"},"example":{"type":"string","example":"Juan"}},"required":["param_name","example"]},"TemplateExampleDto":{"type":"object","properties":{"header_text":{"type":"array","items":{"type":"string"}},"header_text_named_params":{"type":"array","items":{"$ref":"#/components/schemas/NamedParamDto"}},"header_handle":{"type":"array","items":{"type":"string"}},"body_text":{"type":"array","items":{"type":"string"}},"body_text_named_params":{"type":"array","items":{"$ref":"#/components/schemas/NamedParamDto"}}}},"TemplateComponentDto":{"type":"object","properties":{"type":{"type":"string","enum":["HEADER","BODY","FOOTER","BUTTONS"]},"format":{"type":"string","enum":["TEXT","IMAGE","VIDEO","DOCUMENT"]},"text":{"type":"string","maxLength":1024},"buttons":{"type":"array","items":{"$ref":"#/components/schemas/TemplateButtonDto"}},"example":{"$ref":"#/components/schemas/TemplateExampleDto"},"add_security_recommendation":{"type":"boolean"},"code_expiration_minutes":{"type":"number"}},"required":["type"]},"CreateTemplateDto":{"type":"object","properties":{"channel_id":{"type":"string","description":"ObjectId del canal WhatsApp donde se crea el template."},"name":{"type":"string","maxLength":512,"description":"Nombre del template. Solo minúsculas, números y guiones bajos.","example":"welcome_v2"},"language":{"type":"string","maxLength":10,"example":"es_CL"},"category":{"type":"string","enum":["MARKETING","UTILITY","AUTHENTICATION"]},"parameter_format":{"type":"string","enum":["NAMED","POSITIONAL"]},"components":{"type":"array","items":{"$ref":"#/components/schemas/TemplateComponentDto"}},"metadata":{"type":"object","additionalProperties":true}},"required":["channel_id","name","language","category","components"]},"UpdateTemplateDto":{"type":"object","properties":{"channel_id":{"type":"string","description":"ObjectId del canal WhatsApp dueño del template (requerido por upstream)."},"name":{"type":"string","maxLength":512},"language":{"type":"string","maxLength":10},"category":{"type":"string","enum":["MARKETING","UTILITY","AUTHENTICATION"]},"parameter_format":{"type":"string","enum":["NAMED","POSITIONAL"]},"components":{"type":"array","items":{"$ref":"#/components/schemas/TemplateComponentDto"}},"status":{"type":"string","enum":["PENDING","IN_REVIEW","REJECTED","APPROVED","PAUSED","DISABLED","IN_APPEAL"]},"metadata":{"type":"object","additionalProperties":true}},"required":["channel_id"]},"CreateWebhookDto":{"type":"object","properties":{"name":{"type":"string","example":"Producción - Notificaciones CRM"},"url":{"type":"string","example":"https://hooks.example.com/keebai"},"events":{"type":"array","description":"Eventos a los que se subscribe.","items":{"type":"string","enum":["whatsapp.message.received","whatsapp.message.sent","whatsapp.message.delivered","whatsapp.message.read","whatsapp.message.failed","whatsapp.template.status_updated","whatsapp.channel.connected","whatsapp.channel.disconnected","conversation.created","conversation.escalated_to_human","instagram.message.received","whatsapp.flow.response","crm.customer.created","crm.customer.updated","crm.customer.deleted","crm.ticket.created","crm.ticket.updated","crm.ticket.deleted","crm.ticket.stage_changed","crm.ticket.closed","crm.task.created","crm.task.updated","crm.task.deleted","crm.task.completed","crm.note.created","crm.note.updated","crm.note.deleted","scheduling.appointment.created","scheduling.appointment.updated","scheduling.appointment.confirmed","scheduling.appointment.cancelled","scheduling.appointment.rescheduled","scheduling.appointment.no_show","ecommerce.sale.created","ecommerce.sale.paid","ecommerce.sale.cancelled"]}},"headers":{"type":"object","description":"Headers extra a enviar en cada delivery.","example":{"X-Tenant-Origin":"crm"}},"is_active":{"type":"boolean","default":true}},"required":["name","url","events"]},"WebhookCreatedResponseDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string","enum":["whatsapp.message.received","whatsapp.message.sent","whatsapp.message.delivered","whatsapp.message.read","whatsapp.message.failed","whatsapp.template.status_updated","whatsapp.channel.connected","whatsapp.channel.disconnected","conversation.created","conversation.escalated_to_human","instagram.message.received","whatsapp.flow.response","crm.customer.created","crm.customer.updated","crm.customer.deleted","crm.ticket.created","crm.ticket.updated","crm.ticket.deleted","crm.ticket.stage_changed","crm.ticket.closed","crm.task.created","crm.task.updated","crm.task.deleted","crm.task.completed","crm.note.created","crm.note.updated","crm.note.deleted","scheduling.appointment.created","scheduling.appointment.updated","scheduling.appointment.confirmed","scheduling.appointment.cancelled","scheduling.appointment.rescheduled","scheduling.appointment.no_show","ecommerce.sale.created","ecommerce.sale.paid","ecommerce.sale.cancelled"]}},"is_active":{"type":"boolean"},"secret_prefix":{"type":"string","description":"Prefijo del secret para identificación visual."},"headers":{"type":"object"},"failure_count":{"type":"number"},"disabled_reason":{"type":"string","enum":["excessive_failures","manual"],"nullable":true},"last_delivery_at":{"type":"object","nullable":true},"created_at":{"type":"string"},"updated_at":{"type":"string"},"secret":{"type":"string","description":"Secret raw (whsec_...). Se muestra UNA SOLA VEZ. Guárdalo de inmediato — no se puede recuperar."}},"required":["id","name","url","events","is_active","secret_prefix","headers","failure_count","created_at","updated_at","secret"]},"WebhookResponseDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string","enum":["whatsapp.message.received","whatsapp.message.sent","whatsapp.message.delivered","whatsapp.message.read","whatsapp.message.failed","whatsapp.template.status_updated","whatsapp.channel.connected","whatsapp.channel.disconnected","conversation.created","conversation.escalated_to_human","instagram.message.received","whatsapp.flow.response","crm.customer.created","crm.customer.updated","crm.customer.deleted","crm.ticket.created","crm.ticket.updated","crm.ticket.deleted","crm.ticket.stage_changed","crm.ticket.closed","crm.task.created","crm.task.updated","crm.task.deleted","crm.task.completed","crm.note.created","crm.note.updated","crm.note.deleted","scheduling.appointment.created","scheduling.appointment.updated","scheduling.appointment.confirmed","scheduling.appointment.cancelled","scheduling.appointment.rescheduled","scheduling.appointment.no_show","ecommerce.sale.created","ecommerce.sale.paid","ecommerce.sale.cancelled"]}},"is_active":{"type":"boolean"},"secret_prefix":{"type":"string","description":"Prefijo del secret para identificación visual."},"headers":{"type":"object"},"failure_count":{"type":"number"},"disabled_reason":{"type":"string","enum":["excessive_failures","manual"],"nullable":true},"last_delivery_at":{"type":"object","nullable":true},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","url","events","is_active","secret_prefix","headers","failure_count","created_at","updated_at"]},"WebhookListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookResponseDto"}}},"required":["data"]},"UpdateWebhookDto":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string","enum":["whatsapp.message.received","whatsapp.message.sent","whatsapp.message.delivered","whatsapp.message.read","whatsapp.message.failed","whatsapp.template.status_updated","whatsapp.channel.connected","whatsapp.channel.disconnected","conversation.created","conversation.escalated_to_human","instagram.message.received","whatsapp.flow.response","crm.customer.created","crm.customer.updated","crm.customer.deleted","crm.ticket.created","crm.ticket.updated","crm.ticket.deleted","crm.ticket.stage_changed","crm.ticket.closed","crm.task.created","crm.task.updated","crm.task.deleted","crm.task.completed","crm.note.created","crm.note.updated","crm.note.deleted","scheduling.appointment.created","scheduling.appointment.updated","scheduling.appointment.confirmed","scheduling.appointment.cancelled","scheduling.appointment.rescheduled","scheduling.appointment.no_show","ecommerce.sale.created","ecommerce.sale.paid","ecommerce.sale.cancelled"]}},"headers":{"type":"object"},"is_active":{"type":"boolean"}}},"TestWebhookDto":{"type":"object","properties":{"event_type":{"type":"string","enum":["whatsapp.message.received","whatsapp.message.sent","whatsapp.message.delivered","whatsapp.message.read","whatsapp.message.failed","whatsapp.template.status_updated","whatsapp.channel.connected","whatsapp.channel.disconnected","conversation.created","conversation.escalated_to_human","instagram.message.received","whatsapp.flow.response","crm.customer.created","crm.customer.updated","crm.customer.deleted","crm.ticket.created","crm.ticket.updated","crm.ticket.deleted","crm.ticket.stage_changed","crm.ticket.closed","crm.task.created","crm.task.updated","crm.task.deleted","crm.task.completed","crm.note.created","crm.note.updated","crm.note.deleted","scheduling.appointment.created","scheduling.appointment.updated","scheduling.appointment.confirmed","scheduling.appointment.cancelled","scheduling.appointment.rescheduled","scheduling.appointment.no_show","ecommerce.sale.created","ecommerce.sale.paid","ecommerce.sale.cancelled"]}},"required":["event_type"]},"WebhookTestAcceptedResponseDto":{"type":"object","properties":{"accepted":{"type":"boolean","description":"Siempre true: el evento quedó encolado."},"event_id":{"type":"string","description":"Id del evento sintético, para cruzarlo con el delivery"}},"required":["accepted","event_id"]},"DeliveryResponseDto":{"type":"object","properties":{"id":{"type":"string"},"subscription_id":{"type":"string"},"event_id":{"type":"string"},"event_type":{"type":"string","enum":["whatsapp.message.received","whatsapp.message.sent","whatsapp.message.delivered","whatsapp.message.read","whatsapp.message.failed","whatsapp.template.status_updated","whatsapp.channel.connected","whatsapp.channel.disconnected","conversation.created","conversation.escalated_to_human","instagram.message.received","whatsapp.flow.response","crm.customer.created","crm.customer.updated","crm.customer.deleted","crm.ticket.created","crm.ticket.updated","crm.ticket.deleted","crm.ticket.stage_changed","crm.ticket.closed","crm.task.created","crm.task.updated","crm.task.deleted","crm.task.completed","crm.note.created","crm.note.updated","crm.note.deleted","scheduling.appointment.created","scheduling.appointment.updated","scheduling.appointment.confirmed","scheduling.appointment.cancelled","scheduling.appointment.rescheduled","scheduling.appointment.no_show","ecommerce.sale.created","ecommerce.sale.paid","ecommerce.sale.cancelled"]},"status":{"type":"string","enum":["pending","success","failed","dead"]},"status_code":{"type":"object","nullable":true},"attempts":{"type":"number"},"last_error":{"type":"object","nullable":true},"delivered_at":{"type":"object","nullable":true},"duration_ms":{"type":"object","nullable":true},"created_at":{"type":"string"}},"required":["id","subscription_id","event_id","event_type","status","attempts","created_at"]},"DeliveryListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DeliveryResponseDto"}},"next_cursor":{"type":"object","nullable":true}},"required":["data"]},"PublicChannelWhatsappDto":{"type":"object","properties":{"phone_number_id":{"type":"string","description":"phone_number_id emitido por Meta"},"phone_number":{"type":"string"},"business_account_id":{"type":"string"},"coexistence_enabled":{"type":"boolean"},"token_expires_at":{"type":"object","format":"date-time","nullable":true}},"required":["phone_number_id","phone_number","business_account_id","coexistence_enabled","token_expires_at"]},"PublicChannelInstagramDto":{"type":"object","properties":{"scope_id":{"type":"string"},"igb_business_account_id":{"type":"string"},"username":{"type":"string"},"token_expires_at":{"type":"object","format":"date-time","nullable":true}},"required":["scope_id","igb_business_account_id","username","token_expires_at"]},"PublicChannelResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"ObjectId del canal"},"type":{"type":"string","description":"whatsapp | instagram | messenger …"},"name":{"type":"string"},"is_active":{"type":"boolean"},"whatsapp":{"$ref":"#/components/schemas/PublicChannelWhatsappDto"},"instagram":{"$ref":"#/components/schemas/PublicChannelInstagramDto"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","type","name","is_active","created_at","updated_at"]},"PublicChannelListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicChannelResponseDto"}}},"required":["data"]},"WhatsappConnectRequestDto":{"type":"object","properties":{"mode":{"type":"string","description":"Modo de conexión: `embedded_signup` (default) abre el flujo de Meta en el portal; `qr` devuelve un stream SSE para escanear desde la terminal con WhatsApp multi-dispositivo.","enum":["embedded_signup","qr"],"default":"embedded_signup"},"pipeline_id":{"type":"string","description":"Si se especifica, el canal recién creado se asocia automáticamente al pipeline. Sólo aplica al modo embedded_signup."},"coexistence_enabled":{"type":"boolean","description":"Activa el modo coexistencia (si el cliente ya tiene la app de WhatsApp Business activa). Sólo aplica al modo embedded_signup."},"name":{"type":"string","description":"Etiqueta visible del canal cuando se conecta por QR. Default: \"WhatsApp QR\"."}}},"PublicConnectSessionResponseDto":{"type":"object","properties":{"session_id":{"type":"string"},"provider":{"type":"string","description":"whatsapp | whatsapp_qr"},"mode":{"type":"string","description":"embedded_signup | qr"},"verification_uri":{"type":"string","description":"URL del portal donde el usuario completa el Embedded Signup"},"stream_url":{"type":"string","description":"Ruta del stream SSE de pairing, sólo en modo qr"},"expires_in":{"type":"number","description":"Segundos hasta que la sesión expira"},"poll_interval":{"type":"number","description":"Segundos sugeridos entre polls"}},"required":["session_id","provider","mode","expires_in","poll_interval"]},"PublicConnectSessionPollResponseDto":{"type":"object","properties":{"session_id":{"type":"string"},"status":{"type":"string","description":"pending | completed | expired | failed"},"error":{"type":"string","description":"Detalle del fallo cuando status es failed"},"channel":{"description":"Canal creado. Sólo presente cuando status es completed.","allOf":[{"$ref":"#/components/schemas/PublicChannelResponseDto"}]}},"required":["session_id","status"]},"KnowledgeTreeNodeDto":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"node_type":{"type":"string","enum":["folder","document"]},"parent_id":{"type":"object","nullable":true},"position":{"type":"number"},"path_cache":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"children":{"type":"array","items":{"$ref":"#/components/schemas/KnowledgeTreeNodeDto"}}},"required":["id","title","node_type","position","path_cache","children"]},"KnowledgeTreeResponseDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/KnowledgeTreeNodeDto"}}},"required":["items"]},"CreateFolderDto":{"type":"object","properties":{"title":{"type":"string","description":"Título de la carpeta.","example":"Soporte","maxLength":200},"parent_id":{"type":"string","description":"ObjectId de la carpeta padre. Omitir para crear en la raíz."}},"required":["title"]},"KnowledgeNodeDto":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"node_type":{"type":"string","enum":["folder","document"]},"parent_id":{"type":"object","nullable":true},"position":{"type":"number"},"path_cache":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","title","node_type","position","path_cache"]},"CreateDocumentDto":{"type":"object","properties":{"title":{"type":"string","description":"Título del documento.","example":"Política de devolución","maxLength":200},"parent_id":{"type":"string","description":"ObjectId de la carpeta padre. Omitir para crear en la raíz."},"markdown":{"type":"string","description":"Contenido en Markdown. Se convierte a BlockNote JSON al guardar.","example":"# Política\n\nTexto de la política..."}},"required":["title","markdown"]},"SearchKnowledgeDto":{"type":"object","properties":{"query":{"type":"string","description":"Texto de búsqueda.","example":"¿cómo cancelar suscripción?"},"mode":{"type":"string","description":"Modo de búsqueda: full (full-text), vector (semántica) o hybrid (combinación con re-ranking).","enum":["full","hybrid","vector"],"example":"hybrid"},"top_k":{"type":"number","description":"Cantidad máxima de resultados (1-25).","example":5,"default":5},"node_ids":{"description":"Limita la búsqueda a estos node ids (carpetas o documentos).","type":"array","items":{"type":"string"}}},"required":["query","mode"]},"KnowledgeSearchResultItemDto":{"type":"object","properties":{"node_id":{"type":"string"},"title":{"type":"string"},"snippet":{"type":"string"},"score":{"type":"number"},"source":{"type":"string","enum":["full","vector"]}},"required":["node_id","score","source"]},"SearchKnowledgeResponseDto":{"type":"object","properties":{"mode":{"type":"string","enum":["full","hybrid","vector"]},"results":{"type":"array","items":{"$ref":"#/components/schemas/KnowledgeSearchResultItemDto"}}},"required":["mode","results"]},"AssignKnowledgeDto":{"type":"object","properties":{"assistant_id":{"type":"string","description":"ObjectId del asistente destino."},"node_ids":{"description":"ObjectIds de los nodos a asignar a todos los workers del asistente.","type":"array","items":{"type":"string"}}},"required":["assistant_id","node_ids"]},"AssignKnowledgeResponseDto":{"type":"object","properties":{"workers_updated":{"type":"number"}},"required":["workers_updated"]},"PublicContactResponseDto":{"type":"object","properties":{"_id":{"type":"string","description":"ObjectId del contacto"},"channel_type":{"type":"string","enum":["web","whatsapp","whatsapp_qr","facebook","messenger","instagram","tiktok","telegram","email","phone"],"description":"Canal por el que existe el contacto"},"user_id":{"type":"string","description":"Identificador del contacto dentro de su canal"},"channel_id":{"type":"string","description":"ObjectId del canal concreto"},"external_id":{"type":"string","description":"Identificador en un sistema externo"},"username":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"profile_pic":{"type":"string"},"custom_fields":{"type":"object","description":"Campos personalizados de la company"},"tags":{"description":"Ids de tags","type":"array","items":{"type":"string"}},"is_attended":{"type":"boolean","description":"true cuando un agente humano tomó la conversación"},"last_attended_at":{"type":"string","format":"date-time"},"first_seen_at":{"type":"string","format":"date-time"},"last_seen_at":{"type":"string","format":"date-time"},"last_user_message_at":{"type":"string","format":"date-time"},"last_bot_response_at":{"type":"string","format":"date-time"},"last_agent_response_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["_id","channel_type","user_id","custom_fields","tags","is_attended","first_seen_at","created_at","updated_at"]},"PublicContactListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicContactResponseDto"}},"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["data","total","limit","offset"]},"PublicContactEnvelopeDto":{"type":"object","properties":{"contact":{"$ref":"#/components/schemas/PublicContactResponseDto"}},"required":["contact"]},"PublicContactCreateDto":{"type":"object","properties":{"channel_type":{"type":"string","enum":["web","whatsapp","whatsapp_qr","facebook","messenger","instagram","tiktok","telegram","email","phone"],"description":"Canal por el que existe el contacto. `playground` no se acepta en la API pública."},"user_id":{"type":"string","description":"Identificador del contacto dentro de ese canal. En WhatsApp es el wa_id (el teléfono sin +)."},"channel":{"type":"string","description":"ObjectId del canal concreto. Sin él, el contacto queda asociado sólo al tipo de canal."},"username":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"phone":{"type":"string","description":"Teléfono en formato E.164"},"email":{"type":"string"},"profile_pic":{"type":"string","description":"URL de la foto de perfil"},"custom_fields":{"type":"object","description":"Campos personalizados de la company"}},"required":["channel_type","user_id"]},"PublicContactUpdateDto":{"type":"object","properties":{"username":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"phone":{"type":"string","description":"Teléfono en formato E.164"},"email":{"type":"string"},"profile_pic":{"type":"string","description":"URL de la foto de perfil"},"custom_fields":{"type":"object","description":"Se mergea con los campos existentes; no reemplaza el objeto completo."}}},"PublicCustomerExternalIdResponseDto":{"type":"object","properties":{"provider":{"type":"string","description":"Sistema externo dueño del identificador"},"external_id":{"type":"string","description":"Identificador del cliente en ese sistema"}},"required":["provider","external_id"]},"PublicCustomerResponseDto":{"type":"object","properties":{"_id":{"type":"string","description":"ObjectId del cliente"},"name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"},"identification_number":{"type":"string"},"identification_type":{"type":"string","enum":["rut","dni","passport","other"]},"identification_country":{"type":"string","description":"Código de país ISO 3166-1 alpha-2"},"external_ids":{"type":"array","items":{"$ref":"#/components/schemas/PublicCustomerExternalIdResponseDto"}},"custom_fields":{"type":"object","description":"Campos personalizados de la company"},"tags":{"description":"Ids de tags del CRM","type":"array","items":{"type":"string"}},"accepts_marketing":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["_id","name","external_ids","custom_fields","tags","accepts_marketing","created_at","updated_at"]},"PublicCustomerListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicCustomerResponseDto"}},"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["data","total","limit","offset"]},"PublicCustomerEnvelopeDto":{"type":"object","properties":{"customer":{"$ref":"#/components/schemas/PublicCustomerResponseDto"}},"required":["customer"]},"PublicCustomerExternalIdDto":{"type":"object","properties":{"provider":{"type":"string","description":"Sistema externo dueño del identificador"},"external_id":{"type":"string","description":"Identificador del cliente en ese sistema"}},"required":["provider","external_id"]},"PublicCustomerCreateDto":{"type":"object","properties":{"name":{"type":"string","description":"Nombre del cliente"},"last_name":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"},"identification_number":{"type":"string","description":"Único por company cuando se informa"},"identification_type":{"type":"string","enum":["rut","dni","passport","other"]},"identification_country":{"type":"string","description":"Código de país ISO 3166-1 alpha-2"},"external_ids":{"type":"array","items":{"$ref":"#/components/schemas/PublicCustomerExternalIdDto"}},"custom_fields":{"type":"object","description":"Campos personalizados de la company"},"tags":{"description":"Ids de tags del CRM","type":"array","items":{"type":"string"}},"accepts_marketing":{"type":"boolean","default":false}},"required":["name"]},"PublicCustomerUpdateDto":{"type":"object","properties":{"name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"},"identification_number":{"type":"string"},"identification_type":{"type":"string","enum":["rut","dni","passport","other"]},"identification_country":{"type":"string"},"custom_fields":{"type":"object"},"tags":{"description":"Reemplaza la lista completa de tags","type":"array","items":{"type":"string"}},"accepts_marketing":{"type":"boolean"}}},"PublicTicketStageDto":{"type":"object","properties":{"stage_id":{"type":"string","description":"Etapa de destino dentro del pipeline"},"prioridad":{"type":"string","description":"Prioridad reportada al mover la etapa"},"contexto":{"type":"string","description":"Contexto del movimiento"},"problema":{"type":"string","description":"Problema detectado"},"recomendaciones":{"type":"string","description":"Recomendaciones para el operador"}},"required":["stage_id"]},"PublicTicketAssigneeDto":{"type":"object","properties":{"id":{"type":"string","description":"ObjectId del usuario"},"full_name":{"type":"string"},"email":{"type":"string"}},"required":["id"]},"PublicTicketTagDto":{"type":"object","properties":{"id":{"type":"string","description":"ObjectId del tag"},"name":{"type":"string"},"color":{"type":"string","description":"Color hex, ej. #1890ff"}},"required":["id","name"]},"PublicConversationSummaryDto":{"type":"object","properties":{"motivo":{"type":"string"},"estado":{"type":"string"},"proximos_pasos":{"type":"string"},"is_final":{"type":"boolean"}}},"PublicTicketLastMessageDto":{"type":"object","properties":{"id":{"type":"string"},"content":{"type":"string"},"role":{"type":"string"},"direction":{"type":"string","description":"inbound | outbound"},"created_at":{"type":"string","format":"date-time"}},"required":["id"]},"PublicTicketResponseDto":{"type":"object","properties":{"_id":{"type":"string","description":"ObjectId del ticket"},"chat_user":{"type":"string","description":"ObjectId del chat user (contacto)"},"chat_user_name":{"type":"string"},"chat_user_avatar":{"type":"string"},"chat_user_channel":{"type":"string","description":"Canal de origen (whatsapp, instagram…)"},"chat_user_channel_id":{"type":"string"},"stage":{"description":"Etapa actual del pipeline. Ausente si el ticket no tiene una.","allOf":[{"$ref":"#/components/schemas/PublicTicketStageDto"}]},"is_closed":{"type":"boolean"},"resolution":{"type":"string","enum":["won","lost"]},"priority":{"type":"string","enum":["low","medium","high","urgent"]},"category":{"type":"string"},"assigned_to":{"$ref":"#/components/schemas/PublicTicketAssigneeDto"},"tags":{"type":"array","items":{"$ref":"#/components/schemas/PublicTicketTagDto"}},"custom_fields":{"type":"object"},"amount":{"type":"number"},"amount_currency":{"type":"string","description":"Moneda ISO 4217"},"amount_status":{"type":"string","enum":["estimated","confirmed"]},"conversation_summary":{"$ref":"#/components/schemas/PublicConversationSummaryDto"},"ai_feedback_status":{"type":"string","description":"Feedback de la IA: resolved | unresolved"},"appointment_ids":{"description":"Citas de scheduling vinculadas al ticket","type":"array","items":{"type":"string"}},"last_message":{"description":"Último mensaje del contacto. Sólo presente en el listado.","allOf":[{"$ref":"#/components/schemas/PublicTicketLastMessageDto"}]},"closed_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["_id","chat_user","is_closed","priority","tags","custom_fields","created_at","updated_at"]},"PublicTicketListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicTicketResponseDto"}},"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["data","total","limit","offset"]},"PublicTicketEnvelopeDto":{"type":"object","properties":{"ticket":{"$ref":"#/components/schemas/PublicTicketResponseDto"}},"required":["ticket"]},"PublicTicketCreateDto":{"type":"object","properties":{"chat_user":{"type":"string","description":"Id del chat user (contacto) dueño del ticket"},"chat_user_name":{"type":"string"},"chat_user_avatar":{"type":"string"},"chat_user_channel":{"type":"string","description":"Canal de origen (whatsapp, instagram…)"},"chat_user_channel_id":{"type":"string"},"priority":{"type":"string","enum":["low","medium","high","urgent"],"default":"medium"},"category":{"type":"string"},"assigned_to":{"type":"string","description":"Id del usuario asignado"},"custom_fields":{"type":"object"},"amount":{"type":"number","description":"Valor monetario de la oportunidad"},"amount_currency":{"type":"string","description":"Moneda ISO 4217"},"amount_status":{"type":"string","enum":["estimated","confirmed"]},"stage":{"type":"string","description":"Etapa del pipeline. Si se omite, el ticket queda sin etapa asignada."}},"required":["chat_user"]},"PublicTicketUpdateDto":{"type":"object","properties":{"resolution":{"type":"string","enum":["won","lost"]},"is_closed":{"type":"boolean","description":"Cierra o reabre el ticket"},"priority":{"type":"string","enum":["low","medium","high","urgent"]},"category":{"type":"string"},"assigned_to":{"type":"string"},"custom_fields":{"type":"object"},"amount":{"type":"number"},"amount_currency":{"type":"string"},"amount_status":{"type":"string","enum":["estimated","confirmed"]},"tag_ids":{"description":"Reemplaza la lista completa de tags","type":"array","items":{"type":"string"}},"add_tag_ids":{"description":"Agrega tags sin tocar las existentes","type":"array","items":{"type":"string"}},"remove_tag_ids":{"description":"Quita tags sin tocar las demás","type":"array","items":{"type":"string"}},"conversation_summary":{"$ref":"#/components/schemas/PublicConversationSummaryDto"}}},"PublicTicketUpdateResponseDto":{"type":"object","properties":{"ticket":{"$ref":"#/components/schemas/PublicTicketResponseDto"},"just_closed":{"type":"boolean","description":"true sólo en la request que pasó el ticket de abierto a cerrado. Útil para disparar efectos una única vez."},"action":{"type":"string","description":"closed | updated"}},"required":["ticket","just_closed","action"]},"PublicTicketStageChangeResponseDto":{"type":"object","properties":{"ticket":{"$ref":"#/components/schemas/PublicTicketResponseDto"},"previous_stage_id":{"type":"string","description":"Etapa previa al movimiento"},"current_stage_id":{"type":"string","description":"Etapa resultante"},"stage_changed":{"type":"boolean","description":"false si el ticket ya estaba en esa etapa; la llamada es idempotente"},"is_human_stage":{"type":"boolean","description":"La etapa de destino espera intervención de una persona"},"stage_type":{"type":"string"},"next_stage_to_set":{"type":"string","description":"Presente cuando las reglas del pipeline piden avanzar de nuevo"}},"required":["ticket","current_stage_id","stage_changed"]},"PublicTaskResponseDto":{"type":"object","properties":{"_id":{"type":"string","description":"ObjectId de la tarea"},"title":{"type":"string"},"description":{"type":"string"},"status":{"type":"string","description":"Estado libre. Los valores del portal son pending, in_progress, completed y cancelled."},"priority":{"type":"string","enum":["low","medium","high","urgent"]},"assigned_to":{"type":"string","description":"ObjectId del usuario asignado"},"due_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["_id","title","status","priority","created_at","updated_at"]},"PublicTaskListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicTaskResponseDto"}},"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["data","total","limit","offset"]},"PublicTaskEnvelopeDto":{"type":"object","properties":{"task":{"$ref":"#/components/schemas/PublicTaskResponseDto"}},"required":["task"]},"PublicTaskCreateDto":{"type":"object","properties":{"title":{"type":"string","description":"Título de la tarea"},"assigned_to":{"type":"string","description":"Id del usuario asignado"},"status":{"type":"string","description":"Estado libre. Los valores del portal son pending, in_progress, completed y cancelled.","default":"pending"},"priority":{"type":"string","enum":["low","medium","high","urgent"],"default":"medium"},"due_at":{"type":"string","description":"Vencimiento en ISO 8601"},"description":{"type":"string"}},"required":["title"]},"PublicTaskUpdateDto":{"type":"object","properties":{"title":{"type":"string"},"assigned_to":{"type":"string"},"status":{"type":"string"},"priority":{"type":"string","enum":["low","medium","high","urgent"]},"due_at":{"type":"string","description":"Vencimiento en ISO 8601"},"description":{"type":"string"}}},"PublicNoteResponseDto":{"type":"object","properties":{"_id":{"type":"string","description":"ObjectId de la nota"},"content":{"type":"string"},"type":{"type":"string","enum":["note","call","email","meeting"]},"chat_user":{"type":"string","description":"ObjectId del chat user (contacto)"},"ticket_id":{"type":"string","description":"ObjectId del ticket asociado"},"created_by":{"type":"string","description":"ObjectId del usuario que creó la nota"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["_id","content","type","created_by","created_at","updated_at"]},"PublicNoteListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicNoteResponseDto"}},"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["data","total","limit","offset"]},"PublicNoteEnvelopeDto":{"type":"object","properties":{"note":{"$ref":"#/components/schemas/PublicNoteResponseDto"}},"required":["note"]},"PublicNoteCreateDto":{"type":"object","properties":{"content":{"type":"string","description":"Contenido de la nota"},"chat_user":{"type":"string","description":"Chat user (contacto) al que refiere"},"ticket_id":{"type":"string","description":"Ticket al que se adjunta la nota"},"type":{"type":"string","enum":["note","call","email","meeting"],"default":"note"}},"required":["content"]},"PublicNoteUpdateDto":{"type":"object","properties":{"content":{"type":"string"},"type":{"type":"string","enum":["note","call","email","meeting"]}}},"PublicProductVariantDto":{"type":"object","properties":{"external_id":{"type":"string"},"name":{"type":"string"},"price":{"type":"number"},"is_available":{"type":"boolean"}},"required":["external_id","name","price","is_available"]},"PublicProductResponseDto":{"type":"object","properties":{"_id":{"type":"string","description":"ObjectId del producto"},"name":{"type":"string"},"slug":{"type":"string"},"description":{"type":"string"},"sku":{"type":"string"},"price":{"type":"number"},"base_price":{"type":"number","description":"Precio base antes de variantes"},"currency":{"type":"string"},"stock":{"type":"number"},"stock_managed":{"type":"boolean","description":"true cuando el stock se descuenta al vender"},"type":{"type":"string","description":"Origen del producto"},"category_id":{"type":"string","description":"ObjectId de la categoría"},"external_id":{"type":"string","description":"Identificador en el sistema externo"},"variants":{"type":"array","items":{"$ref":"#/components/schemas/PublicProductVariantDto"}},"image_urls":{"type":"array","items":{"type":"string"}},"landing_url":{"type":"string"},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["_id","name","price","currency","stock","stock_managed","type","variants","image_urls","is_active","created_at","updated_at"]},"PublicProductListResponseDto":{"type":"object","properties":{"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"},"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicProductResponseDto"}}},"required":["total","limit","offset","data"]},"PublicProductEnvelopeDto":{"type":"object","properties":{"product":{"$ref":"#/components/schemas/PublicProductResponseDto"}},"required":["product"]},"PublicCartItemDto":{"type":"object","properties":{"product_id":{"type":"string","description":"ObjectId del producto en Keebai"},"product_name":{"type":"string"},"sku":{"type":"string"},"quantity":{"type":"number"},"unit_price":{"type":"number"},"subtotal":{"type":"number"},"modifiers_summary":{"type":"string"},"comment":{"type":"string"}},"required":["product_name","quantity","unit_price","subtotal"]},"PublicCartResponseDto":{"type":"object","properties":{"_id":{"type":"string","description":"ObjectId del carrito"},"source":{"type":"string","description":"Origen del carrito"},"integration_id":{"type":"string","description":"ObjectId de la integración de origen"},"external_id":{"type":"string","description":"Identificador en el sistema externo"},"customer_id":{"type":"string","description":"ObjectId del contacto"},"customer_name":{"type":"string"},"customer_email":{"type":"string"},"customer_phone":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/PublicCartItemDto"}},"total":{"type":"number"},"currency":{"type":"string"},"recovery_status":{"type":"string","description":"pending | contacted | recovered | discarded"},"recovery_url":{"type":"string","description":"URL para que el cliente retome el carrito"},"abandoned_at":{"type":"string","format":"date-time"},"completed_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["_id","source","items","total","currency","recovery_status","created_at","updated_at"]},"PublicCartListResponseDto":{"type":"object","properties":{"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"},"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicCartResponseDto"}}},"required":["total","limit","offset","data"]},"PublicCartEnvelopeDto":{"type":"object","properties":{"cart":{"$ref":"#/components/schemas/PublicCartResponseDto"}},"required":["cart"]},"PublicSaleCustomerDto":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"},"chat_user_id":{"type":"string","description":"ObjectId del contacto"},"customer_id":{"type":"string","description":"ObjectId del cliente de CRM"}},"required":["name"]},"PublicSaleItemDto":{"type":"object","properties":{"kind":{"type":"string","description":"product | service | custom"},"name":{"type":"string"},"quantity":{"type":"number"},"unit_price":{"type":"number"},"subtotal":{"type":"number"}},"required":["kind"]},"PublicSaleAmountsDto":{"type":"object","properties":{"service_subtotal":{"type":"number"},"products_subtotal":{"type":"number"},"custom_subtotal":{"type":"number"},"net_subtotal":{"type":"number"},"tax_amount":{"type":"number"},"tip":{"type":"number"},"total":{"type":"number"}},"required":["service_subtotal","products_subtotal","custom_subtotal","net_subtotal","tax_amount","tip","total"]},"PublicSaleResponseDto":{"type":"object","properties":{"_id":{"type":"string","description":"ObjectId de la venta"},"sale_number":{"type":"number","description":"Correlativo legible de la venta"},"status":{"type":"string","enum":["completed","cancelled","refunded"]},"payment_status":{"type":"string","enum":["pending","paid","partially_paid","refunded"]},"currency":{"type":"string"},"customer":{"$ref":"#/components/schemas/PublicSaleCustomerDto"},"items":{"type":"array","items":{"$ref":"#/components/schemas/PublicSaleItemDto"}},"amounts":{"$ref":"#/components/schemas/PublicSaleAmountsDto"},"payment_method":{"type":"string"},"branch_id":{"type":"string","description":"Sucursal asociada"},"professional_id":{"type":"string","description":"Profesional asociado"},"notes":{"type":"string"},"paid_at":{"type":"string","format":"date-time"},"cancelled_at":{"type":"string","format":"date-time"},"refunded_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["_id","sale_number","status","payment_status","currency","customer","items","amounts","created_at","updated_at"]},"PublicSaleListResponseDto":{"type":"object","properties":{"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"},"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicSaleResponseDto"}}},"required":["total","limit","offset","data"]},"PublicSaleEnvelopeDto":{"type":"object","properties":{"sale":{"$ref":"#/components/schemas/PublicSaleResponseDto"}},"required":["sale"]},"PublicPointsRulesDto":{"type":"object","properties":{"points_per_currency_unit":{"type":"number","description":"Cuántos puntos otorga cada unidad de moneda gastada","example":1},"expiration_days":{"type":"number","description":"Días desde la inscripción tras los cuales el saldo se lee 0. Cero significa sin vencimiento","example":0}},"required":["points_per_currency_unit","expiration_days"]},"PublicStampsRulesDto":{"type":"object","properties":{"target":{"type":"number","description":"Sellos necesarios para el premio","example":10},"reward":{"type":"string","description":"Descripción libre del premio. No es una entidad, es texto","example":"Un café gratis"},"reset_on_redeem":{"type":"boolean","description":"Si los sellos vuelven a cero al canjear"}},"required":["target","reward","reset_on_redeem"]},"PublicTierLevelDto":{"type":"object","properties":{"key":{"type":"string","example":"gold"},"name":{"type":"string","example":"Oro"},"threshold":{"type":"number","description":"Puntos mínimos para alcanzar el nivel","example":5000},"benefits":{"example":["Envío gratis","Acceso anticipado"],"type":"array","items":{"type":"string"}}},"required":["key","name","threshold","benefits"]},"PublicTiersRulesDto":{"type":"object","properties":{"levels":{"type":"array","items":{"$ref":"#/components/schemas/PublicTierLevelDto"}}},"required":["levels"]},"PublicProgramRulesDto":{"type":"object","properties":{"points":{"$ref":"#/components/schemas/PublicPointsRulesDto"},"stamps":{"$ref":"#/components/schemas/PublicStampsRulesDto"},"tiers":{"$ref":"#/components/schemas/PublicTiersRulesDto"}}},"PublicProgramDto":{"type":"object","properties":{"_id":{"type":"string"},"name":{"type":"string","example":"Club Cafetería"},"type":{"type":"string","enum":["points","stamps","tiers"]},"status":{"type":"string","enum":["draft","active","archived"]},"description":{"type":"string","example":"Programa de sellos de la cafetería"},"rules":{"description":"Solo viene poblada la variante que corresponde al type","allOf":[{"$ref":"#/components/schemas/PublicProgramRulesDto"}]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["_id","name","type","status","description","rules","created_at","updated_at"]},"PublicProgramListResponseDto":{"type":"object","properties":{"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"},"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicProgramDto"}}},"required":["total","limit","offset","data"]},"PublicProgramEnvelopeDto":{"type":"object","properties":{"program":{"$ref":"#/components/schemas/PublicProgramDto"}},"required":["program"]},"PublicTemplateListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicTemplateDto"}},"total":{"type":"number"}},"required":["data","total"]},"PublicTemplateEnvelopeDto":{"type":"object","properties":{"template":{"$ref":"#/components/schemas/PublicTemplateDto"}},"required":["template"]},"PublicMembershipCustomerViewDto":{"type":"object","properties":{"id":{"type":"string","example":"crm-8842"},"name":{"type":"string","example":"Camila Rojas"},"phone":{"type":"string","example":"+56912345678"},"email":{"type":"string","example":"camila@ejemplo.cl"}},"required":["id"]},"PublicMembershipDto":{"type":"object","properties":{"_id":{"type":"string"},"program_id":{"type":"string"},"customer":{"$ref":"#/components/schemas/PublicMembershipCustomerViewDto"},"serial_number":{"type":"string","description":"Identificador del pase en Apple y Google. Es lo que codifica el código de barras por defecto"},"balance_points":{"type":"number","description":"Saldo de puntos. Si el programa vence puntos y ya pasó el plazo, se lee 0 sin que el ledger cambie","example":1240},"stamps_count":{"type":"number","example":7},"tier":{"type":"string","description":"Clave del nivel alcanzado. Vacío si el programa no es de tiers","example":"gold"},"status":{"type":"string","enum":["active","suspended","revoked"]},"enrolled_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["_id","program_id","serial_number","balance_points","stamps_count","tier","status","enrolled_at","created_at","updated_at"]},"PublicMembershipListResponseDto":{"type":"object","properties":{"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"},"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicMembershipDto"}}},"required":["total","limit","offset","data"]},"PublicMembershipEnvelopeDto":{"type":"object","properties":{"membership":{"$ref":"#/components/schemas/PublicMembershipDto"}},"required":["membership"]},"PublicMembershipCustomerDto":{"type":"object","properties":{"id":{"type":"string","description":"Identificador del cliente en tu sistema. Lo elegís vos y es la clave con la que después encontrás la membresía","example":"crm-8842"},"name":{"type":"string","example":"Camila Rojas"},"phone":{"type":"string","example":"+56912345678"},"email":{"type":"string","example":"camila@ejemplo.cl"}},"required":["id"]},"PublicMembershipEnrollDto":{"type":"object","properties":{"program_id":{"type":"string","description":"ObjectId del programa al que se inscribe"},"customer":{"description":"Datos del cliente. Se copian tal cual al inscribir y no se vuelven a resolver contra el CRM","allOf":[{"$ref":"#/components/schemas/PublicMembershipCustomerDto"}]}},"required":["program_id","customer"]},"PublicLedgerEntryDto":{"type":"object","properties":{"_id":{"type":"string"},"membership_id":{"type":"string"},"program_id":{"type":"string"},"kind":{"type":"string","enum":["earn","redeem","adjust"]},"metric":{"type":"string","enum":["points","stamps"],"description":"Lo decide el tipo del programa, no el request"},"amount":{"type":"number","description":"Movimiento con signo: negativo en un canje","example":-50},"balance_after":{"type":"number","description":"Saldo resultante después del movimiento","example":1190},"source":{"type":"string","example":"pos-sucursal-centro"},"ref":{"type":"string","example":"boleta-99120"},"note":{"type":"string"},"created_at":{"type":"string"}},"required":["_id","membership_id","program_id","kind","metric","amount","balance_after","source","ref","note","created_at"]},"PublicLedgerListResponseDto":{"type":"object","properties":{"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"},"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicLedgerEntryDto"}}},"required":["total","limit","offset","data"]},"PublicLedgerRecordDto":{"type":"object","properties":{"kind":{"type":"string","enum":["earn","redeem","adjust"],"description":"earn suma, redeem resta, adjust respeta el signo de amount para correcciones"},"amount":{"type":"number","description":"Magnitud del movimiento. En earn y redeem se toma el valor absoluto; en adjust se respeta el signo","example":120},"source":{"type":"string","description":"De dónde vino el movimiento. Por defecto manual","example":"pos-sucursal-centro"},"ref":{"type":"string","description":"Referencia externa, por ejemplo el número de boleta","example":"boleta-99120"},"note":{"type":"string","example":"Compra de 12.000 en tienda"}},"required":["kind","amount"]},"PublicLedgerEntryEnvelopeDto":{"type":"object","properties":{"entry":{"$ref":"#/components/schemas/PublicLedgerEntryDto"}},"required":["entry"]},"PublicGooglePassDto":{"type":"object","properties":{"save_url":{"type":"string","description":"Link de Google Wallet para agregar el pase. Se le manda al cliente tal cual"},"provider_ref":{"type":"string","description":"Id del objeto en Google Wallet"}},"required":["save_url","provider_ref"]},"PublicApplePassLinkDto":{"type":"object","properties":{"download_url":{"type":"string","description":"Link público de descarga del .pkpass. Sirve para QR, WhatsApp o copiar y pegar"}},"required":["download_url"]},"PublicPassNotifyDto":{"type":"object","properties":{"header":{"type":"string","description":"Título del mensaje que ve el cliente en la wallet","example":"Te quedan 3 sellos"},"body":{"type":"string","description":"Cuerpo del mensaje","example":"Junta 3 sellos más y tu próximo café va por la casa."},"link_url":{"type":"string","description":"URL https a la que lleva el botón del mensaje","example":"https://tutienda.cl/promos"},"link_label":{"type":"string","example":"Ver promos"}},"required":["header","body"]},"PublicPassNotifyResultDto":{"type":"object","properties":{"notified":{"type":"number","description":"Dispositivos a los que llegó el mensaje","example":2},"skipped":{"type":"number","description":"Dispositivos omitidos por no tener un pase registrado","example":0}},"required":["notified","skipped"]},"PublicPassNotificationDto":{"type":"object","properties":{"_id":{"type":"string"},"header":{"type":"string"},"body":{"type":"string"},"link_url":{"type":"string"},"link_label":{"type":"string"},"channels":{"example":["google","apple"],"type":"array","items":{"type":"string"}},"delivered":{"type":"number","example":2},"created_at":{"type":"string"}},"required":["_id","header","body","link_url","link_label","channels","delivered","created_at"]},"PublicPassNotificationListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicPassNotificationDto"}},"total":{"type":"number"}},"required":["data","total"]},"PublicAssistantDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"avatar_url":{"type":"string"},"model":{"type":"string"},"voice_response_enabled":{"type":"boolean","description":"Indica si la respuesta de voz está habilitada."},"created_at":{"type":"string"}},"required":["id","name","model","voice_response_enabled"]},"PaginatedAssistantsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PublicAssistantDto"}},"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"}},"required":["items","page","limit","total"]},"PublicAssistantEnvelopeDto":{"type":"object","properties":{"assistant":{"$ref":"#/components/schemas/PublicAssistantDto"}},"required":["assistant"]},"PublicAssistantCreateDto":{"type":"object","properties":{"name":{"type":"string","maxLength":150,"example":"Asistente de ventas"},"description":{"type":"string","maxLength":500},"avatar_url":{"type":"string","description":"URL https de la imagen del avatar.","example":"https://cdn.example.com/avatars/ventas.png"},"avatar_emoji":{"type":"string","maxLength":16,"example":"🤖"},"model":{"type":"string","description":"Identificador del modelo. Se valida contra los modelos soportados; uno desconocido devuelve 400 INVALID_MODEL.","example":"gemini-2.5-flash"},"knowledge_node_ids":{"maxItems":200,"description":"ObjectIds de nodos de la base de conocimiento a asignar.","type":"array","items":{"type":"string"}}},"required":["name"]},"PublicAssistantUpdateDto":{"type":"object","properties":{"name":{"type":"string","maxLength":150},"description":{"type":"string","maxLength":500},"avatar_url":{"type":"string","description":"URL https de la imagen del avatar."},"avatar_emoji":{"type":"string","maxLength":16,"example":"🤖"},"model":{"type":"string","description":"Identificador del modelo. Se valida solo si cambia respecto del actual."},"knowledge_node_ids":{"maxItems":200,"type":"array","items":{"type":"string"}},"is_active":{"type":"boolean"}}},"PublicAttachedBlockDto":{"type":"object","properties":{"_id":{"type":"string"},"type":{"type":"string","enum":["personification","objective","response_format","steps","cases_possible","do_not","product_info","store_info","reservation_info","tables_info","tags","response_policy"]},"family":{"type":"string","enum":["identity","instructions","information"],"description":"Se deriva del tipo y determina en que seccion del prompt entra el bloque. Es de solo lectura."},"name":{"type":"string"},"current_version_id":{"type":"string","nullable":true,"description":"Version vigente del bloque. Su contenido se lee en GET /v1/blocks/{id}/content."},"is_archived":{"type":"boolean"},"content_writable":{"type":"boolean","description":"Si el contenido de este bloque se puede editar por API. Los tipos de catalogo son de solo lectura porque su escritura depende de una sincronizacion de funciones que vive en el portal."},"created_at":{"type":"string"},"updated_at":{"type":"string"},"order":{"type":"number","description":"Posicion del bloque en el prompt del asistente."},"pinned_version_id":{"type":"string","nullable":true,"description":"Version fijada por el asistente. Si es null, el asistente usa la version vigente del bloque."}},"required":["_id","type","family","name","current_version_id","is_archived","content_writable","created_at","updated_at","order","pinned_version_id"]},"PublicAttachedBlockListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicAttachedBlockDto"}},"total":{"type":"number"}},"required":["data","total"]},"PublicBlockRefDto":{"type":"object","properties":{"block_id":{"type":"string","description":"ObjectId del bloque."},"pinned_version_id":{"type":"string","description":"ObjectId de una version concreta. Sin este campo el asistente sigue la version vigente del bloque."},"order":{"type":"number","default":0,"minimum":0,"description":"Posicion del bloque en el prompt."}},"required":["block_id"]},"PublicAssistantBlocksSetDto":{"type":"object","properties":{"blocks":{"maxItems":50,"description":"Lista completa de bloques del asistente. Los que no aparezcan quedan desadjuntados.","type":"array","items":{"$ref":"#/components/schemas/PublicBlockRefDto"}}},"required":["blocks"]},"PublicBlockDto":{"type":"object","properties":{"_id":{"type":"string"},"type":{"type":"string","enum":["personification","objective","response_format","steps","cases_possible","do_not","product_info","store_info","reservation_info","tables_info","tags","response_policy"]},"family":{"type":"string","enum":["identity","instructions","information"],"description":"Se deriva del tipo y determina en que seccion del prompt entra el bloque. Es de solo lectura."},"name":{"type":"string"},"current_version_id":{"type":"string","nullable":true,"description":"Version vigente del bloque. Su contenido se lee en GET /v1/blocks/{id}/content."},"is_archived":{"type":"boolean"},"content_writable":{"type":"boolean","description":"Si el contenido de este bloque se puede editar por API. Los tipos de catalogo son de solo lectura porque su escritura depende de una sincronizacion de funciones que vive en el portal."},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["_id","type","family","name","current_version_id","is_archived","content_writable","created_at","updated_at"]},"PublicBlockListResponseDto":{"type":"object","properties":{"limit":{"type":"number"},"offset":{"type":"number"},"has_more":{"type":"boolean","description":"Si hay al menos una pagina mas despues de esta."},"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicBlockDto"}}},"required":["limit","offset","has_more","data"]},"PublicBlockCreateDto":{"type":"object","properties":{"name":{"type":"string","maxLength":150,"description":"Nombre con el que el bloque aparece en el portal.","example":"Tono cercano"},"content":{"type":"string","maxLength":100000,"description":"Contenido inicial en texto. Se reconocen listas con '-' y con '1.', y encabezados con '#'. Sin este campo el bloque nace vacio."}},"required":["name"]},"PublicBlockEnvelopeDto":{"type":"object","properties":{"block":{"$ref":"#/components/schemas/PublicBlockDto"}},"required":["block"]},"PublicBlockUpdateDto":{"type":"object","properties":{"name":{"type":"string","maxLength":150},"is_archived":{"type":"boolean","description":"Archiva o desarchiva el bloque. Archivar no lo borra ni lo saca de los asistentes que lo tienen adjunto."}}},"PublicBlockContentDto":{"type":"object","properties":{"content":{"type":"string","maxLength":100000,"description":"Contenido completo del bloque en texto. Reemplaza al anterior creando una version nueva.","example":"Sos el asistente de una barberia.\n- Tuteas al cliente."}},"required":["content"]},"PublicBlockContentEnvelopeDto":{"type":"object","properties":{"content":{"$ref":"#/components/schemas/PublicBlockContentDto"}},"required":["content"]},"PublicBlockVersionDto":{"type":"object","properties":{"_id":{"type":"string"},"block_id":{"type":"string"},"version_number":{"type":"number"},"edit_mode":{"type":"string","enum":["assisted","free"]},"is_current":{"type":"boolean","description":"Si esta es la version que el bloque tiene como vigente."},"created_at":{"type":"string"}},"required":["_id","block_id","version_number","edit_mode","is_current","created_at"]},"PublicBlockVersionListResponseDto":{"type":"object","properties":{"limit":{"type":"number"},"offset":{"type":"number"},"has_more":{"type":"boolean","description":"Si hay al menos una pagina mas despues de esta."},"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicBlockVersionDto"}}},"required":["limit","offset","has_more","data"]},"PublicFunctionParamResponseDto":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"type":{"type":"string","enum":["string","number","boolean","array","object"]},"required":{"type":"boolean"}},"required":["name","type","required"]},"PublicWebhookContextResponseDto":{"type":"object","properties":{"url":{"type":"string"},"method":{"type":"string","enum":["GET","POST","PUT","PATCH","DELETE"]},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Headers configurados. Las claves se muestran y los valores vuelven siempre como '***'.","example":{"Authorization":"***"}},"params":{"type":"object","additionalProperties":{"type":"string"},"description":"Query string configurada, con los valores enmascarados igual que headers."},"body":{"type":"object","additionalProperties":true,"description":"Body de la request. No se enmascara: es la plantilla que rellena el modelo."},"timeout":{"type":"number"},"response_path":{"type":"string"}},"required":["url","method","headers","params","timeout"]},"PublicFunctionUsageDto":{"type":"object","properties":{"block_id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["personification","objective","response_format","steps","cases_possible","do_not","product_info","store_info","reservation_info","tables_info","tags","response_policy"]}},"required":["block_id","name","type"]},"PublicFunctionDto":{"type":"object","properties":{"_id":{"type":"string"},"name":{"type":"string"},"display_name":{"type":"string"},"description":{"type":"string"},"type":{"type":"string","example":"webhook"},"tool_params":{"type":"array","items":{"$ref":"#/components/schemas/PublicFunctionParamResponseDto"}},"context":{"$ref":"#/components/schemas/PublicWebhookContextResponseDto"},"tags":{"type":"array","items":{"type":"string"}},"is_active":{"type":"boolean"},"used_by_blocks":{"description":"Bloques que referencian esta funcion. Mientras la lista no este vacia, borrarla devuelve 409.","type":"array","items":{"$ref":"#/components/schemas/PublicFunctionUsageDto"}},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["_id","name","display_name","description","type","tool_params","context","tags","is_active","used_by_blocks","created_at","updated_at"]},"PublicFunctionListResponseDto":{"type":"object","properties":{"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"},"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicFunctionDto"}}},"required":["total","limit","offset","data"]},"PublicFunctionEnvelopeDto":{"type":"object","properties":{"function":{"$ref":"#/components/schemas/PublicFunctionDto"}},"required":["function"]},"PublicWebhookContextDto":{"type":"object","properties":{"url":{"type":"string","description":"URL https publica. Se rechazan loopback, rangos privados, hosts internos del cluster y placeholders en el host.","example":"https://erp.example.com/stock"},"method":{"type":"string","enum":["GET","POST","PUT","PATCH","DELETE"],"default":"POST"},"headers":{"type":"object","description":"Headers de la request. Los valores son de solo escritura: en lectura vuelven enmascarados. Omitir el campo en un update preserva los guardados; mandarlo los reemplaza completos.","example":{"Authorization":"Bearer sk_live_xxx"}},"params":{"type":"object","description":"Query string de la request. Mismo trato que headers: enmascarado en lectura."},"body":{"type":"object","description":"Body de la request. Acepta placeholders '{{arg}}' que se reemplazan con los argumentos del modelo.","example":{"sku":"{{sku}}"}},"timeout":{"type":"number","default":30,"minimum":1,"maximum":30,"description":"Segundos de espera antes de abortar la llamada."},"response_path":{"type":"string","maxLength":200,"description":"Ruta dentro del JSON de respuesta a extraer, por ejemplo 'data.items'. Sin esto se entrega la respuesta completa."}},"required":["url"]},"PublicFunctionParamDto":{"type":"object","properties":{"name":{"type":"string","maxLength":100,"description":"Nombre del argumento tal como lo va a pasar el modelo."},"description":{"type":"string","maxLength":500,"description":"Que significa el argumento. El modelo lee esto para decidir que mandar."},"type":{"type":"string","enum":["string","number","boolean","array","object"],"default":"string"},"required":{"type":"boolean","default":true}},"required":["name"]},"PublicFunctionCreateDto":{"type":"object","properties":{"name":{"type":"string","maxLength":100,"description":"Nombre tecnico, unico por company. Es el nombre con el que el modelo invoca la funcion.","example":"consultar_stock"},"display_name":{"type":"string","maxLength":200,"example":"Consultar stock"},"description":{"type":"string","maxLength":1000,"description":"Para que sirve la funcion. Es lo que lee el modelo para decidir cuando llamarla.","example":"Devuelve el stock disponible de un SKU en el ERP."},"context":{"$ref":"#/components/schemas/PublicWebhookContextDto"},"tool_params":{"maxItems":30,"type":"array","items":{"$ref":"#/components/schemas/PublicFunctionParamDto"}},"tags":{"maxItems":20,"type":"array","items":{"type":"string"}},"is_active":{"type":"boolean","default":true}},"required":["name","display_name","description","context"]},"PublicFunctionUpdateDto":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"display_name":{"type":"string","maxLength":200},"description":{"type":"string","maxLength":1000},"context":{"$ref":"#/components/schemas/PublicWebhookContextDto"},"tool_params":{"maxItems":30,"type":"array","items":{"$ref":"#/components/schemas/PublicFunctionParamDto"}},"tags":{"maxItems":20,"type":"array","items":{"type":"string"}},"is_active":{"type":"boolean"}}},"PublicBranchResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"ObjectId de la sucursal"},"name":{"type":"string"},"display_name":{"type":"string"},"description":{"type":"string"},"address":{"type":"object"},"contact":{"type":"object"},"timezone":{"type":"string","description":"IANA, ej. America/Santiago"},"status":{"type":"string"}},"required":["id","name"]},"PublicBranchListResponseDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PublicBranchResponseDto"}},"total":{"type":"number"},"skip":{"type":"number"},"limit":{"type":"number"}},"required":["items","total","skip","limit"]},"PublicServiceResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"ObjectId del servicio"},"name":{"type":"string"},"description":{"type":"string"},"duration_minutes":{"type":"number","description":"Duración en minutos"},"slot_interval_minutes":{"type":"number","description":"Granularidad de los slots, en minutos"},"price":{"type":"object","description":"{ amount, currency }"},"branches":{"description":"Sucursales donde se presta","type":"array","items":{"type":"string"}},"category":{"type":"string"},"color":{"type":"string"},"status":{"type":"string","description":"active | inactive"}},"required":["id","name","duration_minutes","status"]},"PublicProfessionalResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"ObjectId del profesional"},"name":{"type":"string"},"last_name":{"type":"string"},"specialties":{"type":"array","items":{"type":"string"}},"cargo":{"type":"string"},"avatar":{"type":"string"},"branches":{"description":"Sucursales donde atiende","type":"array","items":{"type":"string"}},"status":{"type":"string","description":"active | inactive | on_leave"}},"required":["id","name"]},"PublicAvailabilitySlotDto":{"type":"object","properties":{"start":{"type":"string","description":"Hora de inicio (HH:mm) o ISO 8601"},"end":{"type":"string","description":"Hora de fin (HH:mm) o ISO 8601"},"professional_id":{"type":"string","description":"Profesional que cubre el slot"},"branch_id":{"type":"string"}},"required":["start"]},"PublicAvailabilityResponseDto":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/PublicAvailabilitySlotDto"}}},"required":["results"]},"PublicAvailabilityDayDto":{"type":"object","properties":{"date":{"type":"string","description":"YYYY-MM-DD"},"results":{"type":"array","items":{"$ref":"#/components/schemas/PublicAvailabilitySlotDto"}}},"required":["date","results"]},"PublicAvailabilityRangeResponseDto":{"type":"object","properties":{"from":{"type":"string","description":"YYYY-MM-DD"},"to":{"type":"string","description":"YYYY-MM-DD"},"days":{"type":"array","items":{"$ref":"#/components/schemas/PublicAvailabilityDayDto"}}},"required":["from","to","days"]},"PublicAppointmentRefDto":{"type":"object","properties":{"id":{"type":"string"},"display_name":{"type":"string"}},"required":["id"]},"PublicAppointmentProfessionalDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"last_name":{"type":"string"},"specialty":{"type":"string"}},"required":["id"]},"PublicAppointmentCustomerDto":{"type":"object","properties":{"name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"}},"required":["name"]},"PublicAppointmentDatesDto":{"type":"object","properties":{"start":{"type":"string","format":"date-time"},"end":{"type":"string","format":"date-time"},"time_zone":{"type":"string","description":"IANA, ej. America/Santiago"}},"required":["start","end"]},"PublicAppointmentResponseDto":{"type":"object","properties":{"_id":{"type":"string","description":"Id de la cita"},"appointment_number":{"type":"number","description":"Correlativo legible de la cita"},"branch":{"$ref":"#/components/schemas/PublicAppointmentRefDto"},"service":{"$ref":"#/components/schemas/PublicAppointmentRefDto"},"professional":{"$ref":"#/components/schemas/PublicAppointmentProfessionalDto"},"customer":{"$ref":"#/components/schemas/PublicAppointmentCustomerDto"},"dates":{"$ref":"#/components/schemas/PublicAppointmentDatesDto"},"appointment_type":{"type":"string","description":"online | in-person"},"status":{"type":"string","description":"pending | confirmed | cancelled | …"},"payment_status":{"type":"string","description":"Estado del pago"},"notes":{"type":"string"},"price":{"type":"number"},"currency":{"type":"string","description":"Moneda ISO 4217"},"paid":{"type":"boolean"},"cancelled_at":{"type":"string","format":"date-time"},"cancellation_reason":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["_id","branch","dates","status"]},"PublicCustomerDto":{"type":"object","properties":{"name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"}},"required":["name"]},"PublicAppointmentCreateDto":{"type":"object","properties":{"branch_id":{"type":"string"},"service_id":{"type":"string"},"professional_id":{"type":"string"},"date":{"type":"string","description":"Fecha (YYYY-MM-DD)"},"start_time":{"type":"string","description":"Hora inicio (HH:mm)"},"end_time":{"type":"string","description":"Hora fin (HH:mm). Si se omite, scheduling la calcula desde la duración del servicio."},"customer":{"$ref":"#/components/schemas/PublicCustomerDto"},"notes":{"type":"string"},"price":{"type":"number"},"currency":{"type":"string"}},"required":["branch_id","service_id","date","start_time","customer"]},"CancelAppointmentDto":{"type":"object","properties":{"reason":{"type":"string","description":"Motivo de cancelación"}}},"TenantCreateDto":{"type":"object","properties":{"name":{"type":"string","description":"Nombre legible del tenant (cliente final del developer). Ej: \"ACME Corp\"."},"external_id":{"type":"string","description":"ID externo del tenant en el sistema del developer. Único por company. Si ya existe se devuelve el tenant existente (idempotencia)."},"metadata":{"type":"object","description":"Metadata libre."}},"required":["name"]},"PublicTenantResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"ObjectId del tenant"},"name":{"type":"string"},"external_id":{"type":"object","nullable":true,"description":"Identificador propio que enviaste al crear el tenant"},"metadata":{"type":"object"},"whatsapp_configs_count":{"type":"number","description":"Canales de WhatsApp asociados"},"setup_links_count":{"type":"number","description":"Setup links vigentes"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","name","external_id","metadata","created_at","updated_at"]},"PublicTenantListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicTenantResponseDto"}},"next_cursor":{"type":"object","nullable":true,"description":"Cursor para la página siguiente. null cuando no hay más."}},"required":["data","next_cursor"]},"TenantUpdateDto":{"type":"object","properties":{"name":{"type":"string"},"external_id":{"type":"object","description":"Pasar null para limpiar el external_id existente."},"metadata":{"type":"object"}}},"PublicTenantWhatsappConfigDto":{"type":"object","properties":{"id":{"type":"string","description":"ObjectId del canal"},"name":{"type":"string"},"phone_number_id":{"type":"string","description":"phone_number_id emitido por Meta"},"phone_number":{"type":"string"},"is_active":{"type":"boolean"}},"required":["id"]},"PublicTenantWhatsappConfigListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicTenantWhatsappConfigDto"}}},"required":["data"]},"SetupLinkThemeDto":{"type":"object","properties":{"primary":{"type":"string"},"primary_foreground":{"type":"string"},"background":{"type":"string"},"text":{"type":"string"},"muted":{"type":"string"},"muted_text":{"type":"string"},"card":{"type":"string"},"border":{"type":"string"},"destructive":{"type":"string"},"destructive_foreground":{"type":"string"},"secondary":{"type":"string"},"secondary_foreground":{"type":"string"}}},"SetupLinkCreateDto":{"type":"object","properties":{"language":{"type":"object","description":"Código de idioma BCP-47. null/omitido = se usa el idioma del browser del cliente final."},"success_redirect_url":{"type":"object"},"failure_redirect_url":{"type":"object"},"allowed_modes":{"type":"array","description":"Modos de conexión permitidos.","items":{"type":"string","enum":["embedded_signup","coexistence","qr"]}},"provision_phone_number":{"type":"boolean","description":"Si true, intentar provisión automática de número (fuera de scope inicial; reservado).","default":false},"theme":{"$ref":"#/components/schemas/SetupLinkThemeDto"}}},"PublicSetupLinkResponseDto":{"type":"object","properties":{"id":{"type":"string"},"dev_tenant_id":{"type":"string"},"token":{"type":"string","description":"Token del link. Es la credencial: tratalo como secreto."},"url":{"type":"string","description":"URL lista para entregar al tenant"},"language":{"type":"object","nullable":true},"success_redirect_url":{"type":"object","nullable":true},"failure_redirect_url":{"type":"object","nullable":true},"allowed_modes":{"type":"array","items":{"type":"string"}},"provision_phone_number":{"type":"boolean"},"theme":{"type":"object","nullable":true},"last_used_at":{"type":"object","format":"date-time","nullable":true},"revoked_at":{"type":"object","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","dev_tenant_id","token","url","language","success_redirect_url","failure_redirect_url","allowed_modes","provision_phone_number","theme","last_used_at","revoked_at","created_at","updated_at"]},"PublicSetupLinkListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicSetupLinkResponseDto"}}},"required":["data"]},"SetupLinkUpdateDto":{"type":"object","properties":{"language":{"type":"object","description":"Código de idioma BCP-47. null/omitido = se usa el idioma del browser del cliente final."},"success_redirect_url":{"type":"object"},"failure_redirect_url":{"type":"object"},"allowed_modes":{"type":"array","description":"Modos de conexión permitidos.","items":{"type":"string","enum":["embedded_signup","coexistence","qr"]}},"provision_phone_number":{"type":"boolean","description":"Si true, intentar provisión automática de número (fuera de scope inicial; reservado).","default":false},"theme":{"$ref":"#/components/schemas/SetupLinkThemeDto"}}},"PublicSetupLinkConfigResponseDto":{"type":"object","properties":{"tenant_name":{"type":"string","description":"Nombre del tenant dueño del link"},"language":{"type":"object","nullable":true},"allowed_modes":{"description":"embedded_signup | coexistence | qr","type":"array","items":{"type":"string"}},"provision_phone_number":{"type":"boolean"},"theme":{"type":"object","nullable":true},"success_redirect_url":{"type":"object","nullable":true},"failure_redirect_url":{"type":"object","nullable":true},"meta_app_id":{"type":"string","description":"App id de Meta para el Embedded Signup"}},"required":["tenant_name","language","allowed_modes","provision_phone_number","theme","success_redirect_url","failure_redirect_url","meta_app_id"]},"StartSetupLinkRequestDto":{"type":"object","properties":{"mode":{"type":"string","enum":["embedded_signup","coexistence","qr"]}},"required":["mode"]},"PublicStartSetupLinkResponseDto":{"type":"object","properties":{"mode":{"type":"string","description":"embedded_signup | coexistence | qr"},"state":{"type":"string","description":"State HMAC que correlaciona el callback"},"meta_app_id":{"type":"string","description":"Sólo en embedded_signup / coexistence"},"config_id":{"type":"string","description":"Sólo en embedded_signup / coexistence"},"graph_api_version":{"type":"string","description":"Sólo en embedded_signup / coexistence"},"stream_url":{"type":"string","description":"Sólo en modo qr: stream SSE de pairing"},"pending_id":{"type":"string","description":"Sólo en modo qr"}},"required":["mode","state"]},"CompleteSetupLinkRequestDto":{"type":"object","properties":{"state":{"type":"string","description":"state HMAC firmado emitido por /start"},"code":{"type":"string","description":"authorization code retornado por FB.login"},"waba_id":{"type":"string","description":"WhatsApp Business Account ID provisto por el SDK"},"phone_number_id":{"type":"string","description":"Phone Number ID provisto por el SDK"},"mode":{"type":"string","enum":["embedded_signup","coexistence"]}},"required":["state","code","waba_id","phone_number_id","mode"]},"PublicCompleteSetupLinkResponseDto":{"type":"object","properties":{"redirect_url":{"type":"string","description":"Dónde mandar al usuario al terminar el flujo"}},"required":["redirect_url"]},"AttachChannelRequestDto":{"type":"object","properties":{"state":{"type":"string","description":"state HMAC firmado emitido por /start"},"channel_id":{"type":"string","description":"channel_id del Channel ya creado vía QR"}},"required":["state","channel_id"]},"PublicAttachChannelResponseDto":{"type":"object","properties":{"channel_id":{"type":"string","description":"ObjectId del canal creado"},"dev_tenant_id":{"type":"string","description":"Tenant al que quedó asociado el canal"}},"required":["channel_id","dev_tenant_id"]},"SelectProjectRequestDto":{"type":"object","properties":{"project":{"type":"string","description":"Slug o ObjectId del project que se quiere activar para la session CLI."}},"required":["project"]},"PublicCliProjectDto":{"type":"object","properties":{"id":{"type":"string","description":"ObjectId del project"},"slug":{"type":"string"},"name":{"type":"string"}},"required":["id"]},"PublicCliSelectProjectResponseDto":{"type":"object","properties":{"access_token":{"type":"string","description":"JWT de sesión CLI con el project ya aplicado"},"expires_at":{"type":"string","format":"date-time"},"current_project":{"$ref":"#/components/schemas/PublicCliProjectDto"}},"required":["access_token","expires_at","current_project"]},"PublicCliMeResponseDto":{"type":"object","properties":{"user_id":{"type":"string","description":"ObjectId del usuario dueño de la sesión"},"email":{"type":"string"},"current_project":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/PublicCliProjectDto"}]},"session_id":{"type":"object","nullable":true},"is_cli_session":{"type":"boolean","description":"true cuando el bearer es un JWT del CLI y no un PAT"}},"required":["user_id","email","current_project","session_id","is_cli_session"]}}}}