Skip to contentSkip to navigationSkip to topbar
Page toolsOn this page
Looking for more inspiration?Visit the

Function Execution


The Twilio Function runtime environment is lightweight, giving you the flexibility to build and deploy code quickly. This topic explains how your code runs, which variables and utilities the environment provides, and how to return a valid response.

During a Function invocation, the following steps occur:

  1. Environment bootstrap: The runtime environment starts and initializes any resources that your Function code requires.
  2. Handler execution: The runtime executes the exports.handler method that your code defines and supplies the context, event, and callback parameters, along with several useful global utilities.
  3. Response emitted: When your code finishes, call callback() to emit the response. After callback() returns, the runtime terminates execution, including any asynchronous operations that are still running.

Handler method

handler-method page anchor

The handler method is the interface between Twilio Functions and your application logic. You can think of the handler method as the entry point to your application, similar to a main() function in Java or an __init__ method in Python.

Twilio Functions executes your handler method when it is ready to hand off control to your code. If your Function code does not contain a handler method, Twilio Functions returns an HTTP 500 error.

Handler arguments

handler-arguments page anchor
ArgumentTypeDescription
contextobjectInformation about the current execution environment
eventobjectThe request parameters passed into the Function
callbackfunctionFunction that completes execution and emits the response

Handler method boilerplate

handler-method-boilerplate page anchor

Twilio Function handler method boilerplate

1
exports.handler = (context, event, callback) => {
2
// Your application logic
3
4
// Emit a response and stop execution.
5
return callback();
6
};

Twilio Functions provides the context object as an interface between the current execution environment and the handler method. The context object gives you access to helper methods and to your environment variables.

The helper methods on context return pre-initialized utilities and clients. They retrieve configuration from your environment variables.

MethodTypeDescription
getTwilioClient()Twilio REST HelperReturns an initialized Twilio REST SDK(link takes you to an external page) client if account credentials are included in the Function. If credentials are not available, the method throws an error, which results in an HTTP 500 response unless your code handles the exception.

Use built-in Twilio REST Helper to send an SMS Message

use-built-in-twilio-rest-helper-to-send-an-sms-message page anchor

Example of using the built-in Twilio REST Helper

1
exports.handler = (context, event, callback) => {
2
// Access the pre-initialized Twilio REST client
3
const twilioClient = context.getTwilioClient();
4
5
// Determine message details from the incoming event, with fallback values
6
const from = event.From || "+15095550100";
7
const to = event.To || "+15105550101";
8
const body = event.Body || "Ahoy, World!";
9
10
twilioClient.messages
11
.create({ to, from, body })
12
.then((result) => {
13
console.log("Created message using callback");
14
console.log(result.sid);
15
return callback();
16
})
17
.catch((error) => {
18
console.error(error);
19
return callback(error);
20
});
21
};

Use environment variables to separate code from configuration. This approach keeps your code portable and lets you change configuration without redeploying.

For more details and examples, see the Environment variables documentation.

Retrieve domain from default environment variables

retrieve-domain-from-default-environment-variables page anchor

Example of how to access the default environment variables

1
exports.handler = (context, event, callback) => {
2
// Check to see if the domain name is null
3
const domain = context.DOMAIN_NAME || "No domain available";
4
// Respond with the domain hosting this Function
5
return callback(null, domain);
6
};

Retrieve environment variables

retrieve-environment-variables page anchor

Example of how to access environment variables

1
exports.handler = (context, event, callback) => {
2
// Get the primary and secondary phone numbers, if set
3
const primary =
4
context.PRIMARY_PHONE_NUMBER || "There is no primary number";
5
const secondary =
6
context.SECONDARY_PHONE_NUMBER || "There is no secondary number";
7
8
// Build the response object
9
const response = {
10
phone_numbers: {
11
primary,
12
backup: secondary,
13
},
14
};
15
16
// Return the response object as JSON
17
return callback(null, response);
18
};

The event object contains the request parameters and headers passed into your Function. POST and GET parameters are merged into the same object. For POST requests, you can send either form-encoded parameters or JSON documents; both formats populate the event object.

The specific values available on event depend on the context in which your Function is invoked and the parameters it receives. The following sections describe common use cases.

If the Function acts as the webhook for an incoming SMS or voice call, event contains a predefined set of parameters related to the phone number. Examples include event.From, which resolves to the E.164-formatted phone number, and event.Body, which returns the text of an incoming SMS.

An incoming message produces an event object similar to the following:

1
{
2
"ToCountry": "US",
3
"ToState": "CA",
4
"SmsMessageSid": "SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
5
"NumMedia": "0",
6
"ToCity": "BOULEVARD",
7
"FromZip": "",
8
"SmsSid": "SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
9
"FromState": "WA",
10
"SmsStatus": "received",
11
"FromCity": "",
12
"Body": "Ahoy!",
13
"FromCountry": "US",
14
"To": "+15555555555",
15
"ToZip": "91934",
16
"NumSegments": "1",
17
"MessageSid": "SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
18
"AccountSid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
19
"From": "+14444444444",
20
"ApiVersion": "2010-04-01",
21
"request": {
22
"headers": { ... },
23
"cookies": { ... }
24
}
25
}

Refer to the dedicated Messaging and Voice webhook documentation for the full list of available properties.

(information)

Webhook parameter naming

Webhook properties are always in PascalCase(link takes you to an external page). Make sure you capitalize the first letter of commonly used variables, such as From.

Access webhook values from event

access-webhook-values-from-event page anchor

Example of how to access webhook values by name from the event object in a Function

1
exports.handler = (context, event, callback) => {
2
// Prepare a new messaging response object; no need to import Twilio
3
const twiml = new Twilio.twiml.MessagingResponse();
4
// Access incoming text information such as the sender and message body
5
twiml.message({ to: context.MY_NUMBER }, `${event.From}: ${event.Body}`);
6
// Return the TwiML as the second argument to `callback`
7
return callback(null, twiml);
8
};

Parameters from HTTP requests

parameters-from-http-requests page anchor

If the Function is executed in response to an HTTP request, the contents of event correspond to the request's query parameters and body (if any).

Given a Function with the URL http-7272.twil.io/response and the following request:

curl -X GET 'https://http-7272.twil.io/response?age=42&firstName=Rick'

event is:

1
{
2
"firstName": "Rick",
3
"age": "42",
4
"request": {
5
"headers": { ... },
6
"cookies": { ... }
7
}
8
}

For a POST request that includes query parameters and a JSON body:

1
curl -L -X POST 'https://http-7272.twil.io/response?age=42&firstName=Rick' \
2
-H 'Content-Type: application/json' \
3
--data-raw '{
4
"color": "orange"
5
}'

event becomes:

1
{
2
"firstName": "Rick",
3
"age": "42",
4
"color": "orange",
5
"request": {
6
"headers": { ... },
7
"cookies": { ... }
8
}
9
}
(warning)

POST request parameter precedence

For a POST request, query parameters and any JSON in the request body are merged into the same object. If a property such as age appears in both places, the value from the JSON body takes precedence and overwrites the value from the query string in event.

(information)

Accessing headers and cookies in the event object

The event object also contains a nested request object with headers and cookies. To learn how to use these values, see the accessing headers and cookies documentation.

Return an Error Response

return-an-error-response page anchor

Example that returns an error with HTTP 500 Internal Server Error

1
exports.handler = (context, event, callback) => {
2
// Passing a single string or an Error object returns HTTP 500 Internal Server Error.
3
return callback('Something went very, very wrong.');
4
};

Return a Simple Successful Response

return-a-simple-successful-response page anchor

Example that returns an empty HTTP 200 OK

1
exports.handler = (context, event, callback) => {
2
// If you pass neither an error nor a response, Functions returns HTTP 200 OK.
3
return callback();
4
};

Return a Successful Plain-Text Response

return-a-successful-plain-text-response page anchor

Example that returns plain text with HTTP 200 OK

1
exports.handler = (context, event, callback) => {
2
// Passing a string returns HTTP 200 OK.
3
return callback(null, 'This is fine');
4
};

Return a Successful JSON Response

return-a-successful-json-response page anchor

Example that returns JSON with HTTP 200 OK

1
exports.handler = (context, event, callback) => {
2
// Build an object in any way you prefer.
3
const response = { result: 'winner winner!' };
4
// Returning a JavaScript object causes the runtime to serialize it to JSON
5
// and set Content-Type: application/json automatically.
6
return callback(null, response);
7
};

In addition to the standard response types, Functions supports generating and returning TwiML.
The callback function accepts TwiML objects—such as MessagingResponse and VoiceResponse—as its second argument.
When you pass TwiML in this way, the runtime serializes it to XML and sets the correct Content-Type header for you. You don't need to stringify the TwiML or manually specify headers.

Return a static Messaging Response to incoming text messages

return-a-static-messaging-response-to-incoming-text-messages page anchor
1
exports.handler = (context, event, callback) => {
2
// Create a new MessagingResponse object.
3
const twiml = new Twilio.twiml.MessagingResponse();
4
// Use any of the Node.js SDK methods, such as message(), to compose the reply.
5
twiml.message('Hello, World!');
6
// Return the TwiML as the second argument to callback().
7
// The runtime renders the response as XML.
8
return callback(null, twiml);
9
};

Return a Voice Response that includes Say and Play verbs

return-a-voice-response-that-includes-say-and-play-verbs page anchor
1
exports.handler = (context, event, callback) => {
2
// Create a new VoiceResponse object.
3
const twiml = new Twilio.twiml.VoiceResponse();
4
5
// Webhook information is available as properties of the event object.
6
const city = event.FromCity;
7
const number = event.From;
8
9
// Optionally change the voice, add template variables, play audio, and more.
10
twiml.say({ voice: 'alice' }, `Never gonna give you up, ${city || number}`);
11
twiml.play('https://demo.twilio.com/docs/classic.mp3');
12
13
// Return the TwiML as the second argument to callback().
14
// The runtime renders the response as XML.
15
return callback(null, twiml);
16
};

In addition to the helpers provided through the context, event, and callback parameters, you can use several globally scoped classes without importing additional Dependencies.

The global Twilio class is always available. Use it to create TwiML or Access Tokens in your Function responses. For example:

1
// Initialize TwiML without importing Twilio
2
const response = new Twilio.twiml.MessagingResponse();
3
4
// Work with other utilities, such as Access Tokens
5
const AccessToken = Twilio.jwt.AccessToken;
6
const SyncGrant = AccessToken.SyncGrant;

You can access the Runtime Client through the global Runtime object. The client provides helper methods for working with private Assets, other Functions, and the Sync client. For example:

1
const text = Runtime.getAssets()["/my-file.txt"].open();
2
console.log("Your file contents: " + text);

Sometimes your Function needs finer control over the response it returns. In those cases, use the Twilio Response object, which is available in the Function's global scope by default—you don't need to import Twilio.

With the Twilio Response object, you can set the status code, headers, and body of the response. Start by creating a new Twilio Response object, as shown in the following example:

1
// Twilio is globally available in Functions; no import required
2
const response = new Twilio.Response();
MethodReturn typeDescription
setStatusCode(int)selfSets the HTTP status code for the response.
setBody(mixed)selfSets the response body. Accepts a string or an object. If you set the body to any format other than plain text, make sure to specify the matching Content-Type header by calling appendHeader().
appendHeader(string, string)selfAdds a single header to the response. The first argument is the header name and the second argument is the header value.
setHeaders(object)selfReplaces all existing headers with the headers provided in the object. Each key is a header name and each value is the corresponding header value.

Set a status code in a response

set-a-status-code-in-a-response page anchor

Example of setting a status code by using Twilio Response

1
exports.handler = (context, event, callback) => {
2
// Twilio is globally available in Functions
3
const response = new Twilio.Response();
4
5
// Set the status code to 204 No Content
6
response.setStatusCode(204);
7
8
return callback(null, response);
9
};

Build a plain text response

build-a-plain-text-response page anchor

Example of building a plain-text response with Twilio Response

1
exports.handler = (context, event, callback) => {
2
// Twilio is globally available in Functions
3
const response = new Twilio.Response();
4
5
response
6
// Set the status code to 200 OK
7
.setStatusCode(200)
8
// Set the response body
9
.setBody('This is fine');
10
11
return callback(null, response);
12
};

Example of building a JSON response with Twilio Response

1
exports.handler = (context, event, callback) => {
2
// Twilio is globally available in Functions
3
const response = new Twilio.Response();
4
5
response
6
// Set the status code to 200 OK
7
.setStatusCode(200)
8
// Specify the content type
9
.appendHeader('Content-Type', 'application/json')
10
// Set the response body
11
.setBody({
12
everything: 'is alright',
13
});
14
15
return callback(null, response);
16
};

Set an HTTP header in a response

set-an-http-header-in-a-response page anchor

Example of setting a header by using Twilio Response

1
exports.handler = (context, event, callback) => {
2
// Twilio is globally available in Functions
3
const response = new Twilio.Response();
4
5
response
6
// Set the status code to 301 Moved Permanently
7
.setStatusCode(301)
8
// Set the Location header for the redirect
9
.appendHeader('Location', 'https://twilio.com');
10
11
return callback(null, response);
12
};

Set multiple HTTP headers in a response

set-multiple-http-headers-in-a-response page anchor

Example of setting multiple headers with Twilio Response

1
exports.handler = (context, event, callback) => {
2
// Twilio is globally available in Functions
3
const response = new Twilio.Response();
4
5
// Map of headers to set in a single call
6
const headers = {
7
'Access-Control-Allow-Origin': 'example.com',
8
'Access-Control-Allow-Methods': 'GET, PUT, POST, DELETE, OPTIONS',
9
'Access-Control-Allow-Headers': 'Content-Type',
10
};
11
12
response.setHeaders(headers);
13
14
return callback(null, response);
15
};

You now understand the core components of writing a Function. For more details and hands-on material, review the Function examples.

Next, learn how Function and Asset visibility affects access to, and use of, your projects.