Fundamentals of Application Channels
Application channels are useful for establishing a communication channel in Front with a variety of third party data sources, from SMS to phone call logs to live chat. Application channels also allow you to publish your integration publicly to all Front customers, although this is optional (Front customers can also build application channels purely for in-house use). For details on when to use an application channel vs a custom channel, please see our Overview page. This guide will walk through all the necessary steps to build an application channel.
Replies to channel messages must use the same channel.
You cannot receive an inbound message through a channel, and then reply to the message via another Front inbox such as your personal email account or a team inbox. If you would like to receive a message via a non-native channel and then reply to the message via another Front inbox, use the Import Message API endpoint instead.
Postman collection
We recommend using our Postman collection for Application Channels to facilitate your development.
Creating an Application Channel
To create an application channel, simply create an app in Front and add a channel type. Then, note the credentials (App UID and App secret) in the Basic information tab.
Composer Types for Application Channels
As of April 2022, new or existing channel types have optional access to using an advanced composer that supports most Markdown styling options. If you have already built an application channel with Front and would like to upgrade it to the advanced composer, please email [email protected]
When you’re entering the information to create your own channel type, you’ll have the option to choose the type of composer for your channel type. The two options provided are Basic and Advanced.
With a Basic composer, you’ll have the ability to compose and send only plain text content along with emojis and attachments while still retaining the ability to receive rich text messages.
With an Advanced composer, you’ll have the ability to compose and send a richer message. The following features are supported (along with their respective keyboard shortcuts).
- Bolding
- Italics
- Linking
- Strikethroughs
- Lists (numbered / bulleted)
- Block quotes
- Emojis
- Attachments
If you're using an application channel with an advanced composer and access messages sent through that channel via the API, please use the "body" field of the message to fetch the message content with all its data and formatting preserved.
Timeline Types for Application Channels
When creating a channel type, you can specify the type of conversation timeline for your channel within the Timeline UI Type setting. The options include:
- Standard Timeline
- Chat Timeline
Standard timeline
The standard Front timeline is designed for email and most other channel types. Messages are displayed in large message boxes, and the composer is initialized when you click on the “Reply” or “Reply all” buttons.
Chat timeline
The chat timeline option is optimized for real-time communication like live chat or SMS. Messages are displayed in message bubbles and the composer is open by default at the bottom of the timeline to make it easy to respond quickly to customers.
Channel Authorization
Now that you have a channel type set up, you’ll need to build support for a few key functions. The first is channel authorization, which occurs when a Front user attempts to connect an instance of your channel from their Front settings.
If you set your authentication method to “API Token”, users will see the following when they attempt to connect your channel. If you haven’t already, you’ll need to set up some kind of mechanism to allow users to create an API token for your service. Note that the API Key
that users are expected to submit here is not the same as the secret key you obtain from the Basic information tab of your app. This key is expected to be something that your users can get directly from you, and will allow you to identify which user is trying to connect the channel to Front.
If you set your authentication method to “OAuth”, users will see the following when they attempt to connect your channel. The blue button will redirect the user to the OAuth URL you provided in the channel application. We’ll use the OAuth Client Secret and OAuth Refresh Url to retrieve an access token.
At this point, whether your channel is using API token or OAuth authentication, Front will have an access token it can use to make requests to your server.
Front will use that bearer token to POST
to the Webhook URL
you supplied in the channel application form. The body of the request will look like:
{
"type": "authorization",
"payload": {
"channel_id": "cha_123"
}
}
Your system will need to respond to this message and other messages from Front within 7 seconds. After 7 seconds, Front will timeout and return an error to the user, regardless of any response received after the 7 second timeout.
Responding to Authentication
Once you’ve verified that the request is valid, your server should store the channel_id
in the authorization payload and associate it with the owner of the token. This will allow you to send and receive messages in the future. You’ll also need to send a 200 response to the authorization request with the following:
{
"type": "success",
"webhook_url": "https://webhook.company.com/..."
}
The webhook URL you provide here will be used by Front to POST new messages sent from Front using the channel instance the user created. It does not necessarily have to be a unique webhook for each channel instance. It also does not necessarily have to be the same as the webhook URL you provided in the channel application form, which is used when sending channel authorization requests.
You can test that your server is properly handling channel creation by using the “Authorization” endpoint under “Your Webhook Endpoints” in the Postman collection for Application Channels.
Sending and Receiving Messages
Managing threading
Threading defines how individual messages will be “threaded” into a single conversation. Some channels thread simply by the sender of a message, while others thread conversations only within a particular time frame, or use some other custom logic. With the Channel API, you can control threading through the external_conversation_id
, which must be set when sending messages into the channel. Messages with the same external_conversation_id
will be threaded together. Note that this value is different from a message’s external_id
, which is simply a unique identifier of a single message.
Creating messages in Front
There are two endpoints that can be used to create a message in Front for your channel — the
Sync inbound message endpoint and the Sync outbound message endpoint. The sync inbound message endpoint should be used when you are trying to send an inbound message to the channel. For example, a lead that has just written a message into a website live chat widget. The sync outbound message endpoint should be used to import a message that was sent from the channel. This is useful if outbounds might be sent by the channel outside the context of Front — for example, importing a message that a bot replied to the lead, so that users in Front can see the full history of the conversation.
In either case, you will need to authenticate requests to Front by setting a bearer token generated using your secret key, channel type id, and the id of the channel instance you are trying to send to. Sample code for doing so can be found in the pre-request script of the Postman collection for Application Channels, or via this link. Note that you can use that bearer token to make requests to any of the Channel API endpoints as well as Core API routes of the following formats:
/conversations/:conversation_id*
/messages/:message_id*
A successful request to the Sync inbound message or Sync outbound message endpoints will result in a response that includes a message_uid
you can use to fetch the full message and conversation created in Front. To do so, use the Get message endpoint and use the uid as a resource alias . For example, https://api2.frontapp.com/messages/alt:uid:abcd1234
. Directly fetching the message this way is not necessary though, because Front will also send message_imported
payload to the channel-instance-specific webhook URL to let you know about the successful import.
{
"type": "message_imported",
"payload": {
[MESSAGE BODY]
},
"metadata": {
// Will eventually be deprecated in favor of "external_conversation_ids"
"external_conversation_id": string,
// A single Front conversation may have multiple external conversation
// ids because conversations in Front can be merged.
"external_conversation_ids": [string]
}
}
You can test that your server is properly sending messages to Front by using the “Inbound Message” and “Outbound Message” endpoints in the Postman collection for Application Channels.
Receiving messages from Front
There are two ways your channel might receive messages from Front:
- Messages sent manually by a user
- Auto-reply messages
1. Manually-sent messages
When a user in Front sends a new outbound message or replies to an inbound message using your channel, Front will POST the following to the channel-instance-specific webhook URL:
{
"type": "message",
"payload": {
[MESSAGE BODY]
}
}
The payload
will match the Message schema, an example of which is provided below:
{
"_links": {
"self": "https://api2.frontapp.com/messages/msg_55c8c149",
"related": {
"conversation": "https://api2.frontapp.com/conversations/cnv_55c8c149",
"message_replied_to": "https://api2.frontapp.com/messages/msg_1ab23cd4"
}
},
"id": "msg_55c8c149",
"type": "email",
"is_inbound": true,
"draft_mode": null,
"created_at": 1453770984.123,
"blurb": "Anything less than immortality is a...",
"author": {
"_links": {
"self": "https://api2.frontapp.com/teammates/tea_55c8c149",
"related": {
"inboxes": "https://api2.frontapp.com/teammates/tea_55c8c149/inboxes",
"conversations": "https://api2.frontapp.com/teammates/tea_55c8c149/conversations"
}
},
"id": "tea_55c8c149",
"email": "[email protected]",
"username": "leela",
"first_name": "Leela",
"last_name": "Turanga",
"is_admin": true,
"is_available": true,
"is_blocked": false
},
"recipients": [
{
"_links": {
"related": {
"contact": "https://api2.frontapp.com/contacts/crd_55c8c149"
}
},
"handle": "[email protected]",
"role": "to"
}
],
"body": "Anything less than immortality is a complete waste of time.",
"text": "Anything less than immortality is a complete waste of time.",
"attachments": [
{
"filename": "attachment.jpg",
"url": "https://api2.frontapp.com/download/fil_55c8c149",
"content_type": "image/jpeg",
"size": 10000,
"metadata": {
"is_inline": true,
"cid": "123456789"
}
}
],
"metadata": {}
}
Be sure to check that the type
of payload is message
, create the message in your system, and respond with an external_id
and external_conversation_id
that you want to associate the message with:
{
"type": "success",
"external_id": "external_message_{{$randomInt}}",
"external_conversation_id": "external_conversation_1"
}
2. Auto-reply messages
Front allows users to create auto-reply rules, which automatically send a response upon receiving an inbound message.
Auto-reply messages differ from manually-sent messages in certain ways, related to data structure and the sequence of events:
- An auto-reply message has not yet actually been sent by the time Front sends the event to your channel. This means that an auto-reply event has a different payload than a
message
event. An example auto-reply event is shown below. - After your channel responds with the external IDs, your channel will receive a
message_imported
event with the full message, as described above.
When an auto-reply message is sent, your channel should take the following steps:
- Expect a request like the following. (Note the different payload when compared to a manually-sent message payload.)
- Create the message in your system
- Respond with the same information as with the
message
events; this will be used to associate the message with a conversation. As withmessage
events, bothexternal_id
andexternal_conversation_id
are required). - Wait for a
message_imported
event from Front, which will include the full message payload.
{
"type": "message_autoreply",
"payload": {
[AUTOREPLY MESSAGE BODY]
}
}
This time, the request type
is message_autoreply
, and the payload
will have a different structure. Here's an example payload
:
{
"_links": {
"related": {
"conversation": "https://api2.frontapp.com/conversations/cnv_55c8c149",
"message_replied_to": "https://api2.frontapp.com/messages/msg_1ab23cd4"
}
},
"type": "auto_reply",
"is_inbound": false,
"created_at": 1453770984.123,
"body": "I'll get back to you as soon as possible.",
"text": "I'll get back to you as soon as possible.",
"recipients": [
{
"_links": {
"related": {
"contact": "https://api2.frontapp.com/contacts/crd_55c8c149"
}
},
"handle": "[email protected]",
"role": "to"
}
],
"attachments": [
{
"filename": "attachment.jpg",
"url": "https://api2.frontapp.com/download/fil_55c8c149",
"content_type": "image/jpeg",
"size": 10000,
"metadata": {
"is_inline": true,
"cid": "123456789"
}
}
]
}
Though the payload is different than the payload for a message
event, the expected response is the same:
{
"type": "success",
"external_id": "external_message_{{$randomInt}}",
"external_conversation_id": "external_conversation_1"
}
Handling errors
In some cases, there might be errors that happen on your channel when Front POSTs a message to the provided webhook. To help debug these issues, and to convey failures to users, you can include a certain error code and message in your response. If you wish to indicate that an error occurred while sending a message, you can respond in the following format.
{
"type": [ERROR_CODE],
"message": [MESSAGE]
}
If type
is any of the following, it will indicate in the UI that the message failed to send.
bad_request
authentication_required
forbidden
not_found
request_timeout
too_many_requests
internal_error
Including the message
property is optional. If you do include it, that string will be presented to users as the reason that the message failed to send, pictured below
Updating status through the API
Application channels can become unauthenticated with their third-party services. While typically Front will detect this automatically and set the channel to offline
, in the case of low-volume channels this may not happen automatically. The application channel PATCH endpoint can be used to update the channel's status to offline
manually, which will prompt users to re-authenticate immediately instead of waiting for drafts to fail to send.
This endpoint should be called by the channel itself using the channel's token in the same way as the sync inbound/outbound message endpoints are called.
When the channel is set to offline
, users will see a popup in the lower-left corner of Front that looks something like this:

offline channel popup
When the 'View Settings' button is clicked, it will take the user into the channel settings where they can begin the process to re-authenticate the channel. That looks something like this:
Deletion (optional)
When a user deletes an instance of your channel, Front will send the following to your webhook URL:
{
"type": "delete",
"payload": {
"channel_id": "cha_123"
}
}
Handling this case is optional, but will allow you to keep up to date with user’s channel usage.
Security
To verify that this and other messages sent from Front for your channel are legitimate, you can validate the message signature before accepting it into your system.
The requests made to your webhook server will include 2 headers: X-Front-Signature
and X-Front-Request-Timestamp
. First, check that the timestamp says the request was made recently in order to prevent replay attacks. We recommend 5 minutes as the maximum time before rejecting a message.
- Retrieve the
X-Front-Request-Timestamp
header on the HTTP request and the body of the request. - Concatenate the timestamp and the JSON stringified body of the request to form a string. Use a colon as the delimiter between the two elements.
- Using HMAC SHA256, hash the above string, using your Channel Type Secret Key as the key.
This should match the X-Front-Signature
header. If it does not, you should not trust this message. See our sample code in Typescript for how to validate a message and generate a token.
Publishing
At this point, you’re all set with the technical implementation! If you’re looking to publish your channel as a public partner integration for all Front customers, simply reply to the existing thread you had with our team when we provided your channel id and secret. We’ll work with you to get some marketing content ready for our integrations page, and then publish the integration.
That’s it! If you have any questions, feel free to reach out to us on the Front Community.
Updated 2 months ago