Mobile SasaDocs

Surveys

Multi-question SMS conversations: a customer texts your keyword, gets asked each question in turn, and every answer is stored for you to pull over the API. No app, no data bundle needed on the customer's side.

A survey attaches to a keyword , every inbound text matching that keyword opens a survey session. The same survey engine also powers USSD survey mode. Endpoints live under /api/v1/ with a scoped mbs_ token or JWT.

Start from a template

GET/api/v1/surveys/templates

Five ready-made question sets, each with a welcome and closing message: customer_satisfaction, event_rsvp, product_feedback, staff_pulse and market_research. Copy one into the questions array below and edit as you like. The portal's Surveys → New Survey wizard offers the same templates, lets you reserve a keyword or point a USSD extension in the same flow, and creates everything in one go.

Create a survey

POST/api/v1/surveys

Parameters

FieldTypeRequiredDescription
namestringYesInternal label.
keyword_uuiduuidNoThe keyword that opens this survey when texted. Leave it out for a USSD or push survey, or set it later with PATCH.
sender_namestringNoSender the questions go out under, usually the shortcode the keyword sits on.
welcome_messagestringNoSent together with the first question when a session starts.
end_messagestringNoSent after the last answer. Thank-yous, vouchers, next steps.
session_timeout_minutesintNoHow long a respondent may pause between answers before they start over. Default 60.
one_per_msisdnbooleanNoAccept one completed response per phone number.
questionsQuestion[]NoThe questions, inline (sequence is stored as given), or add them one at a time afterwards (below).
# Paste your token once (it starts with mbs_):
export MOBILESASA_TOKEN="mbs_your_token_here"

curl -X POST https://api.mobilesasa.com/api/v1/surveys \
  -H "Authorization: Bearer $MOBILESASA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Delivery satisfaction. July",
    "keyword_uuid": "8c11d2ab-…",
    "sender_name": "40404",
    "welcome_message": "Thanks for ordering from Dukapay! 3 quick questions:",
    "end_message": "Asante! Your feedback keeps us sharp.",
    "session_timeout_minutes": 30,
    "questions": [
      {
        "question": "How would you rate your delivery? Reply 1-5",
        "question_type": "numeric",
        "sequence": 1,
        "is_required": true
      },
      {
        "question": "Was the rider courteous? Reply YES or NO",
        "question_type": "yes_no",
        "sequence": 2,
        "is_required": true
      },
      {
        "question": "Anything we should improve?",
        "question_type": "open",
        "sequence": 3,
        "is_required": false
      }
    ]
  }'

Add questions

POST/api/v1/surveys/{uuid}/questions
GET/api/v1/surveys/{uuid}/questions
DELETE/api/v1/surveys/{uuid}/questions/{question_uuid}

Question fields

FieldTypeRequiredDescription
questionstringYesThe text sent to the participant.
question_typestringYesopen (free text), single_choice, multiple_choice, numeric, yes_no, range (a rating between min and max).
optionsJSON stringNoFor choice types: the options as a JSON array string, e.g. "[\"M-Pesa\",\"Card\",\"Cash\"]"; participants reply with the option number. For range: "{\"min\":1,\"max\":5}".
sequenceintYesOrder the question is asked in (1-based).
is_requiredbooleanNoRequired questions re-prompt on an invalid answer; optional ones accept SKIP.
# Paste your token once (it starts with mbs_):
export MOBILESASA_TOKEN="mbs_your_token_here"

curl -X POST https://api.mobilesasa.com/api/v1/surveys/5e9dd410-…/questions \
  -H "Authorization: Bearer $MOBILESASA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "How did you pay? 1. M-Pesa 2. Card 3. Cash",
    "question_type": "single_choice",
    "options": "[\"M-Pesa\",\"Card\",\"Cash\"]",
    "sequence": 4,
    "is_required": true
  }'

Lifecycle

POST/api/v1/surveys/{uuid}/activate
POST/api/v1/surveys/{uuid}/pause
POST/api/v1/surveys/{uuid}/close

Statuses

FieldTypeRequiredDescription
draftinitialNoEditable (PATCH); not answering traffic. A survey needs at least one question before it can activate; no approval is involved.
activeliveNoKeyword texts open sessions and questions flow.
pausedholdNoNew sessions refused; re-activate any time.
closedfinalNoDone. Data remains available.

Approval on amendments

Setting or changing a survey's run window (POST /surveys/{uuid}/amend with starts_at/ends_at) puts it through a quick system review; the survey can't activate while that review is pending. You're emailed automatically when it's approved or rejected.

Test it before going live

POST/api/v1/surveys/{uuid}/simulate

The simulator walks a fake session without sending real SMS. Post the participant's next reply, get back what the survey would send:

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

curl -X POST https://api.mobilesasa.com/api/v1/surveys/5e9dd410-…/simulate \
  -H "Authorization: Bearer $MOBILESASA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "msisdn": "254712345678",
    "message": "START"
  }'

You can also restrict a live survey to test numbers with the whitelist (PUT /surveys/{uuid}/whitelist with {"msisdns": ["2547…"]}; empty array lifts the restriction).

Start a survey yourself

POST/api/v1/surveys/{uuid}/start

A survey usually waits to be texted. This makes it speak first: give it a number and it opens the session and sends question one, from the shortcode its keyword sits on. The reply comes back the ordinary way, so the conversation continues exactly as if the person had texted the keyword themselves.

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

curl -X POST https://api.mobilesasa.com/api/v1/surveys/5e9dd410-…/start \
  -H "Authorization: Bearer $MOBILESASA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "msisdn": "254712345678"
  }'
Response: 200
{
  "success": true,
  "data": { "status": "sent", "msisdn": "254712345678" }
}

Requirements

FieldTypeRequiredDescription
Scopeteam:surveys:sendNoThe API token needs it. Create one under Settings → API tokens.
StatusactiveNoA draft or paused survey is refused: activate it first.
KeywordrequiredNoThe survey's keyword decides which shortcode the question is sent from, and where the answer comes back to. A survey with no keyword has nowhere to send from.
BalanceunitsNoQuestion one is a billed SMS like any other, and so is every question after it.

Where this earns its keep

Close a support ticket, deliver an order, finish a clinic visit — call this and the survey asks about it while the experience is still fresh, without the customer having to remember a keyword. One call per person, so your own system decides who gets asked and when.

USSD surveys cannot be started this way

Only the subscriber can open a USSD session, so a survey answering on a USSD extension can be advertised but not pushed. Send an SMS inviting them to dial the code instead.

Send it to a whole group

One number at a time is the API; a list is a campaign. Create a campaign with survey_uuid set and every recipient is put into a session as their message goes out — priced, reserved and cancellable like any other campaign, and listed with the rest. The survey's own shortcode is used as the sender whatever you pass, because a question asked from another identity has nowhere to be answered.

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

curl -X POST https://api.mobilesasa.com/api/v1/campaigns \
  -H "Authorization: Bearer $MOBILESASA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Customer satisfaction",
    "message": "Two quick questions.\nHow did we do?\n1. Yes\n2. No",
    "source_type": "groups",
    "target_group_uuids": [
      "9f31…"
    ],
    "survey_uuid": "5e9dd410-…"
  }'

The portal does this for you

On a survey's page in the portal, Send this surveyshows the exact opening message, lets you pick contact groups, and totals the units before you commit — it builds the same campaign.

Pull the responses

GET/api/v1/surveys/{uuid}/responses
# Paste your token once (it starts with mbs_):
export MOBILESASA_TOKEN="mbs_your_token_here"

curl "https://api.mobilesasa.com/api/v1/surveys/5e9dd410-…/responses?page=1" \
  -H "Authorization: Bearer $MOBILESASA_TOKEN"
Response: 200
{
  "success": true,
  "data": [
    {
      "uuid": "77b0…",
      "session_uuid": "d2c4…",
      "msisdn": "254712345678",
      "question_uuid": "31aa…",
      "answer": "5",
      "created_at": "2026-07-11T12:40:19Z"
    }
  ],
  "meta": { "page": 1, "page_size": 20, "total": 412 }
}

Answers cost units

Each question and confirmation the survey sends is a normal SMS billed in units from your SMS balance. A 3-question survey costs roughly 4–5 units per completed session.