[{"data":1,"prerenderedAt":897},["ShallowReactive",2],{"docs-nav":3,"content:\u002Fapi":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":30,"title":31,"description":80,"navTitle":32,"order":33,"wide":81,"body":82,"seo":892,"stem":893,"extension":894,"meta":895,"navigation":896},"content\u002Fapi\u002Findex.md","Base URLs, authentication, the two response conventions, error shapes, and how billing and delivery actually work — read this before writing a client.",false,{"type":83,"value":84,"toc":882},"minimark",[85,89,94,135,138,141,149,174,191,195,205,273,282,326,350,354,366,430,436,495,564,567,583,587,596,603,654,662,705,709,716,755,778,782,785,870,878],[86,87,88],"p",{},"The Sendai API is plain JSON over HTTPS, authenticated with an API key. This page covers the\nconventions that apply to every endpoint; each operation then has its own page with the exact\nrequest and response.",[90,91,93],"h2",{"id":92},"base-urls","Base URLs",[95,96,97,110],"table",{},[98,99,100],"thead",{},[101,102,103,107],"tr",{},[104,105,106],"th",{},"Host",[104,108,109],{},"Use",[111,112,113,125],"tbody",{},[101,114,115,122],{},[116,117,118],"td",{},[119,120,121],"code",{},"https:\u002F\u002Fapi.sendai.co.zw",[116,123,124],{},"Production",[101,126,127,132],{},[116,128,129],{},[119,130,131],{},"https:\u002F\u002Fstaging-api.sendai.co.zw",[116,133,134],{},"Staging — a build target for integration work",[86,136,137],{},"All paths in this reference are relative to the production host.",[90,139,65],{"id":140},"authentication",[86,142,143,144,148],{},"One mechanism: an ",[145,146,147],"strong",{},"API key"," as a bearer token on every request.",[150,151,156],"pre",{"className":152,"code":153,"language":154,"meta":155,"style":155},"language-http shiki shiki-themes github-light github-dark","Authorization: Bearer sk_live_4c8e…\n","http","",[119,157,158],{"__ignoreMap":155},[159,160,162,166,170],"span",{"class":161,"line":33},"line",[159,163,165],{"class":164},"s9eBZ","Authorization",[159,167,169],{"class":168},"szBVR",":",[159,171,173],{"class":172},"sZZnC"," Bearer sk_live_4c8e…\n",[86,175,176,177,180,181,187,188,190],{},"Create keys in the dashboard under ",[145,178,179],{},"Settings → Developer",", or with\n",[182,183,184],"a",{"href":5},[119,185,186],{},"POST \u002Fapi\u002Fv1\u002Fapi-tokens",". A key is valid until you revoke it. Full detail,\nincluding zero-downtime rotation, is in ",[182,189,65],{"href":64},".",[90,192,194],{"id":193},"two-response-conventions","Two response conventions",[86,196,197,198,204],{},"This is the one thing to get right before you write a client. ",[145,199,200,203],{},[119,201,202],{},"POST \u002Fapi\u002Fv1\u002Fsms"," returns the\nmessage object bare",", with no wrapper:",[150,206,210],{"className":207,"code":208,"language":209,"meta":155,"style":155},"language-json shiki shiki-themes github-light github-dark","{\n  \"id\": \"0f9c1b3a-6d2e-4a1b-9c3d-7e5f2a8b4c10\",\n  \"to\": \"263771000000\",\n  \"status\": \"enqueued\",\n  \"delivered_at\": null\n}\n","json",[119,211,212,218,233,245,257,267],{"__ignoreMap":155},[159,213,214],{"class":161,"line":33},[159,215,217],{"class":216},"sVt8B","{\n",[159,219,220,224,227,230],{"class":161,"line":49},[159,221,223],{"class":222},"sj4cs","  \"id\"",[159,225,226],{"class":216},": ",[159,228,229],{"class":172},"\"0f9c1b3a-6d2e-4a1b-9c3d-7e5f2a8b4c10\"",[159,231,232],{"class":216},",\n",[159,234,235,238,240,243],{"class":161,"line":7},[159,236,237],{"class":222},"  \"to\"",[159,239,226],{"class":216},[159,241,242],{"class":172},"\"263771000000\"",[159,244,232],{"class":216},[159,246,247,250,252,255],{"class":161,"line":21},[159,248,249],{"class":222},"  \"status\"",[159,251,226],{"class":216},[159,253,254],{"class":172},"\"enqueued\"",[159,256,232],{"class":216},[159,258,259,262,264],{"class":161,"line":38},[159,260,261],{"class":222},"  \"delivered_at\"",[159,263,226],{"class":216},[159,265,266],{"class":222},"null\n",[159,268,270],{"class":161,"line":269},6,[159,271,272],{"class":216},"}\n",[86,274,275,278,279,169],{},[145,276,277],{},"Every other endpoint wraps its payload"," in an envelope, with the payload under ",[119,280,281],{},"data",[150,283,285],{"className":207,"code":284,"language":209,"meta":155,"style":155},"{\n  \"status\": \"success\",\n  \"message\": \"request successful\",\n  \"data\": { }\n}\n",[119,286,287,291,302,314,322],{"__ignoreMap":155},[159,288,289],{"class":161,"line":33},[159,290,217],{"class":216},[159,292,293,295,297,300],{"class":161,"line":49},[159,294,249],{"class":222},[159,296,226],{"class":216},[159,298,299],{"class":172},"\"success\"",[159,301,232],{"class":216},[159,303,304,307,309,312],{"class":161,"line":7},[159,305,306],{"class":222},"  \"message\"",[159,308,226],{"class":216},[159,310,311],{"class":172},"\"request successful\"",[159,313,232],{"class":216},[159,315,316,319],{"class":161,"line":21},[159,317,318],{"class":222},"  \"data\"",[159,320,321],{"class":216},": { }\n",[159,323,324],{"class":161,"line":38},[159,325,272],{"class":216},[86,327,328,329,332,333,336,337,332,339,342,343,346,347,190],{},"So ",[119,330,331],{},"GET \u002Fapi\u002Fv1\u002Fsms\u002F{id}"," gives you ",[119,334,335],{},"data.status",", while ",[119,338,202],{},[119,340,341],{},"status","\nat the top level. Unwrapping ",[119,344,345],{},".data"," on a send returns ",[119,348,349],{},"undefined",[90,351,353],{"id":352},"errors","Errors",[86,355,356,357,359,360,362,363,169],{},"Branch on the HTTP status code — the error body comes in two shapes depending on the endpoint.\nThe two SMS read\u002Fwrite endpoints (",[119,358,202],{},", ",[119,361,331],{},") return an\n",[119,364,365],{},"error.type",[150,367,369],{"className":207,"code":368,"language":209,"meta":155,"style":155},"{\n  \"status\": \"\",\n  \"message\": \"not found\",\n  \"error\": { \"type\": \"err_not_found\", \"description\": \"the resource does not exist\" }\n}\n",[119,370,371,375,386,397,426],{"__ignoreMap":155},[159,372,373],{"class":161,"line":33},[159,374,217],{"class":216},[159,376,377,379,381,384],{"class":161,"line":49},[159,378,249],{"class":222},[159,380,226],{"class":216},[159,382,383],{"class":172},"\"\"",[159,385,232],{"class":216},[159,387,388,390,392,395],{"class":161,"line":7},[159,389,306],{"class":222},[159,391,226],{"class":216},[159,393,394],{"class":172},"\"not found\"",[159,396,232],{"class":216},[159,398,399,402,405,408,410,413,415,418,420,423],{"class":161,"line":21},[159,400,401],{"class":222},"  \"error\"",[159,403,404],{"class":216},": { ",[159,406,407],{"class":222},"\"type\"",[159,409,226],{"class":216},[159,411,412],{"class":172},"\"err_not_found\"",[159,414,359],{"class":216},[159,416,417],{"class":222},"\"description\"",[159,419,226],{"class":216},[159,421,422],{"class":172},"\"the resource does not exist\"",[159,424,425],{"class":216}," }\n",[159,427,428],{"class":161,"line":38},[159,429,272],{"class":216},[86,431,432,433,169],{},"…while bulk sends, the key endpoints, and every authentication failure return an ",[119,434,435],{},"error.code",[150,437,439],{"className":207,"code":438,"language":209,"meta":155,"style":155},"{\n  \"status\": \"error\",\n  \"message\": \"missing authentication\",\n  \"error\": { \"code\": \"UNAUTHORIZED\", \"description\": \"missing authentication\" }\n}\n",[119,440,441,445,456,467,491],{"__ignoreMap":155},[159,442,443],{"class":161,"line":33},[159,444,217],{"class":216},[159,446,447,449,451,454],{"class":161,"line":49},[159,448,249],{"class":222},[159,450,226],{"class":216},[159,452,453],{"class":172},"\"error\"",[159,455,232],{"class":216},[159,457,458,460,462,465],{"class":161,"line":7},[159,459,306],{"class":222},[159,461,226],{"class":216},[159,463,464],{"class":172},"\"missing authentication\"",[159,466,232],{"class":216},[159,468,469,471,473,476,478,481,483,485,487,489],{"class":161,"line":21},[159,470,401],{"class":222},[159,472,404],{"class":216},[159,474,475],{"class":222},"\"code\"",[159,477,226],{"class":216},[159,479,480],{"class":172},"\"UNAUTHORIZED\"",[159,482,359],{"class":216},[159,484,417],{"class":222},[159,486,226],{"class":216},[159,488,464],{"class":172},[159,490,425],{"class":216},[159,492,493],{"class":161,"line":38},[159,494,272],{"class":216},[95,496,497,507],{},[98,498,499],{},[101,500,501,504],{},[104,502,503],{},"Status",[104,505,506],{},"Meaning",[111,508,509,526,536,546],{},[101,510,511,516],{},[116,512,513],{},[119,514,515],{},"400",[116,517,518,519,522,523,190],{},"Malformed body, invalid id, or a ",[119,520,521],{},"from"," that is not an approved sender ID. Validation failures list fields in ",[119,524,525],{},"error.validation_errors",[101,527,528,533],{},[116,529,530],{},[119,531,532],{},"401",[116,534,535],{},"Missing, malformed, or revoked API key.",[101,537,538,543],{},[116,539,540],{},[119,541,542],{},"404",[116,544,545],{},"No such resource on your account.",[101,547,548,553],{},[116,549,550],{},[119,551,552],{},"422",[116,554,555,558,559,563],{},[119,556,557],{},"insufficient balance"," — your prepaid balance does not cover the send (documented on the ",[182,560,562],{"href":561},"\u002Fapi\u002Fsms#send-bulk-sms","bulk operation",").",[90,565,37],{"id":566},"sender-ids",[86,568,569,570,572,573,576,577,580,581,190],{},"The ",[119,571,521],{}," on a message is a ",[145,574,575],{},"sender ID"," — the name the recipient sees. Sender IDs are\napproved before use, so you cannot invent one at send time; an unapproved value is rejected\nwith ",[119,578,579],{},"400 unknown or unapproved sender id",". Yours are captured at registration and approved on\nthe network-operator side, usually in about 30 minutes. Manage them in the dashboard, or list\nthem over the API with ",[182,582,37],{"href":36},[90,584,586],{"id":585},"billing-and-segments","Billing and segments",[86,588,589,590,593,594,190],{},"Accounts are ",[145,591,592],{},"prepaid",". Each send places a hold on your balance, and a send that your balance\nwill not cover is rejected outright — never half-delivered. Check what you hold with\n",[182,595,20],{"href":19},[86,597,598,599,602],{},"SMS is billed ",[145,600,601],{},"per segment",", not per message:",[95,604,605,621],{},[98,606,607],{},[101,608,609,612,615,618],{},[104,610,611],{},"Encoding",[104,613,614],{},"When",[104,616,617],{},"Single segment",[104,619,620],{},"Per segment when concatenated",[111,622,623,637],{},[101,624,625,628,631,634],{},[116,626,627],{},"GSM-7",[116,629,630],{},"Every character is in the GSM-7 alphabet",[116,632,633],{},"160 chars",[116,635,636],{},"153 chars",[101,638,639,642,648,651],{},[116,640,641],{},"UCS-2",[116,643,644,647],{},[145,645,646],{},"Any"," character outside GSM-7 (an emoji, a curly quote, an accent)",[116,649,650],{},"70 chars",[116,652,653],{},"67 chars",[86,655,656,657,661],{},"One stray character switches the ",[658,659,660],"em",{},"whole"," message to UCS-2 and can more than double its cost.",[86,663,664,665,668,669,672,673,676,677,680,681,683,684,686,687,690,691,694,695,698,699,690,702,704],{},"The API returns the amount held as ",[119,666,667],{},"charge",", in ten-thousandths of ",[119,670,671],{},"charge_currency","\n(",[119,674,675],{},"10000"," == 1.00, so ",[119,678,679],{},"450"," == 0.045). Note the type differs by endpoint: ",[119,682,202],{},"\nreturns ",[119,685,667],{}," as a ",[145,688,689],{},"string"," (",[119,692,693],{},"\"450\"","), while ",[119,696,697],{},"POST \u002Fapi\u002Fv1\u002Fsms\u002Fbulk"," returns it as an\n",[145,700,701],{},"integer",[119,703,679],{},"). Coerce on the way in.",[90,706,708],{"id":707},"knowing-whether-it-arrived","Knowing whether it arrived",[86,710,711,712,715],{},"A ",[119,713,714],{},"202"," means Sendai accepted and queued your message — not that it arrived. Two fields track\nthe journey:",[717,718,719,744],"ul",{},[720,721,722,726,727,730,731,730,734,730,737,740,741,190],"li",{},[145,723,724],{},[119,725,341],{}," — ",[119,728,729],{},"created"," → ",[119,732,733],{},"enqueued",[119,735,736],{},"processing",[119,738,739],{},"success",", or ",[119,742,743],{},"failed",[720,745,746,726,751,754],{},[145,747,748],{},[119,749,750],{},"delivered_at",[119,752,753],{},"null"," until the carrier confirms delivery, then a timestamp.",[86,756,757,760,761,767,768,773,774,777],{},[119,758,759],{},"status: success"," means the send pipeline completed. ",[145,762,763,764,766],{},"Confirmed handset delivery is\n",[119,765,750],{}," being non-null"," — that is the only delivery signal the API exposes. Carrier\nconfirmation is asynchronous and can take seconds to hours, so poll\n",[182,769,771],{"href":770},"\u002Fapi\u002Fsms#retrieve-an-sms",[119,772,331],{},", or register a ",[182,775,776],{"href":76},"webhook"," and let\nSendai call you.",[90,779,781],{"id":780},"the-resources","The resources",[86,783,784],{},"The reference is organised by resource — one page each, with the object first and one\nsection per operation:",[95,786,787,797],{},[98,788,789],{},[101,790,791,794],{},[104,792,793],{},"Operation",[104,795,796],{},"Call",[111,798,799,810,820,830,848,859],{},[101,800,801,806],{},[116,802,803],{},[182,804,55],{"href":805},"\u002Fapi\u002Fsms#send-an-sms",[116,807,808],{},[119,809,202],{},[101,811,812,816],{},[116,813,814],{},[182,815,58],{"href":770},[116,817,818],{},[119,819,331],{},[101,821,822,826],{},[116,823,824],{},[182,825,61],{"href":561},[116,827,828],{},[119,829,697],{},[101,831,832,836],{},[116,833,834],{},[182,835,6],{"href":5},[116,837,838,841,842,841,845],{},[119,839,840],{},"POST"," \u002F ",[119,843,844],{},"GET",[119,846,847],{},"DELETE \u002Fapi\u002Fv1\u002Fapi-tokens",[101,849,850,854],{},[116,851,852],{},[182,853,20],{"href":19},[116,855,856],{},[119,857,858],{},"GET \u002Fapi\u002Fv1\u002Faccounts\u002F{id}\u002Fbalances",[101,860,861,865],{},[116,862,863],{},[182,864,37],{"href":36},[116,866,867],{},[119,868,869],{},"GET \u002Fapi\u002Fv1\u002Faccounts\u002F{id}\u002Fchannel-identities",[86,871,872,873,877],{},"Prefer a machine-readable contract? ",[182,874,876],{"href":875},"\u002Fopenapi.yaml","Download the OpenAPI document"," — the\nsame operations, ready for codegen and tooling.",[879,880,881],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}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 .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":155,"searchDepth":49,"depth":49,"links":883},[884,885,886,887,888,889,890,891],{"id":92,"depth":49,"text":93},{"id":140,"depth":49,"text":65},{"id":193,"depth":49,"text":194},{"id":352,"depth":49,"text":353},{"id":566,"depth":49,"text":37},{"id":585,"depth":49,"text":586},{"id":707,"depth":49,"text":708},{"id":780,"depth":49,"text":781},{"title":31,"description":80},"api\u002Findex","md",{},true,1786390037512]