Webhooks (handle received SMS + more)

There are 4 webhooks that we can send to your custom server (or custom no-code workflow):

  1. Received messages - Triggered whenever you receive a message.

  2. Sent messages - Triggered whenever you dispatch an action for sending SMS.

  3. Failed messages - Triggered whenever a message fails (in case of failed messages you firstly get a Sent message webhook, and then failed message webhook)

  4. Changed contact tag - Triggered whenever a contact tag is changed (E.g. Cold -> Warm)

How it works

To make TextLink send request to your webhook, you just need to plug it in the corresponding webhook url field in our API console, and click save. You can click Test webhooks button to get a sample request to each of your webhooks and to see if they are working. Maximum length of webhook string is 300 characters.

Webhook request contains JSON body like this:

{
  "secret": "YOUR_WEBHOOK_SECRET",
  "phone_number": "+11234567890",
  "text": "Working!",
  "timestamp": 1748455363370
}

Though fields can differ based on webhook type.

If your webhook does not return status 200, we will assume that the request was not successful, and we will notify you about it via e-mail.

(Optional) Webhook authorization

If you specified a secret, we will send it to you in each request, so you can verify the request is coming from TextLink's servers. Make sure it is a secret string that only you know.

You can see it in the sample body above, and for Make and Zapier, we have a specific section on their corresponding documentation pages.

Creating a custom server (coding solution)

To handle our HTTP POST request, you can use any web application framework, such as Laravel, Django, Express.js, Spring or ASP.NET.

Here is the example of the endpoint definition for Express.js:

const express = require("express");
const app = express()
app.use(express.json())

app.post("/webhook-endpoint", (req, res) => {
    if (req.body.secret != "YOUR_WEBHOOK_SECRET")
        return res.status(401).json({ ok: false });
    
    const { phone_number/* ... other fields */ } = req.body;
    res.status(200).json({ ok: true });
})

app.listen(80);

Using no-code workflows

You can see the example of using Zapier and Make.com on their documentation pages. The other no-code tools function the similar way. If you need any help with other integrations, please feel free to reach us at [email protected]

Example payloads

Received message

{
  "secret": "YOUR_WEBHOOK_SECRET",
  "phone_number": "+381690156360",
  "text": "General Kenobi",
  "tag": "Cold",
  "name": "Aleksandar Spremo",
  "sim_card_id": 123
}

Where tag is the custom tag defined in the Chat App or update tag API request, and name is the name of the contact (if you have created a contact for that phone number).

Message dispatch (sent message)

{
  "secret": "YOUR_WEBHOOK_SECRET",
  "phone_number": "+381690156360",
  "text": "Hello there",
  "portal": true,
  "timestamp": 1748463114559,
  "sim_card_id": 123
}

portal is true if message is sent through Chat app, and sim_card_id is the id of the SIM card that the message was dispatched to.

Failed message

{
  "secret": "YOUR_WEBHOOK_SECRET",
  "phone_number": "+381690156360",
  "text": "Hello there",
  "portal": true,
  "timestamp": 1748463114559,
  "textlink_id": 100123,
  "custom_id": "1234"
  "sim_card_id": 123
}

portal is true if message is sent through Chat app, and sim_card_id is the id of the SIM card that the message was dispatched to. custom_id is the custom id you have provided in the send SMS API if you provided it, and textlink_id is the message ID in the TextLink database.

Tag change

{
  "name": "Aleksandar Spremo",
  "phone_number": "+381690156360",
  "tag": "Warm",
  "subuser_id": 6
}

name the name of the contact (if you have created a contact for that phone number), tag is the name of the new tag, and subuser_id is optional parameter that shows your TextLink subuser ID that received the webhook, if it was sent to a subuser and not to the admin account.

Last updated