Skip to contentSkip to navigationSkip to topbar
Rate this Page:

Assets


Twilio Assets is a static file hosting service that allows developers to quickly upload and serve the files needed to support their applications. With Twilio Assets you can host your files that support web, voice, and messaging applications. Twilio Assets is frequently used to host .mp3 audio files used in TwiML and Studio Flows, to serve images sent through MMS, or to store configuration used by Twilio Functions.


How Assets work

how-assets-work page anchor

Twilio provides you with three different types of Assets: public, protected, and private. The primary difference between the types is how they are accessed:

  • Public Assets are served over HTTPS from the Twilio CDN to ensure that they are highly available and secure, and are accessible by anyone with the Asset's URL.
  • Protected Assets are accessible via the Twilio CDN by URL as well, but require a valid Twilio request signature, or they will return a 403 error.
  • Private Assets are not accessible by URL or exposed to the web; instead, they are packaged with your Twilio Functions at build time.

If you would like to learn more about Asset visibility, we have a document that goes over the distinctions between public, protected, and private assets in greater detail.

(warning)

Warning about use of public Assets

Anyone with the URL to a public asset will be able to access it. Therefore, customers should be thoughtful about what data they include in a public asset.

(warning)

Metadata warning

Asset files are uploaded as is, with all metadata persisted. If your Asset files contain metadata, that will be stored with the file. An example would be EXIF metadata stored with an image. If you are making files available, please note that metadata is persisted and not removed/changed by the Assets product in any way.


Start by opening one of your existing Services, or by creating a new one. Once you're in the Functions Editor UI for your Service there are three points of interest:

  1. The Assets pane, which lists your Assets, their Visibility, a context menu for adjusting visibility, and another menu for other actions.
  2. The Add+ button which allows you to upload files as Assets, or create a new Asset.
  3. The Deploy All button, which will trigger an upload and deploy of your Assets (along with any Functions)
Assets UI points of interest.

Upload a file by clicking Add+ and then Upload File in the resulting menu, which will open up a standard file upload dialogue. Once you've selected a file or files, you'll be presented with options to set the visibility of each Asset, as well as the ability to remove or add other files. Click Upload to begin uploading your selection of files with the desired settings.

upload assets UI.

While the Asset has been uploaded, it will not be immediately accessible via a URL or in your Functions yet. This will be indicated by the gray circle next to the Asset's name. To deploy the Asset (and the rest of your Service), click the Deploy All button. After a brief period, the deployment will finish, and you should see a green check appear next to all deployed Assets.

Assets once deployed.

Get the URL of an Asset

get-the-url-of-an-asset page anchor

In general the URL of one of your Assets can be determined by taking the URL of your Service, for example https://example-1234.twil.io, and appending the name of your Asset.

In the case of an Asset such as example.json in that Service, it can be accessed at https://example-1234.twil.io/example.json.

For a point and click solution, the Functions Editor UI also provides two ways to copy the URL of an Asset to your clipboard:

  • Open the context menu of an Asset, and click Copy URL
  • Open an Asset in the Functions Editor, and click the Copy URL button that will appear below the content editor and above the logs pane
Copy an Asset url.

Public assets are publicly accessible once deployed, and can be used by referencing their URL. For example: given a Service with the URL of https://example-1234.twil.io and a public Asset named ahoy.mp3, the Asset will be available at https://example-1234.twil.io/ahoy.mp3.

The process for determining the URL of a protected Asset is the same as that of a public Asset. However, the Asset will only be accessible from Twilio code such as a Function, Studio Flow, or Flex.

For example, suppose we have an image grumpy.jpg that's been deployed to https://twilio-assets-1967.twil.io/grumpy.jpg. We would like to be able to send this image to users as part of an MMS, but have the file be inaccessible in all other cases. If the following code were deployed to a Function in the same Service and executed, the recipient will receive the image of grumpy cat, but anybody else trying to access the file by URL will be returned a 403 Forbidden error instead.

Use a protected Asset in a Function

use-a-protected-asset-in-a-function page anchor

_26
exports.handler = (context, event, callback) => {
_26
// Access the NodeJS Helper Library by calling context.getTwilioClient()
_26
const client = context.getTwilioClient();
_26
// Query parameters or values sent in a POST body can be accessed from `event`
_26
const from = event.From || '+15017122661';
_26
const to = event.To || '+15558675310';
_26
const body = event.Body || 'Ahoy, World!';
_26
_26
client.messages
_26
.create({
_26
to,
_26
from,
_26
body,
_26
// You will get a 403 if you try to view this image, but Twilio will
_26
// be able to access it and send it as part of the outgoing MMS
_26
mediaUrl: 'https://twilio-assets-1967.twil.io/grumpy.jpg',
_26
})
_26
.then((message) => {
_26
console.log(`Success! MMS SID: ${message.sid}`);
_26
return callback(null, message.sid);
_26
})
_26
.catch((error) => {
_26
console.error(error);
_26
return callback(error);
_26
});
_26
};

Similarly, suppose you have audio or messaging to include in your Studio Flow, but don't want that audio to be accessible to the entire internet. If the audio were uploaded as protected Asset, you could then reference its URL in the Studio Say/Play widget, and the audio will play for anybody that hits that part of your Flow.

For example, if the audio were a protected Asset deployed at https://twilio-assets-1967.twil.io/sensitive-message.mp3, it could be referenced in your Studio Flow as shown below:

Say/Play a protected Asset.

When Twilio builds your Function for deployment it will bundle any and all Private Assets that you have uploaded. This makes Private Assets perfect for storing sensitive configuration files, templates, and shared code that supports your application.

In order to access a private Asset, you will need to leverage the Runtime.getAssets method and open the file directly using either the open helper method, or by using helper methods from the fs module as shown in the following examples.

Read the content of a Private Asset

read-the-content-of-a-private-asset page anchor

Example of how to read the contents of a Private Asset


_11
exports.handler = (context, event, callback) => {
_11
// Access the open helper method for the Asset
_11
const openFile = Runtime.getAssets()['/my_file.txt'].open;
_11
_11
// Open the Private Asset and read the contents.
_11
// Calling open is equivalent to using fs.readFileSync(asset.filePath, 'utf8')
_11
const text = openFile();
_11
console.log('Your file contents: ' + text);
_11
_11
return callback();
_11
};

Serve an audio file from a Private Asset

serve-an-audio-file-from-a-private-asset page anchor

Example of how to serve an audio file from a Private Asset


_19
// Load the fs module
_19
const fs = require('fs');
_19
_19
exports.handler = (context, event, callback) => {
_19
// Get the path to the Private Asset
_19
const mp3Path = Runtime.getAssets()['/audio.mp3'].path;
_19
_19
// Read the file into the buffer and get its metadata
_19
const buffer = fs.readFileSync(mp3Path);
_19
const stat = fs.statSync(mp3Path);
_19
// Create a new Response object
_19
const response = new Twilio.Response();
_19
// Send the audio file in the response
_19
response.setBody(buffer);
_19
response.appendHeader('Content-Type', 'audio/mpeg');
_19
response.appendHeader('Content-Length', stat.size);
_19
_19
return callback(null, response);
_19
};


In some cases, such as when hosting an app with a landing page, you want the root URL of your Service to return an Asset in the browser. For example, you can visit root-asset-5802.twil.io/(link takes you to an external page) which serves static HTML solely via Assets.

To reproduce this behavior, you will need to use one of two special paths for a public Asset for your file (whether it be HTML, an image, or anything else).

You may rename an Asset's path to /, and that Asset will be served on requests to the root URL of your Service. In the Console UI, it would look like this:

Root Asset Path.

/assets/index.html

assetsindexhtml page anchor

This path applies only to HTML files. Renaming an HTML file's path to /assets/index.html will cause the Service to return that page on requests to the root URL of your Service. It would look like this in the Console UI:

Assets Index.html Path.

You can practice this yourself using the following index.html example code:


_24
<!DOCTYPE html>
_24
<html lang="en">
_24
<head>
_24
<meta charset="UTF-8" />
_24
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
_24
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
_24
<title>Hello Twilio Serverless!</title>
_24
</head>
_24
<body>
_24
<header><h1>Hello from Twilio Serverless!</h1></header>
_24
<main>
_24
<p>
_24
This page is a public Asset that can be accessed from the root URL of
_24
this Service!
_24
</p>
_24
</main>
_24
<footer>
_24
<p>
_24
Made with 💖 by your friends at
_24
<a href="https://www.twilio.com">Twilio</a>
_24
</p>
_24
</footer>
_24
</body>
_24
</html>

(information)

Info

If you want to deploy a root Asset using the Serverless Toolkit instead, you will need to create the /assets/index.html path within the existing assets/ folder that exists for your project.

The resulting path in your local filesystem will be /assets/assets/index.html, and the folder hierarchy will be as follows:


_10
.
_10
├── assets
_10
│ └── assets
_10
│ └── index.html
_10
├── functions
_10
└── package.json

All Builds have limitations on the maximum allowable file size and quantity of each Asset type that can be included:

Asset TypeMaximum SizeQuantity
Public25 MB1000 Assets
Private10 MB50 Assets
Protected25 MB1000 Assets

These limits apply only to individual Builds, so Assets used in a Build by a Subaccount won't affect the limits of other Subaccounts or the main Account.

Using Environments further expands your options, as you can create Builds containing different sets of Assets and deploy them to separate Environments.

(warning)

Warning

When using the Serverless API (either directly, via the Helper Libraries, or through the CLI), you can create more Assets and Asset Versions within a Service, for example, to have different Assets in different Environments. However, a particular Build can only include so many Assets, as indicated in the table above.

This flexibility is currently not supported by the Console UI. Every Asset listed in the UI will be included in the deployed Build, and you will be unable to upload Assets in excess of the stated limits.


Rate this Page: