Implementing Messaging app extension

This page will cover the technical aspects for adding and creating a manifest as well as the implementation flows for Messaging app extension. For general overview and development steps see Messaging app extension page and for error codes Error codes and troubleshooting page.

Manifest for Messaging app extension


A manifest describes, in a special contract format, the endpoints to which Pipedrive will make requests to. Based on the responses to those requests, the data received will be displayed inside Pipedrive UI in a pre-defined format. For the Messaging app extension, the data received from the endpoints will be displayed in the Messaging inbox under integrations.

The manifest for your app will need the appropriate URLs of a messaging service's API endpoints. Once the manifest for your messaging app is submitted to Marketplace Manager, it will be validated against a pre-defined schema.

Template for Messaging manifest

The file below defines the JSON schema of the manifest and the endpoints which the app needs to expose to display the service's contents inside the Pipedrive's Messaging inbox. All endpoints' URLs contain the provider_channel_id value, which is the identifier the app gives Pipedrive. Pipedrive uses this ID to make requests to the integration, specifically to fetch data about channels.

{
    "version": "v202101",
    "endpoints": {
        "getConversations": "https://example.com/api/channels/:providerChannelId/conversations",
        "getConversationById": "https://example.com/api/channels/:providerChannelId/conversations/:sourceConversationId",
        "postMessage": "https://example.com/api/channels/:providerChannelId/messages",
        "getSenderById": "https://example.com/api/channels/:providerChannelId/senders/:senderId",
        "deleteChannelById": "https://example.com/api/channels/:providerChannelId",
        "getTemplates": "https://example.com/api/channels/:providerChannelId/templates",
        "getMessageById": "https://example.com/api/channels/:providerChannelId/conversations/:sourceConversationId/messages/:sourceMessageId"
    }
}

From this manifest some endpoints are optional.

πŸ“˜

You can import this .yaml file to any API testing tool(e.g., https://editor.swagger.io/) to see exact structures and requirements for requests and responses of Manifest endpoints.


Authentication of the request from Pipedrive


All requests from Pipedrive to the app will be supplemented with an authentication header that uses the same client_id and client_secret as the OAuth token exchange in OAuth authorization.
E.g. Authorization: Basic <base64(client_id:client_secret)>



Pagination cursors


Due to how popular business chat providers work, the Channels API uses a different type of pagination from the standard one used in the Pipedrive public API.

The pagination for the manifest works with cursors, which are references provided by the application to our API, that are sent back to the app when a new page needs to be fetched. For example, in the endpoint getConversations, it's expected by Pipedrive to receive a property next_messages_cursor, which we will store and send back when our API calls the getConversationById endpoint (after query parameter).

In the same getConversations endpoint, inside the additional_data object, the application will send the after property to our API, which is a cursor that can be used to fetch more conversations in the same endpoint (after query parameter).



Implementation flows


Installation flow

The installation is considered complete when the app is installed via OAuth 2.0 and there is at least one channel registered for the installation. The installation process will call the following manifest endpoints during the process:

Manifest endpoint

Required to implement?

getConversations

Yes

getTemplates

Yes, if the channel was registered with the option template_support as true

getSenderById

Yes, if a sender was returned in a conversation for the getConversations request, with the fetch_avatar flag set as true.

Channels API endpoint

Usage required?

POST /channels

The app needs to register a channel in order to use the extension.


818818

Sending a message flow

The user is able to send and receive messages by using a channel. These messages may contain attachments. When a user sends a message, Pipedrive will call the following manifest endpoint:

Manifest endpoint

Required to implement?

postMessage

Yes

The public endpoint to receive new messages will update a message if it already exists in the API.

Channels API endpoint

Required to implement?

POST /channels/messages/receive

Yes


741741

Receiving a message flow

When a channel receives a new message, be it to start a new conversation or to add it to an existing one, that message should be sent to Channels API. When it’s a message related to a new conversation, our API will request more detailed data about the conversation by making a request to the manifest endpoint getConversationById.

Manifest endpoint

Required to implement?

getConversationById

If the message received does not have a conversation in the API, Channels API will request more details about the conversation with the specified conversation_id.

Channels API endpoint

Required to implement?

POST /channels/messages/receive

When a message from the end-user is received, use this endpoint to register it.


694694

Handling expiring links flow

Handling expiring attachments

When an attachment was registered with the option link_expires true, Pipedrive will test the attachment links provided, by sending a HEAD request. In the case that the link is no longer accessible, Pipedrive will make a request to the following manifest endpoint:

Manifest endpoint

Required to implement?

getMessageById

If the attachment was registered with the option link_expires, this endpoint should be available.


787787

Handling expiring avatars

When a sender was registered with the option avatar_expires, Pipedrive will test the avatar link provided by sending a HEAD request (not more often than once per day). If the link is no longer accessible, Pipedrive will request the following manifest endpoint:

Manifest endpoint

Required to implement?

getSenderById

If the sender was registered with the option avatar_expires, this endpoint should be available

The rest of the update flow will go similarly to the attachment links.




Messaging endpoints for manifest



GET "getConversations" endpoint


Required

The getConversations endpoint is used to sync an initial batch of conversations and their messages. It is called right after a channel is registered in the Channels API using the POST /channels endpoint in the Pipedrive API.

The path parameters sent in the getConversations endpoint:

Name

Type

Required/Optional

Description

providerChannelId

string

Required in the manifest's path description.

A unique providerChannelId that identifies the channel.

The query parameters sent in the getConversations endpoint:

Name

Type

Description

conversations_limit

integer

The maximum number of conversations expected in the response.

messages_limit

integer

The maximum number of messages expected for each conversation in the response.

after

string

A cursor that will be used to fetch more conversations.

Expected response from the getConversations endpoint:

{
  "success": true,
  "data": [
    {
      "id": "string",
      "link": "string",
      "status": "open",
      "seen": true,
      "next_messages_cursor": "string",
      "messages": [
        {
          "id": "string",
          "status": "sent",
          "created_at": "2022-03-29T06:38:06.913Z",
          "message": "string",
          "sender_id": "string",
          "reply_by": "2022-03-29T06:38:06.913Z",
          "attachments": [
            {
              "id": "string",
              "type": "string",
              "name": "string",
              "size": 0,
              "url": "string",
              "preview_url": "string"
            }
          ]
        }
      ],
      "participants": [
        {
          "id": "string",
          "name": "string",
          "role": "end_user",
          "avatar_url": "string"
        }
      ]
    }
  ],
  "additional_data": {
    "after": "string"
  }
}

GET "getConversationById" endpoint


Required

The getConversationById endpoint is used to fetch a specific conversation and its messages. It is called when an incoming message is part of a new conversation and when paginating over messages.

The path parameters sent in the getConversationById endpoint:

Name

Type

Required/Optional

Description

providerChannelId

string

Required in the manifest's path description.

A unique providerChannelId that identifies the channel.

sourceConversationId

string

Required in the manifest's path description.

The ID of the conversation, as in the field conversation_id on its messages.

The query parameters sent in the getConversationById endpoint:

Name

Type

Description

after

integer

The cursors used for fetching more messages from the provider.

messages_limit

integer

The maximum number of messages expected for each conversation in the response.

It's recommended to use the default value (30) and support pagination, for better performance.

Expected response from the getConversationById endpoint:

{
  "success": true,
  "data": {
    "id": "string",
    "link": "string",
    "status": "open",
    "seen": true,
    "next_messages_cursor": "string",
    "messages": [
      {
        "id": "string",
        "status": "sent",
        "created_at": "2022-03-29T06:39:23.251Z",
        "message": "string",
        "sender_id": "string",
        "reply_by": "2022-03-29T06:39:23.251Z",
        "attachments": [
          {
            "id": "string",
            "type": "string",
            "name": "string",
            "size": 0,
            "url": "string",
            "preview_url": "string"
          }
        ]
      }
    ],
    "participants": [
      {
        "id": "string",
        "name": "string",
        "role": "end_user",
        "avatar_url": "string"
      }
    ]
  },
  "additional_data": {
    "after": "string"
  }
}

POST "postMessage" endpoint


Required

The postMessage endpoint is used to send a new message to a conversation. It’s called when a user types a message in the chat window and sends it. The endpoint supports messages with file attachments.

The Content-Type header

Unlike the other endpoints, requests for this one will be sent as multipart/form-data, since messages may include file attachments.

The path parameters sent in the postMessage endpoint:

Name

Type

Required/optional

Description

providerChannelId

string

Required in the manifest's path description.

A unique providerChannelId that identifies the channel.

The body of the request made to the postMessage endpoint has the following form fields:

Name

Type

Description

message

string

The name of the activity.

senderId

string

The ID of the user who sent the message.

conversationId

string

The ID of the conversation.

recipientIds[]

string

Ids of all recipients for a message, split by ",". Eg. josef123456,Eva879542

files

binaries

A list of binary files. All files sent with the message in multipart/form-data format (with filename and contentType).

Expected response from the postMessage endpoint:

{
  "success": true,
  "data": {
    "id": "string"
  }
}


GET "getSenderById" endpoint


Optional

Inside the Messaging inbox, messages are displayed with their senders. This endpoint is used to fetch additional and up-to-date information about a sender every time a conversation is updated and available in the service/application.
This endpoint is called occasionally (max once per day) to refresh the sender's avatar if avatar_expires is true and also when there is no avatar for the sender but fetch_avatar is set to true during the sender creation (only once when installing the app).

The path parameters sent in the getSenderById endpoint:

Name

Type

Required/Optional

Description

providerChannelId

string

Required

A unique providerChannelId that identifies the channel.

senderId

string

Required

The senderId as specified in the messages.

Expected response from the getSenderById endpoint:

{
  "success": true,
  "data": {
    "id": "string",
    "name": "string",
    "avatar_url": "string"
  }
}


DELETE "deleteChannelById" endpoint


Optional

In some messaging providers (e.g., Facebook Business with various pages), support for multiple channels is provided in the same account. The Messaging app extension provides a way to delete channels from the messaging services with this endpoint.

The path parameters sent in the deleteChannelById endpoint:

Name

Type

Required/optional

Description

providerChannelId

string

Required in the manifest path description

A unique providerChannelId that identifies the channel.

Expected response from the deleteChannelById endpoint:

{
  "success": true,
}


GET "getTemplates" endpoint


Optional

The getTemplates endpoint is used to fetch a list of templates, when available in the provider's service. Right now, only approved WhatsApp templates are supported.

15461546

WhatsApp templates synced to Messaging inbox

The path parameter sent in the getTemplates endpoint:

Name

Type

Required/Optional

Description

providerChannelId

string

Required in the manifest's path description.

A unique providerChannelId that identifies the channel.

Expected response from the getTemplates endpoint:

{
  "success": true,
  "data": {
    "templates": [
      {
        "id": "string",
        "name": "string",
        "content": "string",
        "language": "string"
      }
    ]
  }
}


GET "getMessageById" endpoint


Optional

The getMessageById endpoint is used to get updated messages with attachments. It is used for refreshing an expired attachment's URL when link_expires is set true.

The path parameters sent in the getMessageById endpoint:

Name

Type

Required/Optional

Description

providerChannelId

string

Required in the manifest's path description.

A unique providerChannelId that identifies the channel.

sourceMessageId

string

Required in the manifest's path description.

The message ID as specified in the message.

Expected response from the getMessageById endpoint:

{
  "id": "string",
  "status": "sent",
  "created_at": "2022-03-29T06:51:33.727Z",
  "message": "string",
  "sender_id": "string",
  "reply_by": "2022-03-29T06:51:33.727Z",
  "attachments": [
    {
      "id": "string",
      "type": "string",
      "name": "string",
      "size": 0,
      "url": "string",
      "preview_url": "string"
    }
  ]
}


Did this page help you?