Departments

Split one Mobile Sasa account into departments that each keep their own members, contacts, messages, SMS units and wallet. The organisation funds them by transfer and keeps billing, sender registration and KYC in one place.

How it works

Every account is an organisation with one main department: the team you signed up with. An organisation admin can create further departments under it, move members into them, share sender names with them and move units or wallet balance to them. Inside a department, everything works exactly as it does for a standalone team: people see only their department's messages, contacts, campaigns, reports, API tokens and balances.

Who owns what

  • The organisation (main department) owns the billing identity and paybill reference, SMS rates, postpaid terms, sender ID registration and KYC, platform default sender access, dedicated shortcodes and USSD codes, WhatsApp numbers and email domains. Top-ups happen here.
  • Each department owns its members and invitations, API tokens, contacts and groups, messages and campaigns, keywords, USSD extensions, surveys, reminders, its own SMS units and wallet, its webhook secret and callback URL, and its alert contacts and reorder levels.
  • Shared across the family: customer opt-outs. A number blacklisted by any department or by the organisation is skipped by every team in the family.

Departments are not billed directly

A department has no paybill account number and cannot top up by M-Pesa or card. The organisation pays in, then moves SMS units or KES to the department from Settings → Departments. Every transfer appears in both teams' statements and in the audit log.

Setting up departments in the portal

  1. Create. Settings → Departments → New department. Give it a name and, optionally, a contact email and phone. It starts with zero units, an empty wallet and no members, and inherits your SMS rate.
  2. Fund. On the Transfers tab, move SMS units or wallet balance from the main department. You can pull unused balance back the same way.
  3. Add people. On the Members tab, move existing members across, or invite someone straight into the department from Settings → Members → Invite. A person belongs to exactly one department.
  4. Share senders. On the Senders tab, share any of your approved sender names with the department. Sends are billed to the department's own units.
  5. Move resources. On the Resources tab, move keywords, USSD extensions, surveys or contact groups into a department. Linked items travel together: a keyword brings its survey, a survey brings its keyword and the extensions that dial it, a group brings copies of its contacts.

An organisation admin can also open any department as its admin for one hour with Open as admin. A banner shows where you are; Return ends that access immediately. Dissolving a department returns its balances, members and resources to the organisation and revokes its API tokens.

Things a department cannot do

Register or expand a sender ID, request platform default sender access, connect a WhatsApp number, set a paybill reference, go postpaid, or delete itself. Ask an organisation admin; the portal says so on each of those pages.

Using the API from a department

A department is its own team on the API. Create an API token while signed in to the department (or while acting in it as an organisation admin) and every endpoint behaves as it does for any team: balances are the department's, sends draw down the department's units, message history and delivery reports are the department's only, and callbacks are signed with the department's own webhook secret.

Same endpoints, department scope

  • GET /v1/get-balance/ returns the department's SMS units. localAccountNumber is empty for a department. See Balance.
  • POST /v1/send/message, /v1/send/bulk, /v1/send/bulk-personalized and /v2/send/message send with any sender name the organisation has shared with the department. An unshared name is refused with 0422. See Send SMS.
  • POST /v1/dlr and POST /v2/dlr return delivery reports for the department's messages only. See Delivery reports.
  • Every /api/v1/… endpoint (messages, campaigns, contacts, groups, keywords, surveys, reminders, reports) returns the department's data, and webhooks carry the department's signing secret.

One token per department

Tokens are scoped to the team that created them. If your integration serves several departments, mint one token in each and route by department on your side. Tokens created inside a department are revoked when the department is dissolved.

Organisation endpoints

These are available to admins of the main department only. They need a session or token holding the team:departments:view, team:departments:manage or team:departments:transfer permissions; team admins hold all three.

Where am I?

GET/api/v1/departments/context

Readable by every member. Says which department the session is in and whether it is the main one.

# Paste your token once (it starts with mbs_):
export MOBILESASA_TOKEN="mbs_your_token_here"

curl "https://api.mobilesasa.com/api/v1/departments/context" \
  -H "Authorization: Bearer $MOBILESASA_TOKEN"
Response: 200
{
  "success": true,
  "data": {
    "is_main": false,
    "department_uuid": "23197cb4-…",
    "department_name": "Sales",
    "organisation_uuid": "98a12434-…",
    "organisation_name": "Litemore Limited",
    "departments": 2
  }
}

List departments

GET/api/v1/departments

The main department first, then each department with its balances, member and sender counts.

Response: 200 (one entry)
{
  "uuid": "23197cb4-…",
  "name": "Sales",
  "email": "[email protected]",
  "is_main": false,
  "status": "active",
  "balance": 5000,
  "wallet_balance": 2500.00,
  "sms_rate": 0.24,
  "members": 3,
  "senders_shared": 1,
  "keywords": 0,
  "extensions": 0,
  "created_at": "2026-09-06T09:40:49Z"
}

Create, rename, dissolve

POST/api/v1/departments

Parameters

FieldTypeRequiredDescription
namestringYesShown to members and staff. Up to 20 departments per organisation.
emailstringNoContact email for the department. Defaults to your organisation email with a tag, for example [email protected].
phonestringNoContact phone. Used for low-balance reminders alongside the organisation's alert contacts.
# Paste your token once (it starts with mbs_):
export MOBILESASA_TOKEN="mbs_your_token_here"

curl -X POST https://api.mobilesasa.com/api/v1/departments \
  -H "Authorization: Bearer $MOBILESASA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Sales",
    "email": "[email protected]"
  }'
PATCH/api/v1/departments/{uuid}

Body { "name": "…" } renames the department.

DELETE/api/v1/departments/{uuid}

Dissolves it. Units and wallet balance return to the organisation as transfers, members and resources move back to the main department, API tokens are revoked and pending invitations cancelled.

Transfer units or wallet balance

POST/api/v1/departments/{uuid}/transfers

Parameters

FieldTypeRequiredDescription
directionstringYesto funds the department from the organisation; from returns balance to the organisation.
kindstringYesunits or wallet.
unitsintegerNoWhole SMS units, when kind is units.
amountnumberNoKES, when kind is wallet.
notestringNoOptional memo, kept on the transfer record.
# Paste your token once (it starts with mbs_):
export MOBILESASA_TOKEN="mbs_your_token_here"

curl -X POST https://api.mobilesasa.com/api/v1/departments/{uuid}/transfers \
  -H "Authorization: Bearer $MOBILESASA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "direction": "to",
    "kind": "units",
    "units": 5000,
    "note": "September allocation"
  }'
Response: 200
{
  "success": true,
  "data": {
    "uuid": "79cce045-…",
    "kind": "units",
    "units": 5000,
    "amount": 0,
    "from_name": "Litemore Limited",
    "to_name": "Sales",
    "note": "September allocation",
    "created_at": "2026-09-06T09:42:11Z"
  }
}

A transfer is refused when the source does not hold the balance. An organisation on postpaid terms cannot transfer units while its own balance is overdrawn. Each transfer writes a matching pair of ledger entries, transfer_out and transfer_in, that share the transfer's reference.

GET/api/v1/departments/transfers

History, newest first. Filter with ?department=<uuid> and page with ?page=.

Members and senders

GET/api/v1/departments/members

Every member of the organisation with the department they sit in.

POST/api/v1/departments/members/move

Parameters

FieldTypeRequiredDescription
user_uuidstringYesThe member to move.
department_uuidstringNoDestination. Omit or leave empty to move them back to the main department.

Moving someone signs them out everywhere and re-scopes any API tokens they own to the new department. The last active admin of the main department cannot be moved out.

POST/api/v1/departments/{uuid}/senders
DELETE/api/v1/departments/{uuid}/senders

Body { "sender_uuid": "…" } shares or withdraws one of the organisation's approved sender names. Sends with a shared name are billed to the department.

POST/api/v1/invitations

The usual invite endpoint accepts an optional department_uuid from a main-department admin, so the invitee lands directly in that department.

Move keywords, extensions, surveys and groups

POST/api/v1/departments/resources/transfer

Parameters

FieldTypeRequiredDescription
kindstringYeskeyword, extension, survey or group.
uuidstringYesThe resource, which must belong to the organisation or one of its departments.
department_uuidstringNoDestination. Omit or leave empty to move it back to the main department.

Renewals and charges follow the new owner from then on. Linked items move together, as described above.

Usage across departments

GET/api/v1/departments/reports/messages

Daily outgoing message totals per department for a date range (?from=YYYY-MM-DD&to=YYYY-MM-DD, last 30 days by default). Each department's own reports carry the detail.

Act inside a department

POST/api/v1/departments/{uuid}/session

Issues a token scoped to the department, valid for one hour, for the calling organisation admin. Use it exactly like a member's session. It carries the organisation in an acting_from claim and is recorded in the audit log.

DELETE/api/v1/departments/session

Called with the acting token, revokes it before it expires.

Alerts and reminders

Reorder levels and alert contacts are set per department under Settings → Alerts. When a department runs low, the reminder goes to its alert contacts and to the organisation's, and asks an organisation admin to transfer balance rather than quoting a paybill.