Set OTPMOCK_URL=https://api.otpmock.com in your test environment, point the Twilio client at it, and use your otpmock API key as the Twilio credential. Your application code doesn't change, and production keeps sending real SMS through Twilio.
Setup
The official SDK accepts a custom HTTP client. This one keeps every path and swaps the host, so both api.twilio.com and verify.twilio.com traffic reaches otpmock. Download it from https://otpmock.com/sdk/twilio-node-client.mjs.
import twilio from "twilio";
import { OtpMockHttpClient } from "./twilio-node-client.mjs";
export const sms = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN, {
httpClient: process.env.OTPMOCK_URL ? new OtpMockHttpClient(process.env.OTPMOCK_URL) : undefined,
});Credentials. In the test environment, set TWILIO_AUTH_TOKEN to your otpmock API key. The Account SID can stay as it is; otpmock echoes it back.
What otpmock emulates
| Endpoint | What it does |
|---|---|
POST /2010-04-01/Accounts/{AccountSid}/Messages.json | Programmable Messaging: send an SMS |
POST /v2/Services/{ServiceSid}/Verifications | Verify v2: start a verification (otpmock generates a 6-digit code) |
POST /v2/Services/{ServiceSid}/VerificationCheck | Verify v2: check a code (approved / pending, 5 attempts) |
Responses and errors follow Twilio's own format, so the SDK parses them as usual. Authentication failures and an exhausted monthly allowance also come back in Twilio's error shape.
Phone numbers
Send in E.164 (+15550142), as Twilio expects.
Read the code in your tests
const phone = otp.randomPhone();
const since = Date.now() - 5_000;
await page.getByRole("button", { name: "Send code" }).click(); // your app calls Twilio
const { code } = await otp.waitForCode(phone, { since });The otp helper is a single file: get it from the docs. Full walkthroughs: Playwright, Cypress.
Good to know
- Twilio's own test credentials only cover a few resources and not Verify; otpmock covers both Messaging and Verify.
FAQ
Does otpmock send real SMS through Twilio?
No. In the test environment your app's Twilio requests go to otpmock, which stores the message for 10 minutes and never contacts Twilio or any carrier. Production keeps using Twilio because otpmock is only enabled when OTPMOCK_URL is set.
Is the official twilio SDK supported?
Yes. otpmock's Twilio endpoints are tested end to end with the official twilio package for Node.js. Other languages work too if their Twilio client lets you change the API host.
Which Twilio APIs does otpmock support?
POST /2010-04-01/Accounts/{AccountSid}/Messages.json (Programmable Messaging: send an SMS); POST /v2/Services/{ServiceSid}/Verifications (Verify v2: start a verification (otpmock generates a 6-digit code)); POST /v2/Services/{ServiceSid}/VerificationCheck (Verify v2: check a code (approved / pending, 5 attempts)).
The free plan includes 100 messages a month. Using an AI coding assistant? Point it at otpmock.com/llms-full.txt.
Get a free API key