Rate this page:

Mock API Generation with Twilio's OpenAPI Spec

The Twilio OpenAPI Spec is currently in BETA. The spec is expected to be accurate, but is currently in active development and is unsupported. If you've identified a mismatch between Twilio's API behavior and the specification, please open an issue.

Thanks to the rollout of Twilio’s OpenAPI specification, it is now possible to mock Twilio’s API locally and in your CI environments. Using a mock can save you time and money during development and testing.

What is a mock API server?

A mock API server allows you to emulate a real API (such as Twilio) locally, in your test environments, and/or even publicly. This mock server can receive requests, and will respond to them with static or dynamic data that simulates what the real API would return.

Why use a mock API server?

Developing and/or testing against a mock API server has a litany of benefits, including but not limited to:

  • Testing against Twilio costs money per request, while testing the same requests against a mock are effectively free.
  • A mock API server is typically stateless, so you can repeatedly test the same scenario and expect consistent results.
  • A locally running mock API server will have substantially faster response times than a live API service, which can add up to time savings both in local dev and especially for lengthy test suites. This will also allow you to develop while not connected to the internet, or in a situation where workplace policies may prevent your machine from connecting to Twilio.
  • A mock API server can simulate the behavior of endpoints which are still under development or in a private beta before they’ve been released, unblocking your own development process

Additionally, because the mock server in this example will be generated using Twilo’s OpenAPI Specification, each endpoint will validate requests and return data in the same format as the live Twilio API.

If you’re interested in taking advantage of these benefits, let’s proceed and learn how to set up the mock.

Mocking Twilio with the OpenAPI Specification and Prism


  • git
  • A javascript package manager, such as npm or yarn

Getting started

To begin, you'll want a local copy of Twilio’s OpenAPI specification. You may clone or download the spec from the GitHub repository. Using git, this would be accomplished like so:

git clone

In order to generate a mock server from these files, you will use the open source tool, Prism. What is Prism? According to the Prism documentation:

Prism is an open-source HTTP mock server that can mimic your API’s behavior as if you already built it. Mock HTTP servers are generated from your OpenAPI v2/v3 (formerly known as Swagger) documents.

Install Prism using your preferred package manager as shown below:

npm install -g @stoplight/prism-cli

# OR

yarn global add @stoplight/prism-cli

Preprocessing the OpenAPI Specification to work with Prism

As of the publishing of this article (April 19, 2021) there is an open issue with Prism regarding lengthy startup times with specifications such as Twilio’s API. The steps described in this section will hopefully not be necessary in the near future once the issue is resolved.

In order to remove some characters and patterns from the Twilio OpenAPI spec and prevent long startup times of the Prism server, you’re advised to perform some quick preprocessing to your intended file(s). In this article we’re focusing on Twilio’s v2010 API but this could apply to any other file of interest to you.

From the folder where you cloned the OpenAPI specification, perform the following commands:

cd twilio-oai/
  sed -i.bak '/pattern:/d' spec/json/twilio_api_v2010.json
  sed -i.bak 's/</Before/' spec/json/twilio_api_v2010.json
  sed -i.bak 's/>/After/' spec/json/twilio_api_v2010.json

Note that we’re modifying the JSON spec files. It’s also perfectly valid to use the YAML files as well, but for the sake of this article we will only be focusing on JSON.

Running the mock API server with Prism

Now that Prism is installed and the desired specification file has been preprocessed, the next step is to feed the specification to Prism so that it can generate the desired mock API server. From the twilio-oai directory, run the following command:

prism mock ./spec/json/twilio_api_v2010.json

After a short time you will see a trace similar to below. Once you see the green start line the server is running and listening for requests on the displayed port on localhost. Congratulations on starting your (maybe first) Prism mock server!

$ prism mock ./spec/json/twilio_api_v2010.json

 [CLI] ...  awaiting  Starting Prism...
 [CLI] i  info      GET
 [CLI] i  info      POST
 [CLI] i  info      GET
 [CLI] i  info      GET
 [CLI] i  info      POST
 [CLI]   start     Prism is listening on

Testing the mock API's validation layer

To validate that this is working as expected, let’s make some requests to the mock using curl in various forms to see some features of the mock in action.

First, leave the Prism mock server running in the terminal, and open a new tab or window depending on what’s allowed by your terminal. In the new terminal instance, let’s start with the example of querying the Twilio API for a list of messages sent by your account. If we try the following command and forget to include credentials, we will get the following error:

curl -s -D "/dev/stderr" | json_pp

Which will result in:

HTTP/1.1 401 Unauthorized
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: *
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: *
content-type: application/problem+json
WWW-Authenticate: Basic realm="*"
Content-Length: 327
Date: Wed, 31 Mar 2021 18:41:14 GMT
Connection: keep-alive
Keep-Alive: timeout=5

   "headers" : {
      "WWW-Authenticate" : "Basic realm=\"*\""
   "title" : "Invalid security scheme used",
   "detail" : "Your request does not fullfil the security requirements and no HTTP unauthorized response was found in the spec, so Prism is generating this error for you.",
   "status" : 401,
   "type" : ""

Also, if you take a peek at the Prism terminal instance, you will see some validation errors as below:

 [HTTP SERVER] get /2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Messages.json i  info      Request received
     [NEGOTIATOR] i  info      Request contains an accept header: */*
     [VALIDATOR]   warning   Request did not pass the validation rules
     [NEGOTIATOR]   debug     Unable to find a  response definition
     [NEGOTIATOR]   debug     Unable to find a 'default' response definition
 [HTTP SERVER] get /2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Messages.json   error     Request terminated with error: Invalid security scheme used

Notice here that the mock API server is actually validating the content of our request as the real Twilio API would, and is throwing a 401 error since credentials were not included in the request headers. Let’s fix that and try again once we’ve set some environment variables for Twilio credentials


curl -s -D "/dev/stderr" -u $TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN | json_pp

And the result will be:

HTTP/1.1 422 Unprocessable Entity
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: *
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: *
content-type: application/problem+json
Content-Length: 508
Date: Wed, 31 Mar 2021 18:41:43 GMT
Connection: keep-alive
Keep-Alive: timeout=5

   "title" : "Invalid request",
   "detail" : "Your request is not valid and no HTTP validation response was found in the spec, so Prism is generating this error for you.",
   "status" : 422,
   "validation" : [
         "message" : "should NOT be shorter than 34 characters",
         "severity" : "Error",
         "code" : "minLength",
         "location" : [
         "code" : "pattern",
         "location" : [
         "message" : "should match pattern \"^AC[0-9a-fA-F]{32}$\"",
         "severity" : "Error"
   "type" : ""

Note that this time the mock API server successfully validated the Account SID (in this case, MockSID) and found that it failed validation due to being the wrong length and for including invalid characters. The mock is doing a great job of emulating the real Twilio API so far!

Creating a successful request against the mock API server

If we cut the shenanigans and give the mock API server valid input and see what happens. Run the following command:

curl -s -D "/dev/stderr" -u $TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN | json_pp

and the output will be:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: *
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: *
Content-type: application/json
Content-Length: 551
Date: Wed, 31 Mar 2021 18:43:18 GMT
Connection: keep-alive
Keep-Alive: timeout=5

   "uri" : "",
   "next_page_uri" : "",
   "start" : 0,
   "first_page_uri" : "",
   "messages" : [
         "account_sid" : null,
         "num_segments" : null,
         "uri" : null,
         "subresource_uris" : null,
         "to" : null,
         "direction" : "inbound",
         "body" : null,
         "status" : "queued",
         "num_media" : null,
         "messaging_service_sid" : null,
         "api_version" : null,
         "error_code" : null,
         "from" : null,
         "error_message" : null,
         "date_updated" : null,
         "date_sent" : null,
         "date_created" : null,
         "sid" : null,
         "price_unit" : null,
         "price" : null
   "previous_page_uri" : "",
   "page_size" : 0,
   "page" : 0,
   "end" : 0

Success! This caused the mock server to return a 200 status as well as a JSON representation of a messages sent record. The Prism terminal instance should also reflect this success as shown:

 [HTTP SERVER] get /2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Messages.json i  info      Request received
     [NEGOTIATOR] i  info      Request contains an accept header: */*
     [VALIDATOR]   success   The request passed the validation rules. Looking for the best response
     [NEGOTIATOR]   success   Found a compatible content for */*
     [NEGOTIATOR]   success   Responding with the requested status code 200

Now that we’ve validated the mock API server is running and acting as expected, the next step is to make it so that our applications can communicate with the mock instead of sending requests to Twilio during development and testing.

Connecting applications to the Prism mock server

In order for you to leverage the Prism mock server during development of your application code, your Twilio client will need to be configured to redirect requests to the mock instead of Twilio itself. We’ll demonstrate how to accomplish this in Node.js below, but note that this is supported by all of the Twilio SDKs.

As mentioned in the Twilio Node documentation on custom HTTP clients, it’s possible to extend the behavior of the Twilio client by creating and passing in a custom implementation of the httpClient property. This is a perfect point in the codebase to add some code that will intercept requests and redirect them to the mock.

Starting from within a new empty directory, create a file for housing your custom Request Client. In this case let’s call it PrismClient.js.

Next, add the following example code:


        This PrismClient has a few key points:

        • It is constructed using a url for the locally running Prism instance as well as the existing Twilio RequestClient. Relying on the existing client means we can focus only on our custom behavior and not worry about fully re-creating the client.
        • The request method uses a regular expression to change the url of any request intended for Twilio to instead hit the same relative path, but on the Prism server instead.

        To use this new client, let's create an index.js in the same directory that sends a new SMS Message. Additionally, let's make sure the necessary dependencies are also available, such as the Twilio Node SDK:

        yarn init -y
        # Or if you prefer npm
        npm init -y
        # Once initialized, install dependencies!
        yarn add twilio dotenv
        # Or with npm
        npm i twilio dotenv
        # Create a new js file as well as a safe file for credentials and other sensitive variables to live in
        touch index.js .env

        Next, paste the following example code into index.js


              Note that we’re using best practices here, and creating the Twilio client using an API Key and Secret instead of directly using and potentially exposing your account’s auth token. If you’d like to learn more about API Keys and how to create one, please refer to the API Keys documentation!

              There are a few important things happening here of note:

              • This snippet is importing twilio, the custom PrismClient that we just created earlier, and destructuring out twilios internal RequestClient.
              • After declaring all variables being pulled in from the environment, we’re creating a new Twilio client using account credentials, and more importantly providing a custom httpClient as an option. The first argument is the url and port of the locally running Prism server, and the second is the Twilio RequestClient that was imported earlier.
              • Finally, we’re using this client to create and send an ‘Ahoy!’ SMS to the provided number. Once the message is queued, a log will be printed to the terminal along with the SID of that message (or we’ll safely catch and log just in case there’s some kind of error)

              Similarly, add the following variables to your .env file, being sure to use your own valid Account SID, API Key, Key Secret, and Twilio/Personal phone numbers.

              # .env

              Execute the example code by running node index.js.

              Once execution completes, you’ll see the following in your terminal:

              $ node example.js
              Message null sent!

              Don’t be alarmed by the null, this is simply a result of Prism successfully intercepting the request and returning null for the message sid!

              If you switch over to the terminal that is running Prism, you will see logs indicating a successful request/response cycle from Prism that returned a 201:

               [HTTP SERVER] post /2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Messages.json i  info      Request received
                   [NEGOTIATOR] i  info      Request contains an accept header: application/json
                   [VALIDATOR]   success   The request passed the validation rules. Looking for the best response
                   [NEGOTIATOR]   success   Found a compatible content for application/json
                   [NEGOTIATOR]   success   Responding with the requested status code 201

              This is an example of being able to run your code locally and verify that your integration with Twilio is correct. Note that the request to create and send an SMS never reached Twilio (you shouldn’t have received a text!), and instead was quickly and safely redirected to the mock instead.

              If your code uses the .list or .each methods that are available (such as client.messages.list(), running your code against the mock will cause it to throw an error. This is because the mocked next_page_uri value will be, which will cause the request to 404 against Prism.

              If your application makes calls to other subdomains than, this mocking solution will not intercept calls to those other subdomains yet. It’s possible to duplicate this process for other files one at a time (for example, mocking for but not, however we are still developing a solution to allow mocking for multiple subdomains at once.

              Making the mock server more portable with Docker

              If you want to share this mock with other developers on your team or make it easily reproducible in another environment such as your CI pipeline, packaging it up as a Docker container is highly advised. If you do not have Docker already installed, you can download and install it from here.

              Prism can be run as a container natively and there are examples in their documentation! We’re offering this manual solution because of the preprocessing that’s currently necessary for the twilio_api_v2010 file. In the future hopefully this will no longer be a necessary step.

              Creating and running the Dockerfile

              Starting from your current directory, create a new Dockerfile

              touch Dockerfile

              Edit the file, and paste in the following code:

              # Dockerfile
              # Choose the base image for us to build from.
              FROM alpine
              # Install dependencies.
              RUN apk update && \
               apk add --update git && \
               apk add --update npm && \
               npm i -g @stoplight/prism-cli
              # Clone the Twilio OpenAPI spec.
              RUN git clone
              # Perform preprocessing on the v2010 spec JSON file.
              RUN sed -i.bak '/pattern:/d' ./twilio-oai/spec/json/twilio_api_v2010.json && \
               sed -i.bak 's/</Before/' ./twilio-oai/spec/json/twilio_api_v2010.json && \
               sed -i.bak 's/>/After/' ./twilio-oai/spec/json/twilio_api_v2010.json
              # Expose the port that Prism runs on.
              EXPOSE 4010
              # Run Prism!
              CMD ["prism", "mock", "-h", "", "./twilio-oai/spec/json/twilio_api_v2010.json"]

              To build a new Docker container from this new Dockerfile, run the following:

              docker build --tag twilio-v2010-prism .

              Once the container is built (it may take some time depending on connection speeds), you can then run the newly created Docker container with the following command. Be sure to end any previously running Prism processes, otherwise the port will already be taken and the Docker container will fail to start:

              docker run -d -p 4010:4010 twilio-v2010-prism

              You can verify that your container is running using the following command and looking for the twilio-v2010-prism tag as below:

              docker ps

              You may also leverage the Docker Dashboard for a GUI-based way of viewing the running container and its logs.

              Now that you have a successfully running, Dockerized version of the Prism mock it’s time to verify it is working as expected. Run the node example again via `node example.js`, and once again you should see:

              $ node example.js
              Message null sent!

              If you consult the Docker Dashboard for your container, you should see logs indicating that a message request was received and that a 201 was returned, just as we saw for the non-Dockerized version of Prism.

              When you want to stop your container, first list out the running Docker images, then identify either the Container ID or Name of the running Prism container.

              $ docker ps
              CONTAINER ID   IMAGE                COMMAND                  CREATED         STATUS         PORTS                    NAMES
              18c164b21b92   twilio-v2010-prism   "prism mock -h 0.0.0..."   9 seconds ago   Up 8 seconds>4010/tcp   peaceful_thompson

              In this example, you could use either of these commands to stop the container:

              # Using the ID
              docker stop 18c164b21b92
              # Using the Name
              docker stop peaceful_thompson

              Simplify running the Dockerfile with Docker Compose

              If you’d like to further abstract away the process of building and running the Dockerfile directly, you have the option of configuring and using Docker Compose to simplify the process and reduce friction for other team members.

              First, create a new docker-compose.yml file:

              touch docker-compose.yml

              and paste in the following contents:

              # docker-compose.yml
              version: '3'
                    build: ./
                      - '4010:4010'

              You can now run the Dockerized Prism container with an even shorter command:

              docker-compose up -d
              # compare to:
              # docker run -d -p 4010:4010 <your specific build tag or image name>

              The Docker container will now be running and accessible on localhost:4010 just as before, and you can run the node example (node example.js) once more to verify.

              Sharing your Dockerfile

              Now that you have this Dockerfile set up, you have some options for sharing this with your team or org:

              • You could commit your Dockerfile and docker-compose.yml files to version control alongside the project(s) that leverage these files for testing.
              • You can refer to the Docker Hub documentation to learn more about pushing your image to Docker Hub (or your organization’s equivalent). This will make the image something that other developers in your team or org can pull and run.

              Rate this page:

              Need some help?

              We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd browsing the Twilio tag on Stack Overflow.

              Thank you for your feedback!

              We are always striving to improve our documentation quality, and your feedback is valuable to us. How could this documentation serve you better?

              Sending your feedback...
              🎉 Thank you for your feedback!
              Something went wrong. Please try again.

              Thanks for your feedback!

              Refer us and get $10 in 3 simple steps!

              Step 1

              Get link

              Get a free personal referral link here

              Step 2

              Give $10

              Your user signs up and upgrade using link

              Step 3

              Get $10

              1,250 free SMSes
              OR 1,000 free voice mins
              OR 12,000 chats
              OR more