Getting started

Textbelt is an SMS API that is built for developers who just want to send and receive SMS. Sending an SMS is a simple thing. Our goal is to provide an API that is correspondingly simple, without requiring account configuration, logins, or extra recurring billing.

Send an SMS using HTTP POST

The https://textbelt.com/text endpoint accepts a POST request with the following parameters:

  • phone: A phone number. If you're in the U.S. or Canada, you can just send a normal 10-digit phone number with area code. Outside the U.S., it is best to send the phone number in E.164 format with your country code.

  • message: The content of your SMS.

  • key: Your API key (use textbelt to send a free message).

  • sender: Optionally, the name of the business/organization you represent. This field is for regulatory purposes and is not visible to the end user in most countries. If not set, sender will default to your account-wide sender name. See Compliance for more detail.

Every programming language has a way to send an HTTP POST request. Instead of installing a special Textbelt library, just send a POST request using your preferred method. Below are some examples in common languages.

Examples

curl -X POST https://textbelt.com/text \
     --data-urlencode phone='5555555555' \
     --data-urlencode message='Hello world' \
     -d key=textbelt

Note: Regulations require that you state the name of your business/organization in SMS messages. If you are sending recurring SMS, opt-out language is required (e.g. "Reply STOP to opt-out". We automatically handle STOP replies).

Response

The /text endpoint will respond with JSON:

  • success: Whether the message was successfully sent (true/false).

  • quotaRemaining: The amount of credit remaining on your key.

  • textId: The ID of the sent message, used for looking up its status. Only present when success=true. Use this to check SMS delivery status.

  • error: A string describing the problem. Only present when success=false.

An example of a message successfully sent:

{"success": true, "quotaRemaining": 40, "textId": 12345}

Here's an example of when you've run out of quota:

{"success": false, "quotaRemaining": 0, "error": "Out of quota"}

Or when you're missing a required variable such as phone, message, or key:

{"success": false, "error": "Incomplete request"}

If you're getting the above message even though you're specifying the variable, you should make sure that you're sending the request correctly as an HTTP POST request.

Testing this API

If you want to validate your key without actually using your text quota, append "_test" to your key and you will receive a response from the /text endpoint confirming that a text would send. However, credit will not be deducted from your account.

Receiving SMS replies

U.S. phone numbers only: Textbelt lets you receive replies to SMS you've sent. Replies are sent by webhook, meaning you will have to set up an HTTP or HTTPS route on your website that will process inbound SMS.

Add a replyWebhookUrl parameter to your send message request. This is the same as the examples above, except it includes replyWebhookUrl. For example:

curl -X POST https://textbelt.com/text \
     --data-urlencode phone='5555555555' \
     --data-urlencode message='Hello?' \
     -d replyWebhookUrl='https://my.site/api/handleSmsReply' \
     -d key=textbelt

This will send an SMS. If the recipient responds, Textbelt will send an HTTP POST request to the specified endpoint (in this case, https://my.site/api/handleSmsReply).

The webhook payload is application/json encoded. Your server must interpret it like any other HTTP POST request with a JSON payload. The JSON payload contains the following:

  • textId: The ID of the original text that began the conversation.

  • fromNumber: The phone number of the user that sent the reply (you can use this, for example, to send them a response depending on their reply).

  • text: The content of their reply

Here's an example payload:

{
  "textId": "123456",
  "fromNumber": "+1555123456",
  "text": "Here is my reply"
}

Note: SMS replies cannot be received on the free textbelt key.

Verifying the webhook

It is best practice to verify the incoming POST request to make sure it is not forged. The POST request contains a header X-textbelt-signature, which is an HMAC that authenticates the JSON payload using a SHA-256 hash function.

The header X-textbelt-timestamp contains a UNIX timestamp (in seconds). You should ensure that this timestamp is not more than 15 minutes out of date.

To verify that the request is valid, take the timestamp + raw JSON payload and sign it with your API key. The result should be equal to the signature.

For example, in Javascript:

const crypto = require("crypto");

function verify(apiKey, timestamp, requestSignature, requestPayload) {
  const mySignature = crypto
    .createHmac("sha256", apiKey)
    .update(timestamp + requestPayload)
    .digest("hex");
    
  return crypto.timingSafeEqual(
    Buffer.from(requestSignature),
    Buffer.from(mySignature)
  );
}

And in Python:

import hmac
import hashlib

def verify(api_key, timestamp, request_signature, request_payload):
    my_signature = hmac.new(api_key.encode('utf-8'), (timestamp + request_payload).encode('utf-8'), hashlib.sha256).hexdigest()
    return hmac.compare_digest(request_signature, my_signature)

Including custom data

The /text endpoint supports a webhookData field. This data is passed as data in the webhook request.

For example:

curl -X POST https://textbelt.com/text \
     --data-urlencode phone='5555555555' \
     --data-urlencode message='Hello?' \
     -d replyWebhookUrl='https://my.site/api/handleSmsReply' \
     -d webhookData='my custom data'
     -d key=textbelt

Produces a response:

{
  "textId": "123456",
  "fromNumber": "+1555123456",
  "text": "Here is my reply"
  "data": "my custom data"
}

There is a maximum length of 100 characters in the webhookData field.

Get an API key

Create an API key to start sending and receiving SMS!

Last updated