Skip to Content
SessionCloud PortalProvider SMS and MMSDirect customer-hosted service
SessionCloud Portal

Direct customer-hosted messaging

Use this integration when you operate the app’s messaging service, including its inboxes, user authentication and carrier delivery. The SessionCloud portal supplies account configuration; the app contacts your HTTPS server directly to send and fetch text messages. SIP registration remains with your PBX.

Release requirement. This integration requires the portal’s Customer-hosted service option and an app release that supports its outgoing configuration. The implementation is prepared for release; it is not enabled in the live portal yet. Existing Custom HTTPS connections continue to use SessionCloud’s messaging API.

Choose the correct integration

Custom HTTPSCustomer-hosted service
SendingApp → SessionCloud → your gatewayApp → your service
ReceivingYour gateway → SessionCloud webhook → appYour service stores messages; the app fetches them directly
App inbox and access credentialsManaged by SessionCloudManaged by your service
Carrier webhookForward messages to the portal’s Custom HTTPS webhookReceive and verify callbacks on your own server
NotificationsSessionCloud requests notificationsYour service uses the scoped SessionTalk push API

Both options support a bridge that delivers through VoIP Innovations or another carrier. Choose direct hosting only if your service also implements the app-facing API below. It supports text SMS; MMS and carrier delivery receipts are outside this integration.

Configure the portal

  1. Open the BYO PBX project, go to Provisioning > Advanced > Messaging, enable SMS, and save the project.

  2. Under Messaging providers, select Customer-hosted service.

  3. Enter the service’s HTTPS URLs:

    Portal fieldExampleApp request
    Incoming message fetch URLhttps://sms.example.com/inboxGET /inbox?after=cursor and GET /inbox/UUID
    Push registration URLhttps://sms.example.com/devicesPUT /devices
    Outgoing SMS URLhttps://sms.example.com/sendForm-encoded POST /send
  4. Check Advanced field mappings against your outgoing endpoint. Defaults are username, password, da for the destination, ud for the text, and success response prefix OK:. Clear the prefix if every HTTP 2xx response means accepted.

  5. Save the connection. No SessionCloud incoming webhook is generated for this mode.

URLs must use HTTPS and contain no embedded credentials, query strings or fragments. The app does not follow redirects. Enter final URLs with certificates trusted by the phone. Fetch and registration URLs receive the user’s service credentials.

Assign each user’s service account

Create the user and number assignment on your messaging server first. Your service must select an inbox and permitted sending number from the authenticated service account. A number or mailbox identifier supplied by a client is not authentication.

In the portal’s Assign a number form:

  1. Select the Customer-hosted service connection.
  2. Enter the messaging number in + international format, the exact SIP username and the SIP domain, including its port where applicable.
  3. Enter that user’s Service username and Service password. These are credentials for your SMS service, separate from SIP and carrier API credentials.
  4. Select incoming authentication: the service username/password using HTTP Basic, or an API token issued by your service. A service API token does not have the fixed 43-character requirement of a SessionCloud mailbox token.
  5. Assign the number and generate a new private account provisioning QR, or obtain updated authenticated external provisioning. Provision the matching account in a compatible app.

Outgoing SMS always sends the service username/password in the configured form fields. The incoming authentication selection applies to inbox fetches and push registration. Credentials are encrypted in the portal database and included only in authenticated provisioning for the matching account. Treat its QR as private; do not enter a carrier-wide API credential as a user’s service password.

The portal generates the routing identifier. The user does not register a second mailbox with SessionTalk or manually copy an identifier from your server. Your server associates the app’s device report with the inbox selected by authentication.

Changing an endpoint or service identity requires updated account provisioning. Disabling a portal assignment prevents future provisioning; it cannot revoke credentials already issued by your service. Revoke those credentials and remove device routes on your server when removing access. Your server controls message history and retention.

What the QR contains

The portal supplies byomessaging within the SIP account configuration. In this mode it includes mode: "webservice", fetchurl, reporturl, service credentials, an outgoing object and a routing identifier. apiurl equals the fetch URL.

Do not change only apiurl in a normal SessionCloud mailbox QR. Without the webservice mode, the app expects the SessionCloud-compatible /api/v1/byo-messaging base and /messages API. A different base path can be rejected before the app contacts your server.

The following illustrates the generated account block; placeholders are not usable credentials. Generate the actual QR through authenticated portal provisioning.

{ "byomessaging": { "mode": "webservice", "provider": "custom", "apiurl": "https://sms.example.com/inbox", "fetchurl": "https://sms.example.com/inbox", "reporturl": "https://sms.example.com/devices", "mailboxid": "00000000-0000-4000-8000-000000000001", "number": "+12025550123", "authmode": "basic", "authusername": "user-101", "authpassword": "USER_SERVICE_PASSWORD", "token": "", "binding": { "username": "101", "domain": "pbx.example.com:5062" }, "outgoing": { "url": "https://sms.example.com/send", "username": "user-101", "password": "USER_SERVICE_PASSWORD", "usernameField": "username", "passwordField": "password", "destinationField": "da", "messageField": "ud", "successPrefix": "OK:" } } }

With incoming API-token authentication, authmode is bearer, token contains the service token, and authusername/authpassword are empty. The outgoing form credentials remain in outgoing.

Implement the service API

Fetch and registration requests carry Authorization: Basic ... or Authorization: Bearer ..., according to the account configuration. Return JSON and authenticate every request. Do not delete messages when fetched; multiple devices maintain independent cursors.

Fetch messages

GET /inbox?after=0 returns:

{ "messages": [{ "id": "00000000-0000-4000-8000-000000000002", "peer": "+12025550124", "body": "Example incoming message", "direction": "inbound", "state": "received", "created_at": "2026-01-01T12:00:00Z" }], "next": 1, "more": false }

Message IDs must be stable UUIDs, including across retries. The cursor is a monotonically increasing integer, or decimal string; it is not a UUID. Return messages in sequence order, at most 100 per page. next is the last returned sequence, or the requested cursor for an empty page. Set more when another page is available. The app polls while foregrounded.

GET /inbox/UUID returns {"message": {...}} for that UUID, or HTTP 404 if absent. The mobile app uses this endpoint to fetch the complete message after a push. Use international numbers or supported alphanumeric sender IDs in peer and UTF-8 text in body, up to 65,536 bytes.

Send a message

The app posts UTF-8 application/x-www-form-urlencoded directly to the outgoing URL. With the default mappings the fields are username, password, da and ud. The sending number comes from the authenticated service account.

Return HTTP 2xx and a body beginning with the configured success prefix after accepting a message. An empty prefix accepts any 2xx response. This confirms submission, not carrier delivery. HTTP 3xx/4xx rejects the send. Network failures, 5xx and an unexpected success body can leave submission uncertain; the app does not automatically repeat a potentially billable SMS.

Register notifications

The app sends PUT /devices with:

{ "deviceId": "example-device", "profileId": 22, "selector": "00000000-0000-4000-8000-000000000001", "mailboxId": "00000000-0000-4000-8000-000000000001", "number": "+12025550123", "username": "user-101", "pushUrl": "https://SELECTED_RELAY/byo/webservice/push", "pushToken": "SCOPED_PUSH_GRANT", "expiresAt": 1900000000 }

The username is included with Basic authentication. Authenticate first, verify that the number belongs to that service account, and upsert a route per device/profile. selector and mailboxId are aliases; neither grants inbox access. Return {"ok":true} and protect the stored push token.

After storing an incoming message, request a notification using the reported push URL and Authorization: Bearer SCOPED_PUSH_GRANT, with this JSON body:

{ "messageId": "00000000-0000-4000-8000-000000000002", "remoteNumber": "+12025550124", "text": "Example incoming message" }

Allow only your approved SessionTalk relay hosts and the /byo/webservice/push path. The app obtains the grant from its selected relay; your service does not need a shared relay secret, the SIP password or the native APNs/FCM token. Grants expire after seven days and are refreshed while the app is open. Private push deployments need the matching webservice relay implementation.

Keep messages available for fetching if notifications fail. Retry notification network errors, HTTP 429 and 5xx with backoff and the same message UUID; HTTP 401 requires a refreshed device report. HTTP 200 acknowledges notification submission, not delivery or reading. A missing device report does not prevent foreground inbox fetching and has no bearing on SIP registration.

Verify the direct connection

Use a test service account and confirm these requests in your service’s sanitized logs: inbox GET, outgoing POST, and device PUT on a push-enabled mobile account. Do not log Authorization headers, service passwords, push tokens or message bodies. Check receiving while foregrounded, a reply, duplicate-message handling, offline recovery, and a locked-phone notification that opens the correct conversation.

The portal displays Check your service for last received SMS because SessionCloud does not store these messages. Verify receipt on your server and delivery in the app. An enabled assignment alone does not confirm that your service, carrier or notifications are working.

Last updated on