Skip to main content

APIs overview

Leverage our APIs with our API reference documentation.

Checklist icon

Get started

Telnyx is a real-time communications platform with full, feature-rich functionality, making it quick and easy to:

  • Set up and port numbers around the world
  • Configure messaging
  • Control VoIP and IP network functions
  • Define how and where communications can be used in real-time.

The Telnyx API can power a host of specialty applications, from call tracking to cloud-based PBX, dynamic security, and authentication use cases.

Our API Reference is organized by topics, such as Numbers or Messaging. Each topic is prefaced with a general overview that describes how our API can be used within the context of that topic, followed by reference documentation of specific API endpoints.

Telnyx strives to create a developer-first platform with first-rate interactive documentation and 24/7 support. Explore our API capabilities and please let us know how we can better empower your development team to better serve your customers.

Mission Control Portal

You will need a Mission Control Portal account to access our API. Most of the API Reference topics will be familiar to you if you've used the Portal interface before; for example, the connections page corresponds to the connections API topic. You will be able to perform all the same Portal actions through the API.

All API changes are announced in our release notes .

Protocols

Telnyx HTTP endpoints are RESTful , and consume and return JSON . All HTTP endpoints except sms.telnyx.com/messages require an API token value in the request header.

More information on API tokens, Authorization headers, and IP Authentication will be covered in the authentication section below.

CNAM Data and LRN Data may be retrieved with HTTP, as well as DNS ENUM , SIP (LRN only), or XML UDP (LRN only) protocols. DNS ENUM, SIP, and XML UDP requests must be set up to use an IP-authenticated profile. More information on IP Authentication will be covered in the authentication section below.

Glossary

TermDescription
NumbersDIDs and toll-free numbers that can be purchased and managed to receive calls (inbound/origination)
MessagingShort Message Service (SMS) text messaging. Long code
PortingTransferring of DIDs and toll-free numbers onto the Telnyx network from another carrier
ConnectionsProvisions SIP trunks
ReportsAccess Call and Messaging Detail Records, and generate usage reports
AccountYour Mission Control Portal account
CNAM DataCaller ID Name information
LRN DataLocal Routing Number information
Switch DataTelephone switch information

HTTP endpoints

DNS ENUM endpoints

  • api.telnyx.com
  • lrnlookup.telnyx.com

SIP endpoints

  • lrnlookup.telnyx.com

XML UDP endpoints

  • lrnlookup.telnyx.com

Authentication

Log in to your account to obtain the API access keys needed to authenticate your application.

API user and token

API User may either be your Portal email address or your 24-character API Access Key. You can find your API Access Key and API token under Auth in the Portal.

Add an API Token if you have not done so already. Once you have your API user and token, you may use them as header values in HTTP requests.

Sending SMS

An API token is not required to send SMS. Create a new Messaging profile to obtain a messaging profile secret to add to your HTTP headers. More in-depth information on sending SMS can be found in the Messaging Overview .

Glossary

TermDescription
API UserYour Portal account email address or API Access Key
API Access KeyAccess key used in place of your Portal email address as the API user
API TokenToken generated within your Telnyx account to use with API requests
IP AuthenticationUses IP addresses as the authentication method, as opposed to token-based authentication
Profile SecretMessaging profile token used to authenticate SMS send requests

Rate limits

Requests to api.telnyx.com are rate limited to ensure that the API remains responsive for all users. The rate limits per user are:

ActionPathLimit
Global (all requests)/*~40 requests per second
Number Search (unauthenticated)/origination/number_searches~10 requests per minute
Number Search (authenticated)/origination/number_searches~40 requests per second
Number Update/origination/numbers/{id}~60 requests per minute

When the rate limit is exceeded responses with status code 429 will be returned indicating that you have exhausted the number of requests allowed in the current window.

To avoid exceeding the limits we recommend that you proactively limit the rate of requests made by your application.

These limits are subject to change based on usage and may be adjusted to align with changes in capacity.

Over your rate limit?

Contact [email protected] if you find you are exceeding the rate limit.

Rate limit response body

{
"errors": [
{
"code": "10011",
"title": "Too many requests",
"detail": "You have exceeded the maximum number of allowed requests."
}
]
}

The status code of this response is 429 .

Parameters & field names

The Parameter & Field names section provides an overview of patterns for API request and response parameters and field names.

Booleans

Boolean values are presented as true and false values. They will not be 1 or 0 nor will they be strings such as "true" and "false".

Date-times

All date-times are represented in UTC with precisely the following format: YYYY-MM-DDThh:mm:ss.fffZ where fff is the first three decimals of the fractional seconds (i.e., millisecond precision).

API V2 accepts date-times in at least the following 12 formats:

  • YYYY-MM-DDThh:mm:ss.fffZ
  • YYYY-MM-DDThh:mm:ssZ
  • YYYY-MM-DDThh:mmZ
  • The above with -00, -0000, or -00:00 instead of the Z timezone identifier.

Times (no date portion)

All times are represented in UTC with precisely the following format: hh:mm:ss.fffZ where fff is the first three decimals of the fractional seconds (i.e., millisecond precision).

Durations

If a parameter represents a unit of time, then the unit name should be part of the field name so that the consumer knows what the value represents. For example, a retry timeout value would be named retry_timeout_secs or retry_timeout_millis.

Valid field suffixes are:

  • millis
  • secs
  • hours
  • days
  • weeks
  • months
  • years

API V2 does not use ISO8601 time durations (e.g. P4Y, PT0,42M or P3Y6M4DT12H30M5.423S).

Time zones

Time zone field names are always spelled as timezone and the value is always [the Time Zone Database] area name spelled out as Europe/Berlin, America/Chicago for example.

Date literals

User-friendly date ranges use this naming convention.

Date LiteralRange
yesterdayStarts 00:00:00 the day before and continues for 24 hours.
todayStarts 00:00:00 of the current day and continues for 24 hours.
tomorrowStarts 00:00:00 after the current day and continues for 24 hours.
last_weekStarts 00:00:00 on the first day of the week before the most recent first day of the week and continues for seven full days.
this_weekStarts 00:00:00 on the most recent first day of the week before the current day and continues for seven full days.
next_weekStarts 00:00:00 on the most recent first day of the week after the current day and continues for seven full days.
last_monthStarts 00:00:00 on the first day of the month before the current day and continues for all the days of that month.
this_monthStarts 00:00:00 on the first day of the month that the current day is in and continues for all the days of that month.
next_monthStarts 00:00:00 on the first day of the month after the month that the current day is in and continues for all the days of that month.
last_N_hoursFor the number n provided, starts at 00 of the last hour and continues for the past n hours.
next_N_hoursFor the number n provided, starts at 00 of the next hour and continues for the next n hours.
last_N_daysFor the number n provided, starts 00:00:00 of the current day and continues for the past n days.
next_N_daysFor the number n provided, starts 00:00:00 of the current day and continues for the next n days.
last_N_weeksFor the number n provided, starts 00:00:00 of the last day of the previous week and continues for the past n weeks.
next_N_weeksFor the number n provided, starts 00:00:00 of the first day of the next week and continues for the next n weeks.

HTTP headers

Date-times in HTTP headers follow RFC-7231 §7.1.1.1 's recommended "IMF-fixdate" format.

An example of the preferred format is

Sun, 06 Nov 1994 08:49:37 GMT ; IMF-fixdate

Enums and string literals

Enum and string literal parameters use snake case. If there is an acronym involved, there will not be an underscore between every letter.

For example, by_ani instead ofByANI, byAni, or by_a_n_i.

Country codes

The field name country_code is always used to represent a country. It will be in ISO 3166-1 alpha-2 format in capital letters to represent the country. For example DE for Germany.

Addresses

Addresses are represented like this:

{
"street_address": "311 W Superior St",
"extended_address": "Suite 504",
"locality": "Chicago",
"administrative_area": "IL"
"country_code": "US",
"postal_code": "60654"
}

U.S. addresses

US states are always represented in their two-digit form in capital letters. For example, NY for New York.

City names

City names are always called locality and represented in title case. For example, New York City instead of NEW YORK CITY.

Pagination

The parameter which contains pagination is page. This parameter is a map of pagination attributes.

Example

GET /phone_numbers?page[number]=3&page[size]=1 HTTP/1.1

The default number of items per page is 20; however, sometimes, this may not be appropriate.

Page numbering is 1-based and omitting the page, or the page[number] parameter will return the first page.

Generally speaking, the maximum allowable results will not be more than 250, although there may be some exceptions to this rule.

The total number of results is provided in the total_pages field so that clients will know how many page options to display.

Example

HEADERS

Total-Pages:13

Response:

{
"meta": {
"total_pages": 13,
"total_results": 26,
"page_number": 3,
"page_size": 2
},
"data": [
{
"record_type": "phone_number",
"id": "4567890987",
"phone_number": "+18005550100",
"purchased_at": "2015-05-22T14:56:29.000Z",
...
},
{
"record_type": "phone_number",
"id": "44568890987",
"phone_number": "+18005550199",
"purchased_at": "2015-05-22T14:56:29.000Z",
...
}
]
}

Phone numbers

Phone numbers are always specified in e164 format. For example, +18005550199.

If the country calling code needs to be represented in the API, the field name will always be country_calling_code. If representing the actual country via its alpha 2 representation, country_code will be used.

Ex: {"country_calling_code": "1", "country_code": "US"}

Sorting

An endpoint may support requests to sort the primary data with a sort query parameter.

Example

GET /connections?sort=name HTTP/1.1

Unless not appropriate, the default sort will be created_at DESC

An endpoint may also support multiple sort fields using the array syntax. Sort fields will be applied in the order specified.

Example

GET /connections?sort[]=name&sort[]=created_at HTTP/1.1

The sort order for each sort field will be ascending unless it is prefixed with a minus (U+002D HYPHEN-MINUS, “-“), in which case it will be descending.

GET /connections?sort[]=-created_at&sort[]=name HTTP/1.1

The above example should return the newest connections first. Any connections created on the same date will then be sorted by their name in ascending alphabetical order.

Filtering

Filtering of a resource collection based upon associations do so by allowing query parameters that combine the filter with the association name.

For example, the following is a request for all phone_numbers associated with a particular tag:

GET /phone_numbers?filter[tag]=tag_one HTTP/1.1

Filtering to values within an array can be achieved using query parameter array syntax:

GET /phone_numbers?filter[tag][]=tag_one&filter[tag][]=tag_two HTTP/1.1

Or an example using comments:

GET /comments?filter[tag]=tag_one,tag_two HTTP/1.1

Use the string null to filter on resources that don't have a particular value set:

GET /comments?filter[author]=null HTTP/1.1

To denote that a filter applies to an attribute of a nested object, use the dot notation.

For example, the phone numbers endpoint returns data in this format:

{
"id": "d460a653-8ee6-4061-ae9a-5b8a52539fb4",
"phone_number": "18005550199",
"record_type": "phone_number",
...
"voice": {
"e911_address_id" : "",
"connection_name" : false,
"inbound_call_recording_channels" : "single",
...
}
}

To filter by the connection name the path and request would look like:

GET /phone_numbers?filter[voice.connection_name]=conn_one HTTP/1.1

Similarly by connection ID:

GET /regions?filter[voice.connection_id]=d460a653-8pp6-4061-ae9a-5b8a57339fb4 HTTP/1.1

However, if name was a top-level key as in the below example:

{
"id": "d460a653-8pp6-4061-ae9a-5b8a57339fb4",
"name": "conn_one",
"record_type": "connection",
...
}

then the query would be:

GET /connections?filter[name]=conn_one HTTP/1.1

Complex filters

When filtering, you may need to specify more complex filters than equal to.

Options are:

  • eq
  • ne
  • gt
  • gte
  • lt
  • lte
  • starts_with
  • ends_with
  • contains

Return phone numbers purchased before 2018-02-21:

GET /phone_numbers?filter[purchased_at][lt]=2018-02-21 HTTP/1.1

If using eq then:

GET /phone_numbers?filter[purchased_at][eq]=2018-02-21 HTTP/1.1

and:

GET /phone_numbers?filter[purchased_at]=2018-02-21 HTTP/1.1

are equivalent.

To filter using string data use starts_with, ends_with or contains:

GET /phone_numbers?filter[voice.connection_name][contains]=conn HTTP/1.1

Webhooks

One application can provide another application with real-time updates via a webhook (also referred to as a web callback or HTTP push API). A webhook delivers data to other applications as it happens, meaning you get data immediately. In the past, APIs would typically need to poll for data very frequently to get it promptly. This makes webhooks much more efficient for both providers and consumers. The only drawback to webhooks is the difficulty of initially setting them up - this tutorial walks through how to consume webhooks.

Webhooks are sometimes referred to as “Reverse APIs,” as they give you what amounts to an API spec, and you must design an API for the webhook to use. The webhook will make an HTTP request to your app (typically a POST), and you will then be charged with interpreting it.

Telnyx can send webhook events that notify your application any time an event happens on your account. This is especially useful for events like receiving an SMS or MMS message and getting feedback on Call Control events. The messaging webhooks section goes into a bit more detail on how SMS and MMS webhooks work.

HTTP and HTTPS

  • Unsecure (HTTP) URLs are allowed for webhooks.
  • If HTTPS (TLS) is used, the certificate will be validated.

Event type naming

Where possible, events map to the C(R)UD operations, but this is certainly not always be applicable.

  • resource.created
  • resource.updated
  • resource.deleted

When the CRUD operations are not applicable, events will be named with past tense verbs.

  • message.created
  • message.deleted
  • message.delivered
  • message.received
  • porting_sub_request.ported
  • porting_sub_request.closed

Structure

The top-level structure of the webhook will vary by product but not by type of event received. For example, Call Control webhooks have a different top-level structure than Messaging webhooks however the webhook structure across all Call Control commands is consistent. The payload of the webhook contains the most valuable information for your application.

Call control top-level structure

{
"call_leg_id": "e97d8d4c-1a25-11cd-bc67-02620a0f6d42",
"call_session_id": "e97da4f0-1a25-11bd-909f-02620a0f6d642",
"event_timestamp": "2019-11-10T22:25:27.521992Z",
"metadata": {
"attempt": 1,
"delivered_to": "https://www.example.com/callback",
"event": {
"event_type": "call.initiated",
"id": "0ccc7b54-4df3-4bca-a65a-3da1ecc777f0",
"occurred_at": "2019-11-10T22:25:27.521992Z",
"payload": {
...
},
"record_type": "event"
},
"status": "delivered"
},
"name": "call.initiated",
"organization_id": null,
"type": "webhook",
"user_id": "901dbc74-1597-4d15-aad2-xxxxxxxxxxxx"
}
FIELD NAMEDESCRIPTION
call_leg_idID that is unique to the call and can be used to correlate webhook events.
call_session_idID that is unique to the call session and can be used to correlate webhook events.
event_timestampISO 8601 datetime of when the event occurred.
attemptThe number of attempts made to deliver the webhook. Multiple attempts will occur if your application does not send Telnyx HTTP 200 OK on receipt of the webhook.
delivered_toURL that the webhook was sent to.
event_typeThe type of event being delivered which also determines the structure of the payload.
idUnique ID of the event.
occurred_atISO 8601 datetime of when the event occurred.
record_typeWill always be event.
statusStatus of the webhook for debugging purposes.
nameEvent name.
organization_idID of the organization.

Messaging top-level structure

{
"data": {
"event_type": "message.finalized",
"id": "4ef8c3a6-4195-4389-b3a6-38e3cb9eb4ae",
"occurred_at": "2019-11-10T22:30:14.148+00:00",
"payload": {
...
},
"record_type": "event"
},
"meta": {
"attempt": 1,
"delivered_to": "https://www.example.com/messaging"
}
}
FIELD NAMEDESCRIPTION
event_typeThe type of event being delivered which also determines the structure of the payload.
idUnique ID of the event.
occurred_atISO 8601 datetime of when the event occurred.
payloadThe main data for the event. The structure is denoted by the event_type.
record_typeWill always be event.
attemptThe number of attempts made to deliver the webhook. Multiple attempts will occur if your application does not send Telnyx a 2xx HTTP status code within 2s of receipt of the webhook.
delivered_toURL that the webhook was sent to.

Full call control example

{
"call_leg_id": "428c31b6-7af4-4bcb-b7f5-5013ef9657c1",
"call_session_id": "428c31b6-abf3-3bc1-b7f4-5013ef9657c1",
"event_timestamp": "2019-11-10T22:26:27.521992Z",
"metadata": {
"attempt": 1,
"delivered_to": "https://www.example.com/callback",
"event": {
"event_type": "call.answered",
"id": "0ccc7b54-4df3-4bca-a65a-3da1ecc777f0",
"occurred_at": "2019-11-10T22:26:27.521992Z",
"payload": {
"call_control_id": "v2:F5_vIJVqrosogeY_2L_JhCEHd2Dh-x4xz7tROTbh34tg6Zsk4JJc-w",
"call_leg_id": "428c31b6-7af4-4bcb-b7f5-5013ef9657c1",
"call_session_id": "428c31b6-abf3-3bc1-b7f4-5013ef9657c1",
"client_state": null,
"connection_id": "7267xxxxxxxxxxxxxx",
"from": "+8005550199",
"start_time": "2019-11-10T22:26:26.521992Z",
"to": "+8005550100"
},
"record_type": "event"
},
"status": "delivered"
},
"name": "call.answered",
"organization_id": null,
"type": "webhook",
"user_id": "901dbc74-1597-4d15-aad2-xxxxxxxxxxxx"
}

Responding to a webhook

To acknowledge receipt of a webhook, your endpoint should return a 2xx HTTP status code. Any other information returned in the request headers or request body is ignored. All response codes outside this range, including 3xx codes, will indicate to Telnyx that you did not receive the webhook. URL redirection or a "Not Modified" response will be treated as a failure.

Retries

Webhooks will be retried to each of the supplied URLs if your application does not respond in 2000 milliseconds.

Best practices

If your webhook script performs complex logic or makes network calls, it's possible the script would timeout before Telnyx sees its complete execution. For that reason, you may want to have your webhook endpoint immediately acknowledge receipt by returning a 2xx HTTP status code, and then perform the rest of its duties.

Webhook endpoints may occasionally receive the same event more than once. We advise you to guard against duplicated event receipts by making your event processing idempotent. One way of doing this is logging the events you've processed, and then not processing already-logged events. Additionally, we recommend verifying webhook signatures to confirm that received events are being sent from Telnyx.

Webhook signing

Telnyx signs the webhook events it sends to clients so that the authenticity of the request can be verified. Webhook signing in API V2 uses public key encryption. Telnyx stores a public-private key pair and uses the private key to sign the payload. The public key is available to you so that you can verify the request.

The public key can be viewed in the Mission Control Portal .

The signature for the payload is calculated by building a string that is the combination of the timestamp of when the request was initiated, the pipe | character and the JSON payload. The signature is then Base64 encoded.

Base64.encode64("#{timestamp}|#{payload}")

The signature (Base64 encoded) and the timestamp (in Unix format) are assigned to the request headers telnyx-signature-ed25519 and telnyx-timestamp respectively.

You can then use cryptographic libraries in your language of choice to verify the signature using the public key. For examples, please see:

Congrats, you're ready to build

Now you know how to harness the power of Telnyx APIs for your development projects. Sign up now and dive into our comprehensive documentation to start building seamless communication experiences with ease.

You can also find example projects to get you started on GitHub:

Your next innovation starts with Telnyx.

On this page