{"openapi":"3.1.0","info":{"title":"Kisoasms API","version":"1","description":"Send and receive SMS through Android phones your organization owns. Authenticate every request with an organization API key."},"components":{"securitySchemes":{"ApiKey":{"type":"http","scheme":"bearer","description":"An organization API key, sent as `Authorization: Bearer kso_live_…`."}},"schemas":{"DeviceList":{"type":"object","properties":{"devices":{"type":"array","items":{"$ref":"#/components/schemas/Device"}}},"required":["devices"]},"Device":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"model":{"type":["string","null"]},"status":{"type":"string","enum":["online","stale","never_seen","revoked"]},"createdAt":{"type":"string","format":"date-time"},"revokedAt":{"type":["string","null"],"format":"date-time"},"revokedReason":{"type":["string","null"]},"lastSeenAt":{"type":["string","null"],"format":"date-time"},"battery":{"type":"object","properties":{"percent":{"type":["integer","null"]},"charging":{"type":["boolean","null"]}},"required":["percent","charging"]},"networkType":{"type":["string","null"]},"uptimeSeconds":{"type":["integer","null"]},"freeStorageBytes":{"type":["integer","null"]},"appVersion":{"type":["string","null"]},"outboundEnabled":{"type":"boolean","description":"Off: the phone stays paired and receives SMS, and sends nothing."},"draining":{"type":"boolean","description":"Maintenance: the phone finishes what it holds and claims nothing new."},"defaultSimSubscriptionId":{"type":["integer","null"]},"queueDepth":{"type":"integer","description":"Messages assigned to this phone and not yet sent."},"socket":{"type":"object","properties":{"connected":{"type":"boolean"},"lastChangedAt":{"type":["string","null"],"format":"date-time"}},"required":["connected","lastChangedAt"]},"inbound":{"$ref":"#/components/schemas/InboundCapability"},"sims":{"type":"array","items":{"$ref":"#/components/schemas/SimCard"}}},"required":["id","name","model","status","createdAt","revokedAt","revokedReason","lastSeenAt","battery","networkType","uptimeSeconds","freeStorageBytes","appVersion","outboundEnabled","draining","defaultSimSubscriptionId","queueDepth","socket","inbound","sims"]},"InboundCapability":{"anyOf":[{"type":"object","properties":{"state":{"type":"string","enum":["unlocked"]}},"required":["state"]},{"type":"object","properties":{"state":{"type":"string","enum":["locked"]},"reason":{"type":"string","enum":["revoked","not_reported","not_default_sms_app","stale"]}},"required":["state","reason"]}],"description":"Receiving SMS and recognizing mobile money need Kisoasms to be the default messaging app on the phone. Locked unless the phone reported holding that role within the last 45 minutes."},"SimCard":{"type":"object","properties":{"subscriptionId":{"type":"integer"},"slotIndex":{"type":["integer","null"]},"carrierName":{"type":["string","null"]},"displayName":{"type":["string","null"]},"phoneNumber":{"type":["string","null"],"description":"Often unavailable on Android; null is normal."},"countryIso":{"type":["string","null"]},"firstSeenAt":{"type":"string","format":"date-time"},"lastSeenAt":{"type":"string","format":"date-time"},"removedAt":{"type":["string","null"],"format":"date-time","description":"Set once a heartbeat stops reporting the card."}},"required":["subscriptionId","slotIndex","carrierName","displayName","phoneNumber","countryIso","firstSeenAt","lastSeenAt","removedAt"]},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized","forbidden","no_session","invalid_request","rate_limited","not_found","conflict","unsupported_media_type","clock_skew","no_device","invalid_transition","inbound_locked","internal_error"]},"message":{"type":"string"},"requestId":{"type":"string"}},"required":["code","message","requestId"]}},"required":["error"]},"UpdateDevice":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128},"draining":{"type":"boolean"},"outboundEnabled":{"type":"boolean"},"defaultSimSubscriptionId":{"type":["integer","null"],"minimum":0}}},"SendResult":{"type":"object","properties":{"batchId":{"type":"string"},"messages":{"type":"array","items":{"$ref":"#/components/schemas/Message"}}},"required":["batchId","messages"]},"Message":{"type":"object","properties":{"id":{"type":"string"},"to":{"type":"string","description":"E.164."},"body":{"type":"string"},"status":{"type":"string","enum":["accepted","queued","claimed","sending","sent","delivered","failed","expired","cancelled","unknown"]},"segments":{"type":"integer"},"encoding":{"type":"string","enum":["gsm7","ucs2"]},"deviceId":{"type":["string","null"],"description":"The phone holding the job; null until one claims it."},"requestedDeviceId":{"type":["string","null"]},"simSubscriptionId":{"type":["integer","null"]},"batchId":{"type":["string","null"]},"resendOfId":{"type":["string","null"]},"failureCode":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"claimedAt":{"type":["string","null"],"format":"date-time"},"sentAt":{"type":["string","null"],"format":"date-time"},"deliveredAt":{"type":["string","null"],"format":"date-time"},"failedAt":{"type":["string","null"],"format":"date-time"},"expiresAt":{"type":"string","format":"date-time"}},"required":["id","to","body","status","segments","encoding","deviceId","requestedDeviceId","simSubscriptionId","batchId","resendOfId","failureCode","createdAt","updatedAt","claimedAt","sentAt","deliveredAt","failedAt","expiresAt"]},"SendMessages":{"type":"object","properties":{"to":{"anyOf":[{"type":"string","maxLength":32},{"type":"array","items":{"type":"string","maxLength":32},"minItems":1,"maxItems":500}],"description":"One number, or up to 500. Each becomes its own message with its own status. National numbers use the organization default country."},"body":{"type":"string","minLength":1,"maxLength":1600},"deviceId":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$","description":"Send only from this phone. Omit to let any eligible phone take it."},"simSubscriptionId":{"type":"integer","minimum":0,"description":"A SIM in `deviceId`. Requires `deviceId`."}},"required":["to","body"]},"MessageList":{"type":"object","properties":{"messages":{"type":"array","items":{"$ref":"#/components/schemas/Message"}},"nextCursor":{"type":["string","null"]}},"required":["messages","nextCursor"]},"MessageDetail":{"type":"object","properties":{"id":{"type":"string"},"to":{"type":"string","description":"E.164."},"body":{"type":"string"},"status":{"type":"string","enum":["accepted","queued","claimed","sending","sent","delivered","failed","expired","cancelled","unknown"]},"segments":{"type":"integer"},"encoding":{"type":"string","enum":["gsm7","ucs2"]},"deviceId":{"type":["string","null"],"description":"The phone holding the job; null until one claims it."},"requestedDeviceId":{"type":["string","null"]},"simSubscriptionId":{"type":["integer","null"]},"batchId":{"type":["string","null"]},"resendOfId":{"type":["string","null"]},"failureCode":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"claimedAt":{"type":["string","null"],"format":"date-time"},"sentAt":{"type":["string","null"],"format":"date-time"},"deliveredAt":{"type":["string","null"],"format":"date-time"},"failedAt":{"type":["string","null"],"format":"date-time"},"expiresAt":{"type":"string","format":"date-time"},"events":{"type":"array","items":{"$ref":"#/components/schemas/MessageEvent"}}},"required":["id","to","body","status","segments","encoding","deviceId","requestedDeviceId","simSubscriptionId","batchId","resendOfId","failureCode","createdAt","updatedAt","claimedAt","sentAt","deliveredAt","failedAt","expiresAt","events"]},"MessageEvent":{"type":"object","properties":{"fromStatus":{"type":["string","null"],"enum":["accepted","queued","claimed","sending","sent","delivered","failed","expired","cancelled","unknown",null]},"toStatus":{"type":"string","enum":["accepted","queued","claimed","sending","sent","delivered","failed","expired","cancelled","unknown"]},"source":{"type":"string","enum":["api","member","device","system"]},"code":{"type":["string","null"]},"deviceId":{"type":["string","null"]},"at":{"type":"string","format":"date-time"}},"required":["fromStatus","toStatus","source","code","deviceId","at"]},"IncomingList":{"type":"object","properties":{"messages":{"type":"array","items":{"$ref":"#/components/schemas/IncomingMessage"}},"nextCursor":{"type":["string","null"]}},"required":["messages","nextCursor"]},"IncomingMessage":{"type":"object","properties":{"id":{"type":"string"},"deviceId":{"type":"string"},"from":{"type":"string"},"body":{"type":["string","null"],"description":"Null once removed by the organization retention period."},"simSubscriptionId":{"type":["integer","null"]},"receivedAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"retentionExpiresAt":{"type":"string","format":"date-time"},"bodyPurgedAt":{"type":["string","null"],"format":"date-time"},"mobileMoney":{"type":["object","null"],"properties":{"id":{"type":"string"},"provider":{"type":"string"},"classification":{"type":"string"}},"required":["id","provider","classification"]}},"required":["id","deviceId","from","body","simSubscriptionId","receivedAt","createdAt","retentionExpiresAt","bodyPurgedAt","mobileMoney"]},"MobileMoneyList":{"type":"object","properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/MobileMoneyEvent"}},"nextCursor":{"type":["string","null"]}},"required":["events","nextCursor"]},"MobileMoneyEvent":{"type":"object","properties":{"id":{"type":"string"},"incomingMessageId":{"type":"string"},"provider":{"type":"string","enum":["mvola","orange_money","airtel_money"]},"classification":{"type":"string","enum":["matched","ambiguous","unknown"]},"parsingStatus":{"type":"string","enum":["parsed","partial","failed"]},"verification":{"type":"string","enum":["unverified"],"description":"Always unverified. A recognized SMS is not proof of a transaction: sender IDs and text can be spoofed."},"direction":{"type":["string","null"],"enum":["incoming","outgoing",null]},"amountMinor":{"type":["integer","null"],"description":"In minor units: MGA has two decimals, so 50 000 Ar is 5000000."},"currency":{"type":["string","null"]},"reference":{"type":["string","null"]},"counterpartyName":{"type":["string","null"]},"counterpartyPhoneMasked":{"type":["string","null"]},"providerTimestamp":{"type":["string","null"]},"balanceMinor":{"type":["integer","null"]},"feesMinor":{"type":["integer","null"]},"parserVersion":{"type":"string"},"parserConfidence":{"type":["number","null"]},"ai":{"type":"object","properties":{"status":{"type":"string","enum":["not_needed","pending","not_consented","ai_unavailable","completed","failed"]},"provider":{"type":["string","null"]},"model":{"type":["string","null"]},"confidence":{"type":["number","null"]}},"required":["status","provider","model","confidence"]},"review":{"type":"object","properties":{"status":{"type":"string","enum":["none","reviewed"]},"note":{"type":["string","null"]},"reviewedAt":{"type":["string","null"],"format":"date-time"}},"required":["status","note","reviewedAt"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","incomingMessageId","provider","classification","parsingStatus","verification","direction","amountMinor","currency","reference","counterpartyName","counterpartyPhoneMasked","providerTimestamp","balanceMinor","feesMinor","parserVersion","parserConfidence","ai","review","createdAt","updatedAt"]},"WebhookEndpointList":{"type":"object","properties":{"endpoints":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}},"eventTypes":{"type":"array","items":{"type":"string","enum":["message.queued","message.claimed","message.sending","message.sent","message.delivered","message.failed","message.expired","message.cancelled","message.unknown","incoming.received","mobile_money.detected"]}}},"required":["endpoints","eventTypes"]},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"description":{"type":["string","null"]},"eventTypes":{"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean"},"disabledAt":{"type":["string","null"],"format":"date-time"},"disabledReason":{"type":["string","null"]},"consecutiveFailures":{"type":"integer"},"lastSuccessAt":{"type":["string","null"],"format":"date-time"},"lastFailureAt":{"type":["string","null"],"format":"date-time"},"previousSecretExpiresAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","url","description","eventTypes","enabled","disabledAt","disabledReason","consecutiveFailures","lastSuccessAt","lastFailureAt","previousSecretExpiresAt","createdAt","updatedAt"]},"CreatedWebhookEndpoint":{"type":"object","properties":{"endpoint":{"$ref":"#/components/schemas/WebhookEndpoint"},"secret":{"type":"string","description":"The signing secret. Shown once; store it now. Verify deliveries with it: HMAC-SHA256 over `<t>.<body>`, compared against each `v1` in `Kisoasms-Signature: t=…,v1=…`."}},"required":["endpoint","secret"]},"CreateWebhookEndpoint":{"type":"object","properties":{"url":{"type":"string","maxLength":2048,"description":"A public HTTPS URL."},"description":{"type":["string","null"],"maxLength":256},"eventTypes":{"type":"array","items":{"type":"string","enum":["message.queued","message.claimed","message.sending","message.sent","message.delivered","message.failed","message.expired","message.cancelled","message.unknown","incoming.received","mobile_money.detected"]},"minItems":1}},"required":["url","eventTypes"]},"WebhookDeliveryList":{"type":"object","properties":{"deliveries":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}},"nextCursor":{"type":["string","null"]}},"required":["deliveries","nextCursor"]},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string"},"endpointId":{"type":"string"},"eventId":{"type":"string"},"eventType":{"type":"string"},"status":{"type":"string","enum":["pending","delivered","retrying","dead"]},"attempts":{"type":"integer"},"lastStatusCode":{"type":["integer","null"]},"lastError":{"type":["string","null"]},"lastAttemptAt":{"type":["string","null"],"format":"date-time"},"nextAttemptAt":{"type":["string","null"],"format":"date-time"},"deliveredAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","endpointId","eventId","eventType","status","attempts","lastStatusCode","lastError","lastAttemptAt","nextAttemptAt","deliveredAt","createdAt"]}},"parameters":{}},"paths":{"/v1/devices":{"get":{"tags":["Devices"],"summary":"List devices","description":"Every phone paired to the key's organization, including revoked ones, with battery, network, SIM cards, and inbound capability. Requires the `devices:read` scope.","security":[{"ApiKey":[]}],"responses":{"200":{"description":"The devices.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceList"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this operation needs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected failure. Quote the request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/devices/{deviceId}":{"get":{"tags":["Devices"],"summary":"Get a device","description":"Requires the `devices:read` scope.","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"},"required":true,"name":"deviceId","in":"path"}],"responses":{"200":{"description":"The device.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Device"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this operation needs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected failure. Quote the request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["Devices"],"summary":"Update a device","description":"Rename a phone, drain it, switch its outbound sending, or set the SIM its jobs use by default. Requires the `devices:write` scope.","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"},"required":true,"name":"deviceId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDevice"}}}},"responses":{"200":{"description":"The updated device.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Device"}}}},"400":{"description":"The body is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this operation needs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is not application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected failure. Quote the request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Devices"],"summary":"Revoke a device","description":"Ends the device's access at once: its access token stops working on its next request. The record stays, with status `revoked`. Requires the `devices:write` scope.","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"},"required":true,"name":"deviceId","in":"path"}],"responses":{"200":{"description":"The revoked device.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Device"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this operation needs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected failure. Quote the request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/messages":{"post":{"tags":["Messages"],"summary":"Send SMS","description":"Queues one message per recipient and answers at once with 202. A phone in the organization claims each message and reports it through `queued → claimed → sending → sent → delivered`; follow it with `GET /v1/messages/{messageId}` or the `message.*` webhooks. Counts against the organization's daily limit. Requires the `messages:send` scope.","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[\\x21-\\x7e]+$","description":"Makes a retry safe for 24 hours: the same key with the same request answers with the original response and sends nothing; with a different request it is refused with 409."},"required":false,"description":"Makes a retry safe for 24 hours: the same key with the same request answers with the original response and sends nothing; with a different request it is refused with 409.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessages"}}}},"responses":{"202":{"description":"The queued messages.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendResult"}}}},"400":{"description":"The body is invalid, or a recipient is not a phone number.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this operation needs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`no_device`: no phone in the organization can send. `conflict`: the Idempotency-Key was used with a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is not application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The daily message limit, or the per-key request rate, was reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected failure. Quote the request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["Messages"],"summary":"List messages","description":"Newest first. Requires the `messages:read` scope.","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","enum":["accepted","queued","claimed","sending","sent","delivered","failed","expired","cancelled","unknown"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"The `nextCursor` of the previous page."},"required":false,"description":"The `nextCursor` of the previous page.","name":"before","in":"query"}],"responses":{"200":{"description":"A page of messages.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageList"}}}},"400":{"description":"A query parameter is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this operation needs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected failure. Quote the request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/messages/{messageId}":{"get":{"tags":["Messages"],"summary":"Get a message and its timeline","description":"Requires the `messages:read` scope.","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"},"required":true,"name":"messageId","in":"path"}],"responses":{"200":{"description":"The message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageDetail"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this operation needs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected failure. Quote the request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/messages/{messageId}/cancel":{"post":{"tags":["Messages"],"summary":"Cancel a queued message","description":"Only a message no phone has claimed can be cancelled. Requires the `messages:send` scope.","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"},"required":true,"name":"messageId","in":"path"}],"responses":{"200":{"description":"The cancelled message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this operation needs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The message is already on its way or finished.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected failure. Quote the request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/incoming":{"get":{"tags":["Incoming"],"summary":"List received SMS","description":"SMS received by phones where Kisoasms is the default messaging app, newest first. Requires the `incoming:read` scope.","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"},"required":false,"name":"deviceId","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"The `nextCursor` of the previous page."},"required":false,"description":"The `nextCursor` of the previous page.","name":"before","in":"query"}],"responses":{"200":{"description":"A page of received SMS.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncomingList"}}}},"400":{"description":"A query parameter is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this operation needs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected failure. Quote the request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/incoming/{incomingId}":{"get":{"tags":["Incoming"],"summary":"Get a received SMS","description":"Requires the `incoming:read` scope.","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"},"required":true,"name":"incomingId","in":"path"}],"responses":{"200":{"description":"The SMS.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncomingMessage"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this operation needs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected failure. Quote the request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/mobile-money":{"get":{"tags":["Mobile money"],"summary":"List recognized mobile-money SMS","description":"Likely MVola, Orange Money, and Airtel Money notifications read from received SMS. An unofficial, read-only reading: every record is `unverified`, and none is proof of a transaction. Requires the `mobile-money:read` scope.","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","enum":["matched","ambiguous","unknown"]},"required":false,"name":"classification","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"The `nextCursor` of the previous page."},"required":false,"description":"The `nextCursor` of the previous page.","name":"before","in":"query"}],"responses":{"200":{"description":"A page of records.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MobileMoneyList"}}}},"400":{"description":"A query parameter is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this operation needs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected failure. Quote the request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/mobile-money/{eventId}":{"get":{"tags":["Mobile money"],"summary":"Get a mobile-money record","description":"Requires the `mobile-money:read` scope.","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"},"required":true,"name":"eventId","in":"path"}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MobileMoneyEvent"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this operation needs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected failure. Quote the request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks":{"get":{"tags":["Webhooks"],"summary":"List webhook endpoints","description":"Requires the `webhooks:read` scope.","security":[{"ApiKey":[]}],"responses":{"200":{"description":"The endpoints and the subscribable event types.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointList"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this operation needs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected failure. Quote the request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Webhooks"],"summary":"Create a webhook endpoint","description":"The response carries the signing secret, once. Every `mobile_money.detected` delivery carries `verification: \"unverified\"`. Requires the `webhooks:write` scope.","security":[{"ApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookEndpoint"}}}},"responses":{"201":{"description":"The endpoint and its signing secret.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedWebhookEndpoint"}}}},"400":{"description":"The body is invalid, or the URL is not public HTTPS.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this operation needs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The organization has reached its endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is not application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected failure. Quote the request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/{endpointId}":{"get":{"tags":["Webhooks"],"summary":"Get a webhook endpoint","description":"Requires the `webhooks:read` scope.","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"},"required":true,"name":"endpointId","in":"path"}],"responses":{"200":{"description":"The endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this operation needs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected failure. Quote the request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Webhooks"],"summary":"Delete a webhook endpoint","description":"Its delivery history goes with it. Requires the `webhooks:write` scope.","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"},"required":true,"name":"endpointId","in":"path"}],"responses":{"204":{"description":"Deleted."},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this operation needs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected failure. Quote the request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/{endpointId}/deliveries":{"get":{"tags":["Webhooks"],"summary":"List deliveries to an endpoint","description":"Newest first. Requires the `webhooks:read` scope.","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"},"required":true,"name":"endpointId","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"The `nextCursor` of the previous page."},"required":false,"description":"The `nextCursor` of the previous page.","name":"before","in":"query"}],"responses":{"200":{"description":"A page of deliveries.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryList"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the scope this operation needs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected failure. Quote the request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{}}