# 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

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

| Argument   | Type       | Description                                              |
| :--------- | :--------- | :------------------------------------------------------- |
| `context`  | `object`   | Information about the current execution environment      |
| `event`    | `object`   | The request parameters passed into the Function          |
| `callback` | `function` | Function that completes execution and emits the response |

```js title="Handler method boilerplate" description="Twilio Function handler method boilerplate"
exports.handler = (context, event, callback) => {
  // Your application logic

  // Emit a response and stop execution.
  return callback();
};
```

## Context object

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.

### Helper methods

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

| Method              | Type               | Description                                                                                                                                                                                                                                                                             |
| :------------------ | :----------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `getTwilioClient()` | Twilio REST Helper | Returns an initialized [Twilio REST SDK](https://github.com/twilio/twilio-node) 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. |

```js title="Use built-in Twilio REST Helper to send an SMS Message" description="Example of using the built-in Twilio REST Helper"
exports.handler = (context, event, callback) => {
  // Access the pre-initialized Twilio REST client
  const twilioClient = context.getTwilioClient();

  // Determine message details from the incoming event, with fallback values
  const from = event.From || "+15095550100";
  const to = event.To || "+15105550101";
  const body = event.Body || "Ahoy, World!";

  twilioClient.messages
    .create({ to, from, body })
    .then((result) => {
      console.log("Created message using callback");
      console.log(result.sid);
      return callback();
    })
    .catch((error) => {
      console.error(error);
      return callback(error);
    });
};
```

### Environment variables

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.

```js title="Retrieve domain from default environment variables" description="Example of how to access the default environment variables"
exports.handler = (context, event, callback) => {
  // Check to see if the domain name is null
  const domain = context.DOMAIN_NAME || "No domain available";
  // Respond with the domain hosting this Function
  return callback(null, domain);
};
```

```js title="Retrieve environment variables" description="Example of how to access environment variables"
exports.handler = (context, event, callback) => {
  // Get the primary and secondary phone numbers, if set
  const primary =
    context.PRIMARY_PHONE_NUMBER || "There is no primary number";
  const secondary =
    context.SECONDARY_PHONE_NUMBER || "There is no secondary number";

  // Build the response object
  const response = {
    phone_numbers: {
      primary,
      backup: secondary,
    },
  };

  // Return the response object as JSON
  return callback(null, response);
};
```

## Event object

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.

### Webhook parameters

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:

```json
{
  "ToCountry": "US",
  "ToState": "CA",
  "SmsMessageSid": "SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "NumMedia": "0",
  "ToCity": "BOULEVARD",
  "FromZip": "",
  "SmsSid": "SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "FromState": "WA",
  "SmsStatus": "received",
  "FromCity": "",
  "Body": "Ahoy!",
  "FromCountry": "US",
  "To": "+15555555555",
  "ToZip": "91934",
  "NumSegments": "1",
  "MessageSid": "SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "AccountSid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "From": "+14444444444",
  "ApiVersion": "2010-04-01",
  "request": {
    "headers": { ... },
    "cookies": { ... }
  }
}
```

Refer to the dedicated [Messaging](/docs/messaging/guides/webhook-request#parameters-in-twilios-request-to-your-application) and [Voice](/docs/voice/twiml#request-parameters) webhook documentation for the full list of available properties.

> \[!NOTE]
>
> Webhook properties are always in [PascalCase](https://en.wikipedia.org/wiki/Camel_case#:~:text=PascalCase%20for%20upper%20camel%20case). Make sure you capitalize the first letter of commonly used variables, such as `From`.

```js title="Access webhook values from event" description="Example of how to access webhook values by name from the event object in a Function"
// !mark(6)
exports.handler = (context, event, callback) => {
  // Prepare a new messaging response object; no need to import Twilio
  const twiml = new Twilio.twiml.MessagingResponse();
  // Access incoming text information such as the sender and message body
  twiml.message({ to: context.MY_NUMBER }, `${event.From}: ${event.Body}`);
  // Return the TwiML as the second argument to `callback`
  return callback(null, twiml);
};
```

### Parameters from HTTP requests

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:

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

`event` is:

```json
{
  "firstName": "Rick",
  "age": "42",
  "request": {
    "headers": { ... },
    "cookies": { ... }
  }
}
```

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

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

`event` becomes:

```json
{
  "firstName": "Rick",
  "age": "42",
  "color": "orange",
  "request": {
    "headers": { ... },
    "cookies": { ... }
  }
}
```

> \[!WARNING]
>
> 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`.

> \[!NOTE]
>
> 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](/docs/serverless/functions-assets/functions/headers-and-cookies/access)
> documentation.

```js title="Return an Error Response" description="Example that returns an error with HTTP 500 Internal Server Error"
exports.handler = (context, event, callback) => {
  // Passing a single string or an Error object returns HTTP 500 Internal Server Error.
  return callback('Something went very, very wrong.');
};
```

```js title="Return a Simple Successful Response" description="Example that returns an empty HTTP 200 OK"
exports.handler = (context, event, callback) => {
  // If you pass neither an error nor a response, Functions returns HTTP 200 OK.
  return callback();
};
```

```js title="Return a Successful Plain-Text Response" description="Example that returns plain text with HTTP 200 OK"
exports.handler = (context, event, callback) => {
  // Passing a string returns HTTP 200 OK.
  return callback(null, 'This is fine');
};
```

```js title="Return a Successful JSON Response" description="Example that returns JSON with HTTP 200 OK"
exports.handler = (context, event, callback) => {
  // Build an object in any way you prefer.
  const response = { result: 'winner winner!' };
  // Returning a JavaScript object causes the runtime to serialize it to JSON
  // and set Content-Type: application/json automatically.
  return callback(null, response);
};
```

### Return TwiML

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.

```js title="Return a static Messaging Response to incoming text messages"
exports.handler = (context, event, callback) => {
  // Create a new MessagingResponse object.
  const twiml = new Twilio.twiml.MessagingResponse();
  // Use any of the Node.js SDK methods, such as message(), to compose the reply.
  twiml.message('Hello, World!');
  // Return the TwiML as the second argument to callback().
  // The runtime renders the response as XML.
  return callback(null, twiml);
};
```

```js title="Return a Voice Response that includes Say and Play verbs"
exports.handler = (context, event, callback) => {
  // Create a new VoiceResponse object.
  const twiml = new Twilio.twiml.VoiceResponse();

  // Webhook information is available as properties of the event object.
  const city = event.FromCity;
  const number = event.From;

  // Optionally change the voice, add template variables, play audio, and more.
  twiml.say({ voice: 'alice' }, `Never gonna give you up, ${city || number}`);
  twiml.play('https://demo.twilio.com/docs/classic.mp3');

  // Return the TwiML as the second argument to callback().
  // The runtime renders the response as XML.
  return callback(null, twiml);
};
```

## Global classes

In addition to the helpers provided through the `context`, `event`, and `callback` parameters, you can use several globally scoped classes without importing additional [Dependencies](/docs/serverless/functions-assets/functions/dependencies).

### Twilio

The global `Twilio` class is always available. Use it to create TwiML or [Access Tokens](/docs/iam/access-tokens) in your Function responses. For example:

```javascript
// Initialize TwiML without importing Twilio
const response = new Twilio.twiml.MessagingResponse();

// Work with other utilities, such as Access Tokens
const AccessToken = Twilio.jwt.AccessToken;
const SyncGrant = AccessToken.SyncGrant;
```

### Runtime

You can access the [Runtime Client](/docs/serverless/functions-assets/client) through the global `Runtime` object. The client provides helper methods for working with private Assets, other Functions, and the [Sync](/docs/sync) client. For example:

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

## Constructing a Response

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](#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:

```javascript
// Twilio is globally available in Functions; no import required
const response = new Twilio.Response();
```

### Twilio Response methods

| Method                         | Return type | Description                                                                                                                                                                                          |
| :----------------------------- | :---------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `setStatusCode(int)`           | `self`      | Sets the HTTP status code for the response.                                                                                                                                                          |
| `setBody(mixed)`               | `self`      | Sets 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)` | `self`      | Adds a single header to the response. The first argument is the header name and the second argument is the header value.                                                                             |
| `setHeaders(object)`           | `self`      | Replaces all existing headers with the headers provided in the object. Each key is a header name and each value is the corresponding header value.                                                   |

```js title="Set a status code in a response" description="Example of setting a status code by using Twilio Response"
exports.handler = (context, event, callback) => {
  // Twilio is globally available in Functions
  const response = new Twilio.Response();

  // Set the status code to 204 No Content
  response.setStatusCode(204);

  return callback(null, response);
};
```

```js title="Build a plain text response" description="Example of building a plain-text response with Twilio Response"
exports.handler = (context, event, callback) => {
  // Twilio is globally available in Functions
  const response = new Twilio.Response();

  response
    // Set the status code to 200 OK
    .setStatusCode(200)
    // Set the response body
    .setBody('This is fine');

  return callback(null, response);
};
```

```js title="Build a JSON response" description="Example of building a JSON response with Twilio Response"
exports.handler = (context, event, callback) => {
  // Twilio is globally available in Functions
  const response = new Twilio.Response();

  response
    // Set the status code to 200 OK
    .setStatusCode(200)
    // Specify the content type
    .appendHeader('Content-Type', 'application/json')
    // Set the response body
    .setBody({
      everything: 'is alright',
    });

  return callback(null, response);
};
```

```js title="Set an HTTP header in a response" description="Example of setting a header by using Twilio Response"
exports.handler = (context, event, callback) => {
  // Twilio is globally available in Functions
  const response = new Twilio.Response();

  response
    // Set the status code to 301 Moved Permanently
    .setStatusCode(301)
    // Set the Location header for the redirect
    .appendHeader('Location', 'https://twilio.com');

  return callback(null, response);
};
```

```js title="Set multiple HTTP headers in a response" description="Example of setting multiple headers with Twilio Response"
exports.handler = (context, event, callback) => {
  // Twilio is globally available in Functions
  const response = new Twilio.Response();

  // Map of headers to set in a single call
  const headers = {
    'Access-Control-Allow-Origin': 'example.com',
    'Access-Control-Allow-Methods': 'GET, PUT, POST, DELETE, OPTIONS',
    'Access-Control-Allow-Headers': 'Content-Type',
  };

  response.setHeaders(headers);

  return callback(null, response);
};
```

## What's next?

You now understand the core components of writing a Function. For more details and hands-on material, review the [Function examples](/docs/serverless/functions-assets/quickstart).

Next, learn how [Function and Asset visibility](/docs/serverless/functions-assets/visibility) affects access to, and use of, your projects.
