{"_id":"@cadencercs/sdk","_rev":"2-04dfb186caa12c004cd3dc5118b012d2","name":"@cadencercs/sdk","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@cadencercs/sdk","version":"0.1.0","keywords":["rcs","rbm","sms","messaging","twilio","google-rbm","agent","ai-agent","conversational"],"author":{"name":"Salus, Inc."},"license":"MIT","_id":"@cadencercs/sdk@0.1.0","maintainers":[{"name":"admin-cadence","email":"admin@cadencercs.com"}],"homepage":"https://cadencercs.com/docs.html","bugs":{"url":"https://cadencercs.com/docs.html"},"dist":{"shasum":"90d38266a0f280c9eaa5133edf7290cc727ab38a","tarball":"https://registry.npmjs.org/@cadencercs/sdk/-/sdk-0.1.0.tgz","fileCount":7,"integrity":"sha512-7DuwF2rjtfMVuyOAs6UKYn1yDmoDSz/e77nE+VctWNp8BWha+UqqLs6mxyQZ0TVJLecjoJPxUePRIFB0ycIR2w==","signatures":[{"sig":"MEUCIQC9VCKrFKnObNJ64nynglR76e4LFNGop3sKi9OZxVIf8wIgQ5k3uBlOBcVMAbc5PdQifUqcALoT9sh6HsDcB5lJbEI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":38668},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"827200847339b676ca624f6580eb3c36dfb916a7","scripts":{"build":"rm -rf dist && tsc -p tsconfig.build.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"admin-cadence","email":"admin@cadencercs.com"},"repository":{"url":"git+https://github.com/dwixom/rcs-agent-mvp.git","type":"git","directory":"packages/sdk"},"_npmVersion":"10.9.4","description":"Agent-native RCS messaging with automatic SMS fallback. Open a conversation, get typed replies, and let the channel flip handle itself.","directories":{},"sideEffects":false,"_nodeVersion":"22.22.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.0_1787506370902_0.5031295993645424","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@cadencercs/sdk","version":"0.2.0","description":"Agent-native RCS messaging with automatic SMS fallback. Open a conversation, get typed replies, and let the channel flip handle itself.","license":"MIT","author":{"name":"Salus, Inc."},"homepage":"https://cadencercs.com/docs.html","repository":{"type":"git","url":"git+https://github.com/dwixom/rcs-agent-mvp.git","directory":"packages/sdk"},"bugs":{"url":"https://cadencercs.com/docs.html"},"keywords":["rcs","rbm","sms","messaging","twilio","google-rbm","agent","ai-agent","conversational"],"type":"module","sideEffects":false,"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"engines":{"node":">=18"},"publishConfig":{"access":"public"},"scripts":{"build":"rm -rf dist && tsc -p tsconfig.build.json","prepublishOnly":"npm run build"},"_id":"@cadencercs/sdk@0.2.0","gitHead":"eef0c9b0a11379a3f7f56a1302f319a3305aef14","_nodeVersion":"22.22.0","_npmVersion":"10.9.4","dist":{"integrity":"sha512-di/s0dKHxaJSH5CfsTc41aSYzdHbwHs2ZNpveUNDq6k/uBuq0DOst5NgFgSXncpLo9udzE+1I63uLaGPJohBlg==","shasum":"9621493574c5d427138753a862ca339c69c3a981","tarball":"https://registry.npmjs.org/@cadencercs/sdk/-/sdk-0.2.0.tgz","fileCount":7,"unpackedSize":48528,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCzO334jqh2VFE0n0cFoIMbxPsh8xwpJwDS8C1ZavCJ4AIgcrO0QY6SJSwSj6rm8MUTGXSgJWcgsov4JpW0gYuGcEo="}]},"_npmUser":{"name":"admin-cadence","email":"admin@cadencercs.com"},"directories":{},"maintainers":[{"name":"admin-cadence","email":"admin@cadencercs.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sdk_0.2.0_1787707927136_0.07361575083418193"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-23T17:32:50.702Z","modified":"2026-08-26T01:32:07.414Z","0.1.0":"2026-08-23T17:32:51.045Z","0.2.0":"2026-08-26T01:32:07.279Z"},"bugs":{"url":"https://cadencercs.com/docs.html"},"author":{"name":"Salus, Inc."},"license":"MIT","homepage":"https://cadencercs.com/docs.html","keywords":["rcs","rbm","sms","messaging","twilio","google-rbm","agent","ai-agent","conversational"],"repository":{"type":"git","url":"git+https://github.com/dwixom/rcs-agent-mvp.git","directory":"packages/sdk"},"description":"Agent-native RCS messaging with automatic SMS fallback. Open a conversation, get typed replies, and let the channel flip handle itself.","maintainers":[{"name":"admin-cadence","email":"admin@cadencercs.com"}],"readme":"# @cadencercs/sdk\n\nAgent-native RCS messaging with automatic SMS fallback.\n\nYour agent speaks first over RCS. If the recipient can't receive it, the message becomes a branded\nSMS and you're told it happened. Replies — chip taps and free text — come back typed, with the\ntapped option already resolved against the chips you actually sent.\n\nNo dependencies. Uses `fetch`, `ReadableStream` and `TextDecoder`, so it runs on Node 18+, Deno,\nBun, Cloudflare Workers and browsers.\n\nESM only. `import` works everywhere above; `require()` works on Node 22+ and needs `await import()`\non Node 18 and 20.\n\n```bash\nnpm install @cadencercs/sdk\n```\n\n## Get a key\n\n```ts\nimport { Messaging } from \"@cadencercs/sdk\";\n\nconst { apiKey } = await Messaging.signup();   // sandbox key, no account needed\nconst m = new Messaging({ apiKey });\n```\n\nA sandbox key simulates delivery end to end — nothing reaches a phone — so you can build the whole\nloop before anything is billable. Pass an email to `POST /v1/signup` instead if you want a key that\ncan also manage brands and go live.\n\n## Open a conversation\n\n```ts\nconst convo = await m.open({\n  to: \"+12025550123\",\n  agentId, brandId,\n  useCase: \"transactional\",\n  optin: { method: \"appointment_booking\", capturedAt },\n  opening: {\n    text: \"Your 3pm is confirmed. Reschedule?\",\n    suggestions: [\"Reschedule\", \"Cancel appt\", \"All good\"],\n    smsFallbackText: \"Your 3pm is confirmed. Reply 1 reschedule, 2 cancel, 3 all good.\",\n  },\n});\n```\n\n`smsFallbackText` is required whenever you send chips or a rich card — it's what the recipient reads\nif the message goes out over SMS, and the send is refused without it rather than silently losing the\ncontent.\n\n## Handle replies\n\n```ts\nconvo.onReply(async (intent) => {\n  // intent.optionLabel is resolved server-side against the chips you sent.\n  // Don't branch on intent.text — on RCS a tap arrives as the label, on SMS as the digit typed.\n  await convo.send({ text: reply(intent.optionLabel ?? intent.text) });\n});\n\nconvo.onFellback(() => {/* RCS → SMS: re-render rich UI as text */});\n\nawait m.listen();   // connects the event stream\n```\n\n`listen()` holds a connection open. **If your code runs somewhere that can't do that** — a Cloud\nFunction, a Lambda — don't use it. Either attach a `flow` when you open, and Cadence answers each\nreply itself with nothing of yours running, or register a delivery webhook and we POST each event to\nyou. Both are in the [docs](https://cadencercs.com/docs.html#receiving).\n\n## Typing, media, and messages that expire\n\n```ts\nawait convo.typing();                       // bubble appears; call it BEFORE the slow work\nconst answer = await model.respond(intent); // …seconds pass…\nawait convo.send({ text: answer });         // sending clears the bubble\n\nawait convo.send({\n  text: \"Your results are ready.\",\n  media: { url: \"https://cdn.example.com/chart.png\", altText: \"Weekly trend\" },\n  smsFallbackText: \"Your results are ready: https://example.com/r/abc\",\n  expiresIn: 3600,                          // stop trying after an hour\n});\n```\n\n- **`typing()` never throws.** SMS conversations have no bubble, sandbox keys reach no handset, and\n  calling it in a loop is rate limited — none of which mean your conversation is broken. The reason\n  comes back as `{ ok: false, reason }`. Call it right before the work, and skip it if the work\n  turns out to be fast: a bubble with no message behind it reads worse than no bubble at all.\n- **`media` needs `altText`** and an `https` URL — Google will not fetch plain http. Media *with*\n  text is repacked as a standalone card for you, because RBM's content message is a oneof and\n  sending both any other way drops the text in silence.\n- **`expiresIn` is honoured exactly on RCS and clamped on SMS.** RBM will hold a message for an\n  offline handset for up to 30 days; the SMS validity period tops out at 10 hours. Set it on\n  anything tied to a moment — a daily check-in that lands three days late gets answered against the\n  wrong day, and nothing downstream can tell.\n\n## Things that will bite you otherwise\n\n- **Chip labels can't be carrier keywords.** `\"Cancel\"` is intercepted by the network and never\n  reaches you; `\"Cancel appt\"` is fine. The send is refused with `RESERVED_KEYWORD_CHIP`.\n- **An action chip is not an answer.** A tap that dialled, opened a URL or shared a location\n  arrives with `intent.chipAction` set. Someone who tapped \"Call us\" has told you nothing about the\n  question you asked, so scoring it as a response records an answer they never gave.\n- **`optionIndex` is 1-based** — the same number the SMS fallback tells people to reply with. Prefer\n  `optionLabel` and never index at all.\n- **Opt-out is enforced for you.** A recipient who texts STOP is refused with\n  `RECIPIENT_OPTED_OUT`, on that conversation and on every later one, and re-asserting consent in a\n  request does not override it.\n- **Three operations are irreversible** and refuse with `409 CONFIRMATION_REQUIRED` until you\n  re-send with `{ \"confirm\": \"irreversible\" }`. `sync-google` also takes `{ \"dryRun\": true }`, which\n  creates nothing and shows exactly what would be sent.\n\n## Reference\n\n- Full API, in prose written for agents: <https://cadencercs.com/llms.txt>\n- OpenAPI 3.1 with schemas: <https://cadencercs.com/openapi.json>\n- Docs: <https://cadencercs.com/docs.html>\n\nMIT licensed. Cadence is a service of Salus, Inc.\n","readmeFilename":"README.md"}