{"_id":"@activescott/auth-sms-twilio","_rev":"3-263fb86054183bc3950c05a5214e47c1","name":"@activescott/auth-sms-twilio","dist-tags":{"latest":"1.0.0"},"versions":{"0.1.0":{"name":"@activescott/auth-sms-twilio","version":"0.1.0","keywords":["auth","authentication","sms","twilio","rcs","otp"],"author":{"name":"Scott Willeke"},"license":"MIT","_id":"@activescott/auth-sms-twilio@0.1.0","maintainers":[{"name":"activescott","email":"scott@willeke.com"}],"homepage":"https://github.com/activescott/auth#readme","bugs":{"url":"https://github.com/activescott/auth/issues"},"dist":{"shasum":"1f4c03984cacfb220c746679f24c87c3c500e1fc","tarball":"https://registry.npmjs.org/@activescott/auth-sms-twilio/-/auth-sms-twilio-0.1.0.tgz","fileCount":11,"integrity":"sha512-CIENSx3uYSpXV2tUm9F57aWA4aYC9VvoOd8sTgjWjV+v69em2gE6BCXpahqE+irR7wOJgZSUnCG2sO90esfiqA==","signatures":[{"sig":"MEQCIA1xWD5nntx1mEtkOtG3LKPM9LUDHOAD1duZW3T06YegAiAFUuwcChDmEzty7VT4PS1ByRNsFo2CtOs7ymimNBf6yw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":12911},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"9405943132469bb2401e9ef502a324bc4906f4e4","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"activescott","email":"scott@willeke.com"},"repository":{"url":"git+https://github.com/activescott/auth.git","type":"git","directory":"packages/auth-sms-twilio"},"_npmVersion":"10.9.4","description":"Twilio SMS/RCS transport for @activescott/auth-provider-sms","directories":{},"_nodeVersion":"22.21.1","_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.16","typescript":"^5.7.2","@types/node":"^22","@activescott/auth-provider-sms":"*"},"peerDependencies":{"@activescott/auth-provider-sms":">=0.1.0"},"_npmOperationalInternal":{"tmp":"tmp/auth-sms-twilio_0.1.0_1785610704645_0.6152047297235854","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@activescott/auth-sms-twilio","version":"0.1.1","keywords":["auth","authentication","sms","twilio","rcs","otp"],"author":{"name":"Scott Willeke"},"license":"MIT","_id":"@activescott/auth-sms-twilio@0.1.1","maintainers":[{"name":"activescott","email":"scott@willeke.com"}],"homepage":"https://github.com/activescott/auth#readme","bugs":{"url":"https://github.com/activescott/auth/issues"},"dist":{"shasum":"7cd28c7c31b6715327f6e25b2632de6c1f9ca7c0","tarball":"https://registry.npmjs.org/@activescott/auth-sms-twilio/-/auth-sms-twilio-0.1.1.tgz","fileCount":11,"integrity":"sha512-kNKpihhSFnp5bMHv1NzQSE6A6vBf+4p6tkEyhLX3HGK2o8dXdlPbGU1ohSOfd/5wZxhu5OC4SDRg1LsmkqkXyw==","signatures":[{"sig":"MEUCIG4C4Jm3uLivKhomBwMyLnsw58X6FthOmyBFB/X2t5UqAiEA+QqkEw5OeDDMA7YBE5K/VZw1UuSLIn3VgLKVzGGOiF0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@activescott%2fauth-sms-twilio@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":12919},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"5f74b6df0c31191887dcde7e4abc6e2f0dd62d9b","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:64f25665-d48a-446b-9dbd-da8a73009d1f"}},"repository":{"url":"git+https://github.com/activescott/auth.git","type":"git","directory":"packages/auth-sms-twilio"},"_npmVersion":"11.16.0","description":"Twilio SMS/RCS transport for @activescott/auth-provider-sms","directories":{},"_nodeVersion":"24.18.0","_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.16","typescript":"^5.7.2","@types/node":"^22","@activescott/auth-provider-sms":"*"},"peerDependencies":{"@activescott/auth-provider-sms":">=0.1.0"},"_npmOperationalInternal":{"tmp":"tmp/auth-sms-twilio_0.1.1_1785611652776_0.5167161373958358","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@activescott/auth-sms-twilio","version":"1.0.0","description":"Twilio SMS/RCS transport for @activescott/auth-provider-sms","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsc","dev":"tsc --watch","typecheck":"tsc --noEmit","test":"vitest run","prepublishOnly":"npm run build"},"keywords":["auth","authentication","sms","twilio","rcs","otp"],"author":{"name":"Scott Willeke"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/activescott/auth.git","directory":"packages/auth-sms-twilio"},"peerDependencies":{"@activescott/auth-provider-sms":">=0.1.0"},"devDependencies":{"@activescott/auth-provider-sms":"*","@types/node":"^22","typescript":"^5.7.2","vitest":"^4.0.16"},"gitHead":"43c5ff808ce2638b7f477287d56cc591d157b510","_id":"@activescott/auth-sms-twilio@1.0.0","bugs":{"url":"https://github.com/activescott/auth/issues"},"homepage":"https://github.com/activescott/auth#readme","_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-ANN195LVo4+VPCoJbAlPqUYQMxHmodJwl7OgPkep2JV37+fqbqef8tbKWaDUXeRpUnuy6+tI/poVeX0sd9X7+w==","shasum":"1fd5c6c2090b46934559c20e4f93bea45c9eb46f","tarball":"https://registry.npmjs.org/@activescott/auth-sms-twilio/-/auth-sms-twilio-1.0.0.tgz","fileCount":15,"unpackedSize":32841,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@activescott%2fauth-sms-twilio@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDZjwm7l2E7tKauD+A+zjRb9ykqKNf+Z9zF341CPOrjHgIga5Dx4e7MVXr5WDYdjzNlFVMJ7pQoaSR5/5+Vw60eL74="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:64f25665-d48a-446b-9dbd-da8a73009d1f"}},"directories":{},"maintainers":[{"name":"activescott","email":"scott@willeke.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/auth-sms-twilio_1.0.0_1786087433332_0.3450563463780383"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-01T18:58:24.509Z","modified":"2026-08-07T07:23:53.805Z","0.1.0":"2026-08-01T18:58:24.782Z","0.1.1":"2026-08-01T19:14:12.914Z","1.0.0":"2026-08-07T07:23:53.482Z"},"bugs":{"url":"https://github.com/activescott/auth/issues"},"author":{"name":"Scott Willeke"},"license":"MIT","homepage":"https://github.com/activescott/auth#readme","keywords":["auth","authentication","sms","twilio","rcs","otp"],"repository":{"type":"git","url":"git+https://github.com/activescott/auth.git","directory":"packages/auth-sms-twilio"},"description":"Twilio SMS/RCS transport for @activescott/auth-provider-sms","maintainers":[{"name":"activescott","email":"scott@willeke.com"}],"readme":"# @activescott/auth-sms-twilio\n\n[![npm version](https://img.shields.io/npm/v/@activescott/auth-sms-twilio.svg)](https://www.npmjs.com/package/@activescott/auth-sms-twilio)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nTwilio transports for [`@activescott/auth-provider-sms`](https://www.npmjs.com/package/@activescott/auth-provider-sms), both raw `fetch` — **zero dependencies**, running on any WinterTC-compatible runtime (Node, Cloudflare Workers, Deno, Bun):\n\n- **`TwilioVerifyTransport`** (Twilio Verify) — **quick setup, cheaper at low volume.** Twilio generates, sends, and checks the code through the [Verify API](https://www.twilio.com/docs/verify). No number to buy and **no 10DLC registration**: Verify \"procures and manages short codes, long codes, toll free, and global alpha-sender IDs\" on your behalf. Costs $0.05 per successful verification plus the channel fee (~4–6x a raw SMS), which at low sign-in volume is often less than 10DLC's fixed monthly fees.\n- **`TwilioMessagingTransport`** (Twilio Messaging) — **slow setup, cheaper at high volume.** You own the number and the code; sends through the Twilio Messages API. Cheapest per message (~$0.011–0.013 all-in for US SMS), but US traffic first needs your own [A2P 10DLC](https://www.twilio.com/docs/messaging/compliance/a2p-10dlc) brand and campaign registration — days to weeks, plus monthly fees per campaign and per number. Also the only path to RCS and custom message copy.\n\nSame texted-code experience either way; the difference is who owns the code and what it takes to start.\n\n## Usage\n\n```ts\nimport { SmsProvider } from \"@activescott/auth-provider-sms\"\nimport { TwilioMessagingTransport } from \"@activescott/auth-sms-twilio\"\n\nnew SmsProvider(\n  { appName: \"MyApp\" },\n  new TwilioMessagingTransport({\n    accountSid: process.env.TWILIO_ACCOUNT_SID!,\n    authToken: process.env.TWILIO_AUTH_TOKEN!,\n    // one of:\n    messagingServiceSid: process.env.TWILIO_SMS_MESSAGING_SERVICE_SID, // preferred\n    from: process.env.TWILIO_SMS_FROM, // an E.164 number you own in Twilio\n  }),\n)\n```\n\nOr with Verify, which replaces the sender configuration entirely:\n\n```ts\nimport { SmsProvider } from \"@activescott/auth-provider-sms\"\nimport { TwilioVerifyTransport } from \"@activescott/auth-sms-twilio\"\n\nnew SmsProvider(\n  {}, // the message text, code length, and expiry are Twilio's here\n  new TwilioVerifyTransport({\n    accountSid: process.env.TWILIO_ACCOUNT_SID!,\n    authToken: process.env.TWILIO_AUTH_TOKEN!,\n    serviceSid: process.env.TWILIO_VERIFY_SERVICE_SID!, // starts with VA\n  }),\n)\n```\n\n## Provisioning, step by step\n\n1. Create a Twilio account: https://www.twilio.com/try-twilio\n2. Grab the **Account SID** and **Auth Token** from https://console.twilio.com\n3. Buy an SMS-capable number (Console → Phone Numbers → Buy a Number).\n4. **US traffic**: register for [A2P 10DLC](https://www.twilio.com/docs/messaging/compliance/a2p-10dlc) or complete toll-free verification — unregistered numbers get filtered by carriers. Console → Regulatory Compliance.\n5. Set the env vars above; done.\n\nTroubleshooting:\n\n- A 401 ([error 20003](https://www.twilio.com/docs/errors/20003)) with credentials copied straight from the console usually means a **suspended account** (e.g. out of funds) — Twilio returns the same error as for wrong credentials. The suspension notice may only appear on the [project summary page](https://www.twilio.com/console/projects/summary).\n- **Message \"sent\" but never arrives**: the API accepts messages that carriers later filter, so check the [per-message delivery log](https://console.twilio.com/us1/monitor/logs/sms) — the only place the failure shows. Error [30034](https://www.twilio.com/docs/api/errors/30034) means the number isn't A2P 10DLC registered (step 4 above).\n\n## Verify, step by step\n\nSteps 3 and 4 above are what Verify removes:\n\n1. Create a Twilio account and grab the **Account SID** and **Auth Token** (steps 1–2 above).\n2. Console → **Develop → Verify → [Services](https://console.twilio.com/us1/develop/verify/services) → Create new**. The friendly name you give the service is what appears in the message (\"Your _MyApp_ verification code is …\"), so name it after your app.\n3. Copy the service SID (starts with `VA`) into `serviceSid`. That's it — no number, no campaign registration, nothing to wait on.\n\nOptions:\n\n| Option        | Default    | Description                                                                                                                                                                   |\n| ------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `channel`     | `\"sms\"`    | `\"sms\"`, `\"call\"`, `\"whatsapp\"`, or `\"email\"`                                                                                                                                 |\n| `locale`      | (Twilio's) | Message language, e.g. `\"es\"`                                                                                                                                                 |\n| `appHash`     | (off)      | Android [SMS Retriever](https://developers.google.com/identity/sms-retriever/overview) hash — Verify's equivalent of the provider's `webOtpDomain`, which does not apply here |\n| `templateSid` | (off)      | A message template (starts with `HJ`) configured in the Verify service                                                                                                        |\n\nVerification outcomes are in the [Verify log](https://console.twilio.com/us1/monitor/logs/verify-logs), not the SMS delivery log. Twilio's own rate limits and fraud guards (SMS pumping protection) are configured per service in that console section.\n\nTroubleshooting: a 401 carrying `\"code\": 20003` and a message like _\"account AC… with status 4 is not active\"_ means the **account** is suspended or closed (often unfunded or an expired trial), not that the credentials are wrong — Twilio returns 20003 for both. Check the [project summary page](https://www.twilio.com/console/projects/summary); no Verify request will succeed until the account is active.\n\nCost note: you're billed $0.05 on **successful** verification, so failed and abandoned attempts cost only the channel fee. The provider counts attempts before calling Twilio, so a guesser can trigger at most `otp.maxAttempts` checks per challenge.\n\n## RCS (branded, richer messages)\n\nTwilio delivers RCS through a **Messaging Service** with an onboarded RCS sender — same Messages API, zero code changes here:\n\n1. Create a Messaging Service (Console → Messaging → Services) and add your number to its sender pool.\n2. Onboard an RCS sender to it: https://www.twilio.com/docs/rcs — brand/carrier approval is manual and takes **days to weeks**.\n3. Use `messagingServiceSid` (not `from`). Twilio sends RCS where the recipient supports it and falls back to SMS automatically.\n\n## Testing\n\nThree levels, cheapest first:\n\n1. **No Twilio at all** (recommended for app development): use the provider's `ConsoleTransport` — codes print to the server console. The [example app](https://github.com/activescott/auth/tree/main/examples/react-router) does this by default and its e2e suite captures messages at the `SmsTransport` seam, so full sign-in flows are tested without any SMS gateway.\n2. **Exercise the real API without sending or charging**: Twilio's [test credentials](https://www.twilio.com/docs/iam/test-credentials) — a separate SID/token pair with magic numbers (`+15005550006` succeeds; others reproduce specific errors like invalid-number 21211). Note test-credential messages are never delivered and don't appear in the console's message logs, so they verify your API integration and error handling, not message content or delivery.\n3. **Real delivery**: live credentials and a registered number; verify content and delivery in the [per-message log](https://console.twilio.com/us1/monitor/logs/sms).\n\nFor unit tests, the constructor accepts an injectable `fetch` (this package's own tests use it; apps usually don't need it):\n\n```ts\nnew TwilioMessagingTransport({ accountSid, authToken, from, fetch: fetchMock })\nnew TwilioVerifyTransport({\n  accountSid,\n  authToken,\n  serviceSid,\n  fetch: fetchMock,\n})\n```\n\nLevel 1 is the same for Verify: develop against `ConsoleTransport` and swap the transport at the edge of your app, since a Verify integration cannot be exercised end to end without billable verifications.\n","readmeFilename":"README.md"}