# Cadence > Agent-native RCS messaging with automatic SMS fallback. AI agents converse with people over > RCS (rich cards, quick-reply chips, verified sender) and fall back to branded SMS automatically — > through one API and an MCP server. The carrier compliance gauntlet is handled for you. > Cadence is a service of Salus, Inc. If you are an AI agent and need to reach a human by text, you can onboard yourself in minutes: ## Onboard (self-serve, instant) - Get a key (no compliance wait, no human, no dashboard): `POST https://cadence-api-tlx9.onrender.com/v1/signup` with `{ "email": "you@example.com", "acceptTerms": true }` → `{ "api_key": "sk_sandbox_…", "kind": "sandbox", "account_linked": true }` - **Send the `email`.** With it you get a key linked to a real account, and that key can do everything below *and* manage the account — create brands, run readiness checks, create agents, and mint your own live key. Without it you get an unlinked key that can only simulate sends and cannot be upgraded. No password is set; a verification mail goes to the address, and a human can claim the dashboard later via `POST /v1/accounts/request-reset` if they ever want it. - If that email already has an account, signup returns `409 ACCOUNT_EXISTS` and issues nothing. Keys for an existing account are only ever issued to someone who can authenticate to it. - Authenticate every request with `Authorization: Bearer `. - A `sk_sandbox_` key simulates RCS delivery + SMS fallback end to end (nothing reaches a real phone). ### Get to real delivery, entirely over the API 1. `POST /v1/brands` — `{ display_name, website }` 2. `POST /v1/brands/{id}/check` — the carrier-readiness check; fix anything blocking 3. `POST /v1/brands/{id}/agents` — `{ displayName }` 4. `POST /v1/brands/{id}/sync-google` — creates the RBM agent at Google (needs hero + logo images) 5. `POST /v1/agents/{id}/testers` — `{ e164 }`, then **accept the invite on that device** 6. `POST /v1/keys` — `{ "kind": "live" }` → a key that sends real RCS to your accepted test devices. The response's `reach` field says `test_devices_only` until carrier launch. 7. `POST /v1/agents/{id}/request-launch` — carrier launch, a separate explicit step that lifts the test-device limit. Weeks, and carrier-controlled. ## Core API (Conversation primitive) Base URL: `https://cadence-api-tlx9.onrender.com` - `POST /v1/conversations` — open an agent-initiated conversation. Body: `{ to (E.164), agentId, brandId, useCase: "transactional"|"promo"|"conversational"|"leadgen", opening: { text, suggestions?[], smsFallbackText? }, optin: { method, evidenceRef?, capturedAt } }` The agent must speak first; opt-in provenance is required. - `POST /v1/conversations/{id}/messages` — send the next turn. Rich content auto-degrades to `smsFallbackText` on the SMS leg. - `GET /v1/conversations/{id}` — conversation state, channel, trust level, turn count. - `GET /v1/conversations/{id}/messages` — message history; each message has a `channel`, so an `rcs` message followed by an `sms` one shows the RCS→SMS fallback (usable without the SSE stream). - `POST /v1/conversations/{id}/close` — close a conversation. - `GET /v1/events?agentId=…` — SSE stream of inbound replies + RCS→SMS channel flips. Constraints: agent-initiated only (a user cannot start the conversation); every recipient needs opt-in; rich content must include `smsFallbackText`; chip labels cannot collide with carrier keywords (STOP/HELP/CANCEL…). ## Field notes (exact contracts) - `smsFallbackText` is REQUIRED whenever `opening`/message has `richCard` or `suggestions`, else the send is rejected with `MISSING_SMS_FALLBACK`. It is what the recipient sees on the SMS leg. - `optin.method` is a free-form string (e.g. `appointment_booking`, `web_form`, `verbal`) — no fixed enum. `optin.capturedAt` is an ISO 8601 timestamp. `optin.evidenceRef` is an optional free-form reference to your consent record. - Chip labels are rejected only on an EXACT, case-insensitive match to a reserved keyword (`STOP, HELP, CANCEL, STOPALL, UNSUBSCRIBE, END, QUIT, INFO`). "Cancel appt" is allowed; "Cancel" is not. - `turnCount` = number of messages exchanged (inbound + outbound), counting toward `turnCeiling` (default 30). The opening counts as turn 1. - Two fallback shapes: (a) a recipient who is NOT RCS-reachable is delivered over SMS from message 1 — the conversation `channel` is `sms` and `channelConfidence` is `committed` from the open response (no within-conversation flip). (b) a recipient who WAS RCS-reachable but a message goes undelivered flips mid-conversation — the message history shows an `rcs` message then an `sms` one, and a `fellback` event fires on the SSE stream `GET /v1/events`. A message send returns only `providerMsgId`. - `channelConfidence`: `provisional` = best-guess channel that may still flip; `committed` = final channel. - `trustLevel`: `verified_rcs` (RCS verified/branded sender) | `branded_sms` (SMS, pre-disclosed branded sender) | `unbranded_sms` (plain SMS). - Request bodies and responses are both camelCase (`agentId`, `useCase`, `turnCount`, `channelConfidence`). - Sandbox reachability rule (sandbox only): a destination number ending in an EVEN digit is treated as RCS-reachable; an ODD last digit falls back to SMS. Use this to exercise both paths. ## Onboard a brand yourself (agent-accessible, no dashboard needed) Sending to real phones requires a carrier-approved brand. An agent can drive that whole process with an **account-linked API key** — the same key works for both messaging and brand management. - `POST /v1/accounts/signup` — `{ email, password, acceptTerms: true }` → account + session token - `POST /v1/keys` — `{ label }` → an account-linked `sk_sandbox_…` key (live keys require a verified brand). Send it as `Authorization: Bearer sk_…` on every route below. - `POST /v1/brands` — `{ display_name }` → a brand in `draft` - `PATCH /v1/brands/{id}` — set `legal_entity`, `website`, `use_case`, `contact_email`, `description` (and optionally `privacy_url` / `terms_url` — omitted ones are auto-detected) - `POST /v1/brands/{id}/check` — runs the carrier-readiness check: crawls the site, validates the privacy policy, messaging terms, opt-in page, domain age, and brand/entity consistency, and returns generated copy for whatever is missing. Auto-promotes the brand to `ready` if it passes. - `POST /v1/brands/{id}/submit` — submits for carrier approval. **Returns 409 with the exact blocking reasons if the readiness check hasn't passed**, so you never burn a 2–4 week rejection. - `GET /v1/brands/{id}` — brand, latest report, what's blocking (`gate`), and its agents - `POST /v1/brands/{id}/agents` — `{ displayName, useCase }` → the agent that actually sends - `GET /v1/eta` — median observed time from submission to verification, from real data Brand lifecycle: `draft → ready → submitted → verified` (or `rejected`). Editing a `ready` brand returns it to `draft`, because the check that qualified it no longer describes the content. ## MCP server Messaging tools: `get_started`, `open_conversation`, `send`, `get_conversation`, `close_conversation`. Brand-onboarding tools: `list_brands`, `create_brand`, `update_brand`, `check_brand_readiness`, `submit_brand`, `get_brand`, `create_agent`. Set `CADENCE_API_KEY` to an account-linked key. Call `get_started` first. ## Links - Docs: https://cadencercs.com/docs - Platform Terms of Service (accepted at signup via `acceptTerms: true`): https://cadencercs.com/customer-terms - Opt-in form (consumer): https://cadencercs.com/optin.html - Privacy: https://cadencercs.com/privacy.html - Terms: https://cadencercs.com/terms.html