Chatfuel
Public API

Referencia de la API de mensajería

Lee conversaciones y envía texto, archivos y plantillas de WhatsApp en WhatsApp, Instagram, Facebook, TikTok y el widget del sitio web con la Public API.

Última actualización

La parte de mensajería de la Public API de Chatfuel cubre la bandeja de entrada: leer conversaciones y sus mensajes, enviar texto, archivos y plantillas de WhatsApp a contactos en todos los canales, tomar un chat como humano y devolverlo a un flow, y escuchar mensajes nuevos en tiempo real. Todo funciona para usuarios virtuales Agent, así que una integración de soporte o de CRM no necesita el rol Editor.

Una conversación pertenece a un contacto, y su id es el mismo valor que el ID del contacto. Siempre que una operación pida un conversationID, puedes pasar el ID del contacto de la API de contactos.

Cómo leer conversaciones y mensajes

type Bot {
  # Agent. The conversation with one contact.
  conversation(conversationID: ConversationID!): Conversation!
  # Agent. Number of conversations per status: open, closed, automated.
  conversationCount: [ConversationCountEntry!]!
  # Agent. Open conversations nobody has looked at yet.
  unseenOpenDialogsCount: Int!
  # Agent. The inbox list: contacts with conversations, filtered like the dashboard inbox.
  contactChatsConnection(
    first: Int!, before: ContactSearchCursor, after: ContactSearchCursor,
    assigneeFilter: ContactAssigneeFilter!, unreadOnly: Boolean!,
    salesStageV2Filter: [SalesStageV2!]!, textInputFilter: String
  ): ContactConnection!
}
query Chat($botID: BotID!, $contactID: ConversationID!) {
  bot(id: $botID) {
    conversation(conversationID: $contactID) {
      id
      platform          # whatsapp, instagram, facebook, tiktok, widget
      status            # open, closed, automated
      read
      messages(first: 20) {
        edges {
          node {
            id
            sentTime
            sender { name }
            errors { code originalErrMessage }
            ... on WhatsAppInTextMessage { text }
            ... on WhatsAppOutTextMessage { text whatsappStatus }
          }
        }
        pageInfo { hasNextPage endCursor }
      }
    }
  }
}

Message es una interfaz con un tipo por canal, dirección y contenido, por ejemplo WhatsAppInTextMessage, InstagramInStoryReplyMessage o FacebookOutAttachment. Selecciona los campos de los tipos que manejas y omite el resto; pueden aparecer nuevos tipos de mensaje en cualquier momento.

Cómo enviar mensajes

Cada canal tiene una mutación de texto y una de archivo adjunto. Todas reciben el ID del bot y el ID de la conversación (el ID del contacto) y funcionan para Agent:

type Mutation {
  whatsAppTextMessageSend(botID: BotID!, conversationID: ConversationID!, message: WhatsAppTextMessageSendInput): WhatsAppOutTextMessage
  whatsappAttachmentMessageSend(botID: BotID!, conversationID: ConversationID!, message: WhatsAppAttachmentMessageSendInput!): WhatsAppOutAttachment
  instagramTextMessageSend(botID: BotID!, conversationID: ConversationID!, message: InstagramTextMessageSendInput!): InstagramOutTextMessage!
  instagramAttachmentMessageSend(botID: BotID!, conversationID: ConversationID!, message: InstagramAttachmentMessageSendInput!): InstagramOutAttachment
  facebookTextMessageSend(botID: BotID!, conversationID: ConversationID!, message: FacebookTextMessageSendInput!): FacebookOutTextMessage!
  facebookAttachmentMessageSend(botID: BotID!, conversationID: ConversationID!, message: FacebookAttachmentMessageSendInput!): FacebookOutAttachment
  tiktokTextMessageSend(botID: BotID!, conversationID: ConversationID!, message: TikTokTextMessageSendInput!): TikTokOutTextMessage!
  tiktokAttachmentMessageSend(botID: BotID!, conversationID: ConversationID!, message: TikTokAttachmentMessageSendInput!): TikTokOutAttachment
  widgetTextMessageSend(botID: BotID!, conversationID: ConversationID!, message: WidgetTextMessageSendInput): WebWidgetTextMessage
  widgetAttachmentMessageSend(botID: BotID!, conversationID: ConversationID!, message: WidgetAttachmentMessageSendInput): WebWidgetAttachmentMessage
}
mutation Reply($botID: BotID!, $contactID: ConversationID!) {
  whatsAppTextMessageSend(
    botID: $botID
    conversationID: $contactID
    message: { text: "Hi! Your order has shipped.", clientId: "order-1042-shipped" }
  ) {
    id
    whatsappStatus
    errors { code originalErrMessage }
  }
}

clientId es un ID opcional que eliges tú; vuelve en el mensaje y en los eventos de suscripción, así puedes vincular tus propios registros con los mensajes de Chatfuel. Para los archivos adjuntos, sube el archivo al endpoint de carga del chat descrito en cómo hacer solicitudes y pasa su ID. En WhatsApp, attachmentType es image, document o audio. Las mutaciones de archivos adjuntos pueden fallar con FileContentTypeNotSupported, FileTooBig o FileDoesNotExist.

Las reglas de cada canal siguen vigentes. En WhatsApp, un mensaje libre llega al contacto solo dentro de la ventana de mensajería de 24 horas después del último mensaje del contacto; pasado ese plazo, envía una plantilla aprobada. Instagram y Facebook tienen ventanas de mensajería similares. Los problemas de entrega aparecen en los errors del mensaje.

Cómo enviar una plantilla de WhatsApp

Enviar una plantilla lleva tres pasos: elegir una plantilla aprobada, completar sus parámetros y enviar la plantilla completada. Todos los pasos funcionan para Agent.

type Bot {
  # Agent. The bot's WhatsApp templates with their status, language, category and components.
  whatsAppTemplates(first: Int, after: WhatsAppTemplateCursor, before: WhatsAppTemplateCursor): WhatsappTemplates
  filledWhatsAppTemplate(id: FilledWhatsAppTemplateID!): FilledWhatsAppTemplate!
}

type Mutation {
  # 1. Create a one-time filled copy of a template.
  filledWhatsAppTemplateCreateTemporary(botID: BotID!, templateID: WhatsAppTemplateID!): FilledWhatsAppTemplate!
  # 2. Fill in variables and media.
  filledWhatsAppTemplateSetHeaderTextParamValue(templateID: FilledWhatsAppTemplateID!, name: WhatsAppTemplateTextParamName!, value: String!): FilledWhatsAppTemplate!
  filledWhatsAppTemplateSetBodyTextParamValue(templateID: FilledWhatsAppTemplateID!, name: WhatsAppTemplateTextParamName!, value: String!): FilledWhatsAppTemplate!
  filledWhatsAppTemplateSetFooterTextParamValue(templateID: FilledWhatsAppTemplateID!, name: WhatsAppTemplateTextParamName!, value: String!): FilledWhatsAppTemplate!
  filledWhatsAppTemplateSetHeaderImageFile(templateID: FilledWhatsAppTemplateID!, fileID: FileID!): FilledWhatsAppTemplate!
  filledWhatsAppTemplateSetHeaderVideoFile(templateID: FilledWhatsAppTemplateID!, fileID: FileID!): FilledWhatsAppTemplate!
  filledWhatsAppTemplateSetHeaderDocumentFile(templateID: FilledWhatsAppTemplateID!, fileID: FileID!, fileName: String!): FilledWhatsAppTemplate!
  filledWhatsAppTemplateSetURLButtonParamValue(templateID: FilledWhatsAppTemplateID!, buttonID: ComponentHandleID!, name: WhatsAppTemplateTextParamName!, value: String!): FilledWhatsAppTemplate!
  filledWhatsAppTemplateSetCopyCodeButtonCodeValue(templateID: FilledWhatsAppTemplateID!, buttonID: ComponentHandleID!, codeValue: String!): FilledWhatsAppTemplate!
  # 3. Send it to the contact.
  whatsAppTemplateSend(botID: BotID!, conversationID: ConversationID!, template: WhatsAppTemplateSendInput): WhatsAppOutTemplateMessage
}

Las imágenes, videos y documentos del encabezado se suben al endpoint de carga de plantillas descrito en archivos y tareas. Revisa FilledWhatsAppTemplate.errors antes de enviar: lista los parámetros que siguen vacíos o no son válidos. Usa solo plantillas cuyo IsSupportedInLivechat sea true. Cómo crear plantillas de WhatsApp explica cómo se crean y aprueban las plantillas.

Cómo tomar un chat y devolverlo

type Mutation {
  # Agent. Returns the conversation with a contact, creating it if the contact has none yet.
  conversationCreate(contactID: ContactID!): Conversation!
  # Agent. Opens a live chat with the contact (status open), like a teammate taking over the chat in the inbox.
  conversationStart(botID: BotID!, conversationID: ConversationID!): Conversation!
  # Agent. Closes the live chat and sends the contact to a flow.
  conversationFinishSendToFlow(botID: BotID!, conversationID: ConversationID!, flowID: FlowID!): Conversation!
  # Agent. Marks messages up to the given one as read.
  conversationReadMessages(botID: BotID!, conversationID: ConversationID!, before: MessageID!): Conversation!
}

Los chats en vivo pueden cerrarse automáticamente tras un periodo sin mensajes. bot.livechatAutoClosingConfig muestra esta configuración a cualquier usuario virtual; cambiarla con botSetLivechatAutoClosingConfig(botID, cfg: { enabled, delay }), donde delay va de Minutes10 a Days7, es Personal token only (solo con token personal) y requiere el rol Admin.

Suscripciones de mensajería

type Subscription {
  # Agent. A new message in one conversation, incoming or outgoing.
  messageAdded(botID: BotID!, conversationID: ConversationID!): Message
  # Agent. A message changed, for example its WhatsApp delivery status.
  messageUpdated(botID: BotID!, conversationID: ConversationID!): Message
  # Agent. Changes in the inbox list for the given filters.
  contactsChatUpdates(
    botID: BotID!, assigneeFilter: ContactAssigneeFilter!, unreadOnly: Boolean!,
    salesStageV2Filter: [SalesStageV2!]!, textInputFilter: String
  ): ContactsChatUpdate
  # Agent. The number of unseen open conversations changed.
  unseenOpenDialogsCountChanged(botID: BotID!): Int
}

Para seguir toda la bandeja de entrada, suscríbete a contactsChatUpdates con assigneeFilter: { type: Any } y luego abre messageAdded para las conversaciones que te interesan.

Problemas comunes

Un mensaje de WhatsApp se acepta pero nunca se entrega

Probablemente la ventana de 24 horas está cerrada. Lee errors en el mensaje devuelto o espera messageUpdated; para llegar al contacto, envía una plantilla aprobada con whatsAppTemplateSend.

"NotEnoughPermissions" al enviar un mensaje

La conversación pertenece a otro bot, o la configuración de roles del bot limita al usuario virtual a los contactos asignados a él. Asigna el contacto al usuario virtual con contactSetAssignee o cambia la configuración de roles, como se describe en equipo y roles.

"FileContentTypeNotSupported"

El canal no acepta este tipo de archivo, o el fileType usado al subirlo no coincide con attachmentType. Vuelve a subir el archivo con el tipo correcto.

En esta página