chamaileon integrationChamaileon offers a webhook interface for email HTML exchange. Through this integration emails and related data can be uploaded directly to other software (ESP, CRM, ERP, etc) that has an open API for managing emails or email templates.

Several integrations with the largest ESPs and CRMs are already added to Chamaileon as well as Zapier integration for tools that has a Zapier integration. If your tool is not listed on Chamaileon’s official integration list, you can develop an integration yourself and add it as a custom integration.

As a Custom Integration API partner, you can sync and update emails from Chamaileon to your tool. A status synchronization allows you to sync the email’s workflow status back to the Chamaileon platform. It’s useful when an email is sent or scheduled, and edits shouldn’t be made anymore.

The following documentation includes every detail developers might need to create a custom integration to Chamaileon.

General use-case and basic terms

In the basic and most general use-case, a Chamaileon user creates an email template with Chamaileon Email Builder and wants to send the email with an email sending tool (we will call it partner). To do that, email HTML needs to be transferred from the Chamaileon app to the partner system (we call it synchronization), and if needed, the email HTML has to be updateable.

We assume that the Chamailen user has an account in the partner system that is accessible with the appropriate credentials, usually an API key, token, or a token with a secret. These values usually serve as authorization keys and also identify the user account in the partner system. When integration is saved to Chamaileon, you can add these credentials as custom fields. In this description, we will refer to these credentials as connection data. Connection data is sent securely with every webhook request.

We call integration that connects Chamaileon with the partner system. Integration must implement as a set of webhooks that are called with a request when a user action is performed in the Chamaileon app.

When you have developed the integration and it is ready to use, Chamailon users must setup (save) a new integration connection (also often referred to only as integration) in their Chamaileon workspace. For a custom webhook integration, the user must add the base URL of the webhook and the secret used in webhook calls. Users can add and save a custom number of connection fields that will be encapsulated in the connection data.

Where the integration is implemented?

In most cases, integration is an independent proxy tool that implements the Chamaileon webhook interface and transfers the data to the partner’s API.

In some cases, the integration is directly implemented on the partner’s backend.

Email fields and data that can be synchronized with the API:

  • emailHTML: email HTML output generated by Chamaileon software,
  • emailText: plain text version of the generated HTML email,
  • previewText: the email’s preview text, useful when you sync campaigns,
  • subject: the subject line for the planned campaign/email

Security and authorization

Webhooks are called with sensitive and private data, including emails, addresses, and authorization credentials.

  • Webhook endpoints must use HTTPS.
  • Body content is signed in a JWT (JSON Web Token) and attached to the request (to the query params for GET requests and in the body of POST and PUT requests)
  • Content is signed with a secret that can be specified when you create a new custom integration.

Example:

const body = { … }
body.authedPayload = jwt.sign(body, apiSecret)
post(URL, method, body);

Responses

All responses are JSON objects with standardized fields.

If the query was unsuccessful the response contains an error object, otherwise, the error has to be null. The result of the query is encapsulated in the result object.

The content of the error object can be useful for debugging or informing users.

Please use the following error pattern when you want to show a meaningful error notification to Chamaileon users on the interface:

result: null,
error: {
    notification: “String displaying on the front-end, it is propagated until another notification overwrites it”,
    message: “String, a message used for debugging or logging”,
    code: “SHORT_ERROR_CODE”,
    originalError: Object
}

originalError might be an empty Object ({}) or might contain another level of the same pattern.

Webhook endpoints

Synchronization webhooks must be implemented on the integration partner’s side. Webhook routes must be found at <baseURL>/<hookRoute>, where <baseURL> is customizable when saving a custom integration.

Routes are called by the Chamaielon backend in the following cases:

  • When the user in Chamaileon creates the integration (Integration setup post-hook, POST: <baseURL>/v1/integration/create)
  • When the user in Chamaileon opens the Sync dialog of an email and selects the integration (Pre hook, GET: <baseURL>/v1/email/pre)
  • When the user in Chamaileon synchronizes the email with the integration (Synchronization hook, POST: <baseURL>/v1/email/sync)
  • When the user selects “Update sync” in order to update the email template (Synchronization update hook, PUT: <baseURL>/v1/email/sync/:id)

Integration setup post-hook

This is a one-time call when a Chamaileon user sets a new integration up. Regardless of the response, the integration will be saved in Chamaileon’s database.

If the response contains an error notification, it will be shown for the user as a warning on the UI.

POST <baseURL>/v1/integration/create

Body:

{
    connectionData: Object, described below (link),
    authedPayload: Object, described above (link)
}

Example:

{
    connectionData: {
        user: “username”,
        apiKey: “sssdfmdspovksdlvm”,
    },
    authedPayload: “slkdfiw.dkfioefsf.sdfioxvmkvx”,
}

ConnectionData is an object with all necessary connection credentials that are needed for authenticating the user in the partner system. If you choose to create a predefined integration, the keys of the connectionData are saved to offer for the client when creating the integration.

The response does not influence the save process of the integration in the Chamaileon database, however, if the error contains a notification field, it is shown for the user.

Pre-hook

Listing preconditions and requirements of adding a new email/campaign/template.

How it works: When a client wants to synchronize an email with a given integration (clicks Sync), some information might be needed from the integration side, eg. the folder in the parter system, where to save the mail, the name, or the subject, etc. On the integration connector side, these data might be required or might be overridden as well.

After the below-described data is pre-fetched a form is displayed in the Chamaeilon app based on the hook answer to fill in the missing information by the user. Once the user fills out the form, the e-mail can be synced (next route).

Note that connectionData and authedPayload (carry only the connectionData) are sent as a query param. These objects are sent as a stringified and URL-encoded JSON.

GET <baseURL>/v1/email/pre

The response is directly used to display the user-filled form and results are sent back during sync.

Response:

{
    error,
    result: [fieldSet]
}

a fieldSet is

{
    id: an identifier of the field,
    name: a human-readable name of the field,
    type: the type of the field (text, select or logical),
    required: a boolean value that tells whether it is required to answer,
    values: if the type is select, this is an array of choices.
}

an element of the values can be:

{
    value: the value to send,
    name: a human-readable text of the value,
    default: boolean, true for the default value
}

Example response:

{
    "success": true,
    "result": [{
        "id": "folder",
        "name": "Folder",
        "type": "select",
        "values": [{
            "value": "0bdb03ef0000000000000000000000006a2b",
            "name": "Messages",
            "default": true
        }, {
            "value": "0bdb03ef0000000000000000000000006a2d",
            "name": "Drafts",
            "default": false
        }, {
            "value": "0bdb03ef0000000000000000000000006a47",
            "name": "newFolder",
            "default": false
        }],
        "required": true
    }, {
        "id": "messageName",
        "name": "Message name (default: the subject)",
        "type": "text",
        "required": false
    }]
}

Sync email HTML

Action: Once the user filled out the form with preconditions, then clicked the Sync button, email, text-version, and all other details are generated and sent to the sync route.

POST <baseURL>/v1/email/sync

Body:

{
    "authedPayload": String, the signed payload,
    "emailHTML": String, the email in html,
    "emailText": String, the email as text,
    "previewText": String, the email preview text,
    "subject": String, The subject of the e-mail,
    "connectionData": Object, connection keys and credentials,
    "pre": Object, the filled preconditions
}

Example:

{
    "authedPayload": "sdasld.asdmasld.sadfksdfdf",
    "emailHTML": "<html>The content as a html</html>",
    "emailText": "The content as a text",
    "subject": "The subject of the e-mail",
    "connectionData": {
        "apiToken": "72kg358mcjsn"
    },
    "pre": [{
        "id": "folder",
        "value": "0bdb03ef0000000000000000000000006a2c"
    }, {
        "id": "messageName",
        "value": "Name to be saved in the ESP"
    }]
}

The pre object contains the response from the previous, pre, request.

Response:

{
    error: error object, if any, otherwise null,
    result: {
        id: the id of the email on the integration side
        status: String, optional, the status of the email (synced or sent),
        webUrl: String, optional, a URL where the email can be opened in a browser
    }
}

Update sync

When an email/campaign/template has been already synchronized, its content can be updated. It can be done using the following method:

PUT: <baseURL>/v1/email/sync/:id

Where id” is a key to identify the email/campaign/template on the integrator side returned from the created endpoint.

Body:

{
    "authedPayload": String, the signed payload,
    "emailHTML": String, the email in html,
    "emailText": String, the email as text,
    "previewText": String, the email preview text,
    "subject": String, The subject of the e-mail,
    "connectionData": Object, connection keys and credentials
}

The structure is the same as for the sync without pre fields.

Workflow connector webhooks

To report back to Chamaileon about the email//campaigntemplate status, a webhook can be configured on the integrator side.

Email status update webhook

This webhook is a reverse hook, implemented at the Chamaileon backend, and should be called by the integration when the status of the email is changed from “synced” to “sent” or back. Since this action is not necessarily existing or is not visible through the API, the implementation and usage of this hook are optional.

Target:

POST – https://folders.chamaileon.io/sync/webhook/v1/

Body:

{
    syncId: The id of the email on the integration side,
    status: String, the new status of the e-mail
    authedPayload: The signed payload
}

How to make available your integration to Chamaileon users

Bear in mind, that only Chamaileon’s support team can enable your integration for all OR specific Chamaileon users.

Enabling for all users is a good way to promote your solution that has email sending capabilities. If you wish to do so, please drop an email to hello@chamaileon.io about you and your plans.

We recommend checking out how existing integrations work for Chamaileon users with a test Chamaileon account before you start developing a new integration.