[{"data":1,"prerenderedAt":857},["ShallowReactive",2],{"docs-nav":3,"content:\u002Fguides\u002Fmcp":78},[4,18,29,35,46,63,66,69,72,75],{"path":5,"title":6,"navTitle":6,"order":7,"subnav":8},"\u002Fapi\u002Fapi-tokens","API tokens",3,[9,12,15],{"title":10,"anchor":11},"Create an API key","create-an-api-key",{"title":13,"anchor":14},"List API keys","list-api-keys",{"title":16,"anchor":17},"Revoke an API key","revoke-an-api-key",{"path":19,"title":20,"navTitle":20,"order":21,"subnav":22},"\u002Fapi\u002Fbalances","Balances",4,[23,26],{"title":24,"anchor":25},"The balance object","the-balance-object",{"title":27,"anchor":28},"List balances","list-balances",{"path":30,"title":31,"navTitle":32,"order":33,"subnav":34},"\u002Fapi","API overview","Overview",1,null,{"path":36,"title":37,"navTitle":37,"order":38,"subnav":39},"\u002Fapi\u002Fsender-ids","Sender IDs",5,[40,43],{"title":41,"anchor":42},"The sender identity object","the-sender-identity-object",{"title":44,"anchor":45},"List sender IDs","list-sender-ids",{"path":47,"title":48,"navTitle":48,"order":49,"subnav":50},"\u002Fapi\u002Fsms","SMS",2,[51,54,57,60],{"title":52,"anchor":53},"The message object","the-message-object",{"title":55,"anchor":56},"Send an SMS","send-an-sms",{"title":58,"anchor":59},"Retrieve an SMS","retrieve-an-sms",{"title":61,"anchor":62},"Send bulk SMS","send-bulk-sms",{"path":64,"title":65,"navTitle":65,"order":49,"subnav":34},"\u002Fguides\u002Fauthentication","Authentication",{"path":67,"title":68,"navTitle":68,"order":7,"subnav":34},"\u002Fguides\u002Fbulk-sms","Bulk SMS",{"path":70,"title":71,"navTitle":71,"order":38,"subnav":34},"\u002Fguides\u002Fmcp","AI agents (MCP)",{"path":73,"title":74,"navTitle":74,"order":33,"subnav":34},"\u002Fguides\u002Fquickstart","Quickstart",{"path":76,"title":77,"navTitle":77,"order":21,"subnav":34},"\u002Fguides\u002Fwebhooks","Webhooks",{"id":79,"path":70,"title":71,"description":80,"navTitle":71,"order":38,"wide":81,"body":82,"seo":852,"stem":853,"extension":854,"meta":855,"navigation":856},"content\u002Fguides\u002Fmcp.md","Connect Claude, Cursor, or any MCP client to your Sendai account — six tools over hosted HTTP, authenticated with your API key, nothing to install.",false,{"type":83,"value":84,"toc":842},"minimark",[85,102,143,160,165,172,213,217,228,454,464,468,475,613,628,635,639,642,655,667,670,706,710,801,805,811,815,838],[86,87,88,89,96,97,101],"p",{},"Sendai runs a hosted ",[90,91,95],"a",{"href":92,"rel":93},"https:\u002F\u002Fmodelcontextprotocol.io",[94],"nofollow","MCP"," server, so an AI agent can send\nand track messages ",[98,99,100],"strong",{},"from your account",": the same API key, the same prepaid balance, the\nsame delivery record and message log as everything else you do. There is nothing to install\nand nothing to run — you configure a URL and a key, and every message the agent sends shows\nup in your dashboard exactly as if your own code had sent it.",[103,104,105,118],"table",{},[106,107,108],"thead",{},[109,110,111,115],"tr",{},[112,113,114],"th",{},"Host",[112,116,117],{},"Use",[119,120,121,133],"tbody",{},[109,122,123,130],{},[124,125,126],"td",{},[127,128,129],"code",{},"https:\u002F\u002Fmcp.sendai.co.zw",[124,131,132],{},"Production",[109,134,135,140],{},[124,136,137],{},[127,138,139],{},"https:\u002F\u002Fmcp-staging.sendai.co.zw",[124,141,142],{},"Staging",[144,145,146],"blockquote",{},[86,147,148,151,152,155,156,159],{},[98,149,150],{},"Agents send real messages."," ",[127,153,154],{},"send_sms"," and ",[127,157,158],{},"send_bulk_sms"," deliver to real handsets and\ncharge your prepaid balance, exactly as if you had called the REST API yourself. Both are\nmarked destructive in the MCP metadata, so well-behaved clients ask before running them —\nbut the enforcement that matters (approved sender, sufficient balance) happens server-side.",[161,162,164],"h2",{"id":163},"how-it-works","How it works",[86,166,167,168,171],{},"The server speaks MCP over plain ",[98,169,170],{},"HTTP",": your client POSTs JSON-RPC to the host and gets\nthe response back in the same request. There is no session and no state — each request\ncarries your API key as a bearer token, the server forwards it to the REST API for the life\nof that one request, and nothing about you is stored on it.",[173,174,175,183,202],"ul",{},[176,177,178,179,182],"li",{},"The endpoint answers on both the bare host and ",[127,180,181],{},"\u002Fmcp"," — either URL works.",[176,184,185,186,189,190,193,194,197,198,201],{},"It accepts ",[127,187,188],{},"POST"," only; a ",[127,191,192],{},"GET"," on the endpoint returns ",[127,195,196],{},"405",", and any other path is a\ndeliberate ",[127,199,200],{},"404"," so a mistyped URL fails loudly instead of half-working.",[176,203,204,205,208,209,212],{},"Authentication is a normal API key from ",[98,206,207],{},"Settings → Developer"," in the dashboard, sent as\n",[127,210,211],{},"Authorization: Bearer …",". No OAuth — browser and mobile connector UIs that expect an\nOAuth flow cannot connect; use a client that reads a config file.",[161,214,216],{"id":215},"connect-a-client","Connect a client",[86,218,219,220,222,223,227],{},"Create an API key in the dashboard under ",[98,221,207],{}," — ideally one dedicated to\nthe agent (see ",[90,224,226],{"href":225},"#security","Security",") — then add the server to your client:",[229,230,232,281,381],"code-group",{"title":231},"Connect",[233,234,240],"pre",{"className":235,"code":236,"filename":237,"language":238,"meta":239,"style":239},"language-bash shiki shiki-themes github-light github-dark","claude mcp add --transport http sendai https:\u002F\u002Fmcp.sendai.co.zw \\\n  --header \"Authorization: Bearer sk_your_key_here\"\n","Claude Code","bash","",[127,241,242,273],{"__ignoreMap":239},[243,244,246,250,254,257,261,264,267,270],"span",{"class":245,"line":33},"line",[243,247,249],{"class":248},"sScJk","claude",[243,251,253],{"class":252},"sZZnC"," mcp",[243,255,256],{"class":252}," add",[243,258,260],{"class":259},"sj4cs"," --transport",[243,262,263],{"class":252}," http",[243,265,266],{"class":252}," sendai",[243,268,269],{"class":252}," https:\u002F\u002Fmcp.sendai.co.zw",[243,271,272],{"class":259}," \\\n",[243,274,275,278],{"class":245,"line":49},[243,276,277],{"class":259},"  --header",[243,279,280],{"class":252}," \"Authorization: Bearer sk_your_key_here\"\n",[233,282,287],{"className":283,"code":284,"filename":285,"language":286,"meta":239,"style":239},"language-json shiki shiki-themes github-light github-dark","\u002F\u002F claude_desktop_config.json\n{\n  \"mcpServers\": {\n    \"sendai\": {\n      \"type\": \"http\",\n      \"url\": \"https:\u002F\u002Fmcp.sendai.co.zw\",\n      \"headers\": { \"Authorization\": \"Bearer sk_your_key_here\" }\n    }\n  }\n}\n","Claude Desktop","json",[127,288,289,295,301,309,316,330,343,363,369,375],{"__ignoreMap":239},[243,290,291],{"class":245,"line":33},[243,292,294],{"class":293},"sJ8bj","\u002F\u002F claude_desktop_config.json\n",[243,296,297],{"class":245,"line":49},[243,298,300],{"class":299},"sVt8B","{\n",[243,302,303,306],{"class":245,"line":7},[243,304,305],{"class":259},"  \"mcpServers\"",[243,307,308],{"class":299},": {\n",[243,310,311,314],{"class":245,"line":21},[243,312,313],{"class":259},"    \"sendai\"",[243,315,308],{"class":299},[243,317,318,321,324,327],{"class":245,"line":38},[243,319,320],{"class":259},"      \"type\"",[243,322,323],{"class":299},": ",[243,325,326],{"class":252},"\"http\"",[243,328,329],{"class":299},",\n",[243,331,333,336,338,341],{"class":245,"line":332},6,[243,334,335],{"class":259},"      \"url\"",[243,337,323],{"class":299},[243,339,340],{"class":252},"\"https:\u002F\u002Fmcp.sendai.co.zw\"",[243,342,329],{"class":299},[243,344,346,349,352,355,357,360],{"class":245,"line":345},7,[243,347,348],{"class":259},"      \"headers\"",[243,350,351],{"class":299},": { ",[243,353,354],{"class":259},"\"Authorization\"",[243,356,323],{"class":299},[243,358,359],{"class":252},"\"Bearer sk_your_key_here\"",[243,361,362],{"class":299}," }\n",[243,364,366],{"class":245,"line":365},8,[243,367,368],{"class":299},"    }\n",[243,370,372],{"class":245,"line":371},9,[243,373,374],{"class":299},"  }\n",[243,376,378],{"class":245,"line":377},10,[243,379,380],{"class":299},"}\n",[233,382,385],{"className":283,"code":383,"filename":384,"language":286,"meta":239,"style":239},"\u002F\u002F ~\u002F.cursor\u002Fmcp.json\n{\n  \"mcpServers\": {\n    \"sendai\": {\n      \"type\": \"http\",\n      \"url\": \"https:\u002F\u002Fmcp.sendai.co.zw\",\n      \"headers\": { \"Authorization\": \"Bearer sk_your_key_here\" }\n    }\n  }\n}\n","Cursor",[127,386,387,392,396,402,408,418,428,442,446,450],{"__ignoreMap":239},[243,388,389],{"class":245,"line":33},[243,390,391],{"class":293},"\u002F\u002F ~\u002F.cursor\u002Fmcp.json\n",[243,393,394],{"class":245,"line":49},[243,395,300],{"class":299},[243,397,398,400],{"class":245,"line":7},[243,399,305],{"class":259},[243,401,308],{"class":299},[243,403,404,406],{"class":245,"line":21},[243,405,313],{"class":259},[243,407,308],{"class":299},[243,409,410,412,414,416],{"class":245,"line":38},[243,411,320],{"class":259},[243,413,323],{"class":299},[243,415,326],{"class":252},[243,417,329],{"class":299},[243,419,420,422,424,426],{"class":245,"line":332},[243,421,335],{"class":259},[243,423,323],{"class":299},[243,425,340],{"class":252},[243,427,329],{"class":299},[243,429,430,432,434,436,438,440],{"class":245,"line":345},[243,431,348],{"class":259},[243,433,351],{"class":299},[243,435,354],{"class":259},[243,437,323],{"class":299},[243,439,359],{"class":252},[243,441,362],{"class":299},[243,443,444],{"class":245,"line":365},[243,445,368],{"class":299},[243,447,448],{"class":245,"line":371},[243,449,374],{"class":299},[243,451,452],{"class":245,"line":377},[243,453,380],{"class":299},[86,455,456,457,460,461,463],{},"The same JSON shape works in any client that reads an ",[127,458,459],{},"mcpServers"," config file — VS Code\nincluded. The dashboard's ",[98,462,207],{}," tab shows this exact configuration with a\ncopy button.",[161,465,467],{"id":466},"the-six-tools","The six tools",[86,469,470,471,474],{},"The tools are the same operations as the ",[90,472,473],{"href":30},"REST reference",", so everything an agent does\nis visible in your dashboard's messages log and reports.",[476,477,478,521,547,568,574,587],"properties",{},[479,480,482],"property",{"name":154,"type":481},"write · charges the account",[86,483,484,485,488,489,492,493,496,497,500,501,504,505,508,509,512,513,516,517,520],{},"Sends one SMS. ",[98,486,487],{},"Real message, real charge."," Args: ",[127,490,491],{},"to"," (recipient MSISDN in international\nformat, e.g. ",[127,494,495],{},"263771000000","), ",[127,498,499],{},"message"," (billed per GSM-7\u002FUCS-2 segment), ",[127,502,503],{},"from"," (an\napproved sender ID — an unapproved value is rejected with ",[127,506,507],{},"400","). Returns ",[127,510,511],{},"202"," — accepted,\npriced and queued, ",[98,514,515],{},"not delivered","; poll ",[127,518,519],{},"get_sms"," to confirm delivery.",[479,522,523],{"name":158,"type":481},[86,524,525,526,488,529,531,532,534,535,537,538,541,542,546],{},"Sends the same body to many recipients, priced as one send. ",[98,527,528],{},"Real messages, real\ncharges.",[127,530,491],{}," (array of MSISDNs), ",[127,533,499],{},", ",[127,536,503],{}," (approved sender ID), optional\n",[127,539,540],{},"webhook_url"," (a delivery callback applied to every message in the send). Rejected outright\nwith ",[543,544,545],"em",{},"insufficient balance"," when the prepaid balance does not cover it — never partially\ndelivered.",[479,548,550],{"name":519,"type":549},"read-only",[86,551,552,553,556,557,559,560,563,564,567],{},"Reads a message back by id. Args: ",[127,554,555],{},"id"," (from the ",[127,558,154],{}," response). ",[127,561,562],{},"status: success","\nmeans the carrier accepted or confirmed it — ",[127,565,566],{},"delivered_at"," non-null is the confirmed\nhandset delivery. There is no separate delivery-status field.",[479,569,571],{"name":570,"type":549},"get_balance",[86,572,573],{},"Prepaid wallet balance, one row per currency. No args. Worth calling before a bulk send —\nan underfunded send is rejected, not partially delivered.",[479,575,577],{"name":576,"type":549},"list_sender_ids",[86,578,579,580,583,584,586],{},"Sender identities on the account. No args. Rows with ",[127,581,582],{},"usable_as_from: true"," are valid ",[127,585,503],{},"\nvalues — an SMS identity that is both active and verified; the rest are listed so a rejected\nsender can be explained rather than guessed at.",[479,588,590],{"name":589,"type":549},"list_api_keys",[86,591,592,593,534,596,534,599,534,602,534,605,608,609,612],{},"API keys on the account — ",[127,594,595],{},"ID",[127,597,598],{},"Name",[127,600,601],{},"Active",[127,603,604],{},"CreatedAt",[127,606,607],{},"LastUsedAt",". ",[98,610,611],{},"Metadata\nonly, never key material."," No args.",[86,614,615,616,619,620,623,624,627],{},"One convenience the tools add over raw REST: every charge is decorated with a\n",[127,617,618],{},"charge_display"," sibling (",[127,621,622],{},"\"0.045 USD\"","), so an agent reads four cents as four cents rather\nthan as the API's raw ten-thousandths integer ",[127,625,626],{},"450",".",[86,629,630,631,634],{},"Deliberately ",[98,632,633],{},"not"," exposed: creating or revoking API keys. Minting a key returns the\nsecret once, in plaintext — over MCP it would land in the model's context and the client\ntranscript, and it would let an agent create credentials that outlive the session. Listing\nis safe (only metadata comes back), so only listing is here.",[161,636,638],{"id":637},"a-worked-example","A worked example",[86,640,641],{},"A typical first session — you ask the agent to check the balance, then send a verification\ncode and confirm it arrived:",[229,643,646],{"title":644,"label":645},"Session","\u002F\u002F sample",[233,647,653],{"className":648,"code":650,"filename":651,"language":652,"meta":239},[649],"language-text","\u002F\u002F sample — tool calls an agent makes for:\n\u002F\u002F \"Check my Sendai balance, then text the code 4821 to 263771000000.\"\n\n→ get_balance\n← [{ \"currency\": \"USD\", \"amount\": 184500, \"amount_display\": \"18.45 USD\" }]\n\n→ list_sender_ids\n← [{ \"from\": \"Sendai SMS\", \"channel\": \"sms\", \"usable_as_from\": true }]\n\n→ send_sms { \"to\": \"263771000000\", \"from\": \"Sendai SMS\",\n             \"message\": \"Your code is 4821\" }\n← { \"id\": \"0f9c1b3a-…\", \"status\": \"enqueued\", \"charge\": \"450\",\n    \"charge_display\": \"0.045 USD\", \"delivered_at\": null }   \u002F\u002F 202 — queued\n\n→ get_sms { \"id\": \"0f9c1b3a-…\" }                            \u002F\u002F a little later\n← { \"status\": \"success\", \"delivered_at\": \"2026-07-06T09:12:44Z\" }\n","Transcript","text",[127,654,650],{"__ignoreMap":239},[86,656,657,658,660,661,663,664,666],{},"That sequence exercises the whole delivery story, and teaches the agent the same lesson the\n",[90,659,74],{"href":73}," teaches you: ",[127,662,511],{}," is queued; ",[127,665,566],{}," is delivered.",[161,668,226],{"id":669},"security",[173,671,672,684,690,700],{},[176,673,674,677,678,680,681,683],{},[98,675,676],{},"Give the agent its own key."," A key is the only credential the server sees, and it scopes\nevery call to one account — a dedicated key means you can cut the agent off without\ntouching your services. Create and revoke keys under ",[98,679,207],{}," or with the\n",[90,682,6],{"href":5}," endpoints; revocation takes effect on the next request.",[176,685,686,689],{},[98,687,688],{},"Your key is never stored."," Each request's bearer key is forwarded to the REST API for\nthat one request and then gone — the MCP server keeps no key material and no per-tenant\nstate.",[176,691,692,151,695,155,697,699],{},[98,693,694],{},"The send tools spend money.",[127,696,154],{},[127,698,158],{}," are flagged destructive so\nclients prompt first, but treat any agent holding a key as able to send: fund the account\naccordingly and watch the messages log.",[176,701,702,705],{},[98,703,704],{},"Agents cannot mint keys."," Key creation and revocation are excluded from the tool\nsurface by design (see above).",[161,707,709],{"id":708},"troubleshooting","Troubleshooting",[103,711,712,722],{},[106,713,714],{},[109,715,716,719],{},[112,717,718],{},"Symptom",[112,720,721],{},"Cause and fix",[119,723,724,741,762,775,788],{},[109,725,726,732],{},[124,727,728,731],{},[127,729,730],{},"401"," Missing or malformed Authorization header",[124,733,734,735,738,739,627],{},"The key is absent, not in ",[127,736,737],{},"Authorization: Bearer sk_…"," form, or revoked. Check the header in your client config, and that the key is still active under ",[98,740,207],{},[109,742,743,748],{},[124,744,745,747],{},[127,746,507],{}," unknown or unapproved sender id",[124,749,750,751,753,754,756,757,759,760,627],{},"The ",[127,752,503],{}," value is not an approved sender ID on your account. Run ",[127,755,576],{}," and use a row with ",[127,758,582],{}," — see ",[90,761,37],{"href":36},[109,763,764,769],{},[124,765,766,768],{},[127,767,200],{}," No MCP endpoint at that path",[124,770,771,772,774],{},"The URL has a typo. The server answers on the bare host and ",[127,773,181],{}," only.",[109,776,777,782],{},[124,778,779,781],{},[127,780,196],{}," This endpoint accepts POST",[124,783,784,785,787],{},"The client is probing with ",[127,786,192],{},". Configure it as an HTTP (streamable) MCP server, not SSE.",[109,789,790,795],{},[124,791,792,794],{},[543,793,545],{}," on a bulk send",[124,796,797,798,800],{},"The prepaid balance does not cover the whole send. Check ",[127,799,570],{},", top up in the dashboard, retry — nothing was partially sent.",[161,802,804],{"id":803},"health","Health",[86,806,807,810],{},[127,808,809],{},"GET \u002Fhealth"," on the MCP host answers unauthenticated and says only that the server is up —\nnothing about your account.",[161,812,814],{"id":813},"next-steps","Next steps",[173,816,817,822,828,833],{},[176,818,819,820],{},"The endpoints behind the tools → ",[90,821,31],{"href":30},[176,823,824,825],{},"Delivery, confirmed → ",[90,826,58],{"href":827},"\u002Fapi\u002Fsms#retrieve-an-sms",[176,829,830,831],{},"Push instead of poll → ",[90,832,77],{"href":76},[176,834,835,836],{},"Key hygiene in full → ",[90,837,65],{"href":64},[839,840,841],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}",{"title":239,"searchDepth":49,"depth":49,"links":843},[844,845,846,847,848,849,850,851],{"id":163,"depth":49,"text":164},{"id":215,"depth":49,"text":216},{"id":466,"depth":49,"text":467},{"id":637,"depth":49,"text":638},{"id":669,"depth":49,"text":226},{"id":708,"depth":49,"text":709},{"id":803,"depth":49,"text":804},{"id":813,"depth":49,"text":814},{"title":71,"description":80},"guides\u002Fmcp","md",{},true,1786390037513]