# Introduction
TumaMaoni is a customer feedback platform for Tanzanian and global businesses. Our developer API lets you collect, read and analyse feedback programmatically — using prepaid tokens instead of a subscription.
What the API gives you
- Collect feedback — submit ratings and comments from your app or widget in a single request.
- Read feedback — list and search everything customers have shared, with pagination and filters.
- Analytics — overviews, trends, department and product breakdowns, satisfaction scores.
- Simple billing — 1 token = 1 request = TZS 1. No monthly fees, no credit checks.
- Ready widget — a drop-in JavaScript feedback bubble for websites, powered by publishable keys.
Base URL
| Environment | Base URL |
|---|---|
| Production | https://tumamaoni.com/api/v2 |
Pricing
| Item | Cost | Notes |
|---|---|---|
| Paid request | 1 token | Debited per request, refunded if the request fails (4xx/5xx) |
| Token price | TZS 1 | Buy tokens via mobile money (M-Pesa, Airtel, Tigo) |
| Free grant | 100 tokens | Credited automatically when you create your first API key |
| Wallet & key management | Free | Balance, usage, keys and topup endpoints never cost tokens |
Next steps
- Create your account and open the Developer API portal.
- Generate an API key — you get 100 free tokens.
- Make your first request (see Quickstart).
# Quickstart
Get your first feedback submitted through the API in about two minutes.
1. Create an API key
- Log in to TumaMaoni and open the Developer API portal.
- Open the API keys tab and click Create an API key.
- Choose Secret for server-side access (full access) or Publishable for the client-side widget.
- Copy the key immediately — it is only shown once.
Creating your first key also grants you 100 free tokens.
2. Check your balance
curl https://tumamaoni.com/api/v2/balance \
-H "Authorization: Bearer TM-secret-your_key_here"
{
"success": true,
"message": "Success",
"data": {
"user_id": 42,
"balance": 100,
"total_purchased": 0,
"total_spent": 0,
"free_granted": 1,
"used_today": 0,
"rejected_insufficient": 0,
"min_topup": 1000,
"max_topup": 200000,
"tokens_per_request": 1,
"topup_url": "https://tumamaoni.com/api"
}
}
3. Submit your first feedback
This paid request costs 1 token and submits feedback to your own business.
curl -X POST https://tumamaoni.com/api/v2/feedbacks/submit \ -H "Authorization: Bearer TM-secret-your_key_here" \ -H "Content-Type: application/json" \ -d '{ "customer_name": "John Doe", "email_phone": "john@example.com", "comments": "Great service, very fast!", "satisfaction_score": 5, "recommend": "yes", "department": "Support", "product_service": "Mobile App" }'
{
"success": true,
"message": "Feedback submitted successfully",
"data": { "feedback_id": 1024 }
}
# Authentication
Authenticate every request with your API key. Send it as a Bearer token or in the X-API-Key header.
Bearer token
Authorization: Bearer TM-secret-your_key_here
X-API-Key header
X-API-Key: TM-secret-your_key_here
Key formats
| Prefix | Type | Use |
|---|---|---|
TM-secret-… | Secret | Server-side. Full access: submit, read, analytics. |
TM-pub-… | Publishable | Client-side widget only. Can submit feedback, cannot read data. |
Authenticating requests
Most endpoints require authentication and return 401 with an invalid or missing key. The POST /feedbacks/submit endpoint also accepts publishable keys so your widget can submit feedback directly.
# API keys
Create and manage keys from the Developer API portal or through the API itself. Keys are hashed in our database — the raw key is shown only once at creation.
Secret vs publishable
| Capability | Secret | Publishable |
|---|---|---|
| Submit feedback | Yes | Yes |
| Read feedback / analytics | Yes | No |
| Manage keys & wallet | Yes | No |
| Allowed domains | Not enforced | Enforced (Referer) |
| Daily request cap | 1,000 | 100 |
| Where it lives | Your backend | Your frontend |
Allowed domains (publishable keys)
You can restrict a publishable key to specific domains. Requests are checked against the Referer header, so the widget will only run on your sites. One domain per line, e.g. myapp.com and localhost. Leave empty to allow any domain.
Create a key via the API
Zero-token endpoint. Requires an existing secret key.
curl -X POST https://tumamaoni.com/api/v2/keys \
-H "Authorization: Bearer TM-secret-your_key_here" \
-H "Content-Type: application/json" \
-d '{
"name": "My Mobile App",
"key_type": "publishable",
"allowed_referrers": ["myapp.com", "localhost"]
}'
The response returns your new key once:
{
"success": true,
"message": "API key created. Store it now — you will not see it again.",
"data": {
"id": 7,
"key": "TM-pub-a1b2c3d4e5...",
"key_type": "publishable",
"name": "My Mobile App"
}
}
# Token billing
TumaMaoni API uses simple prepaid billing. There are no subscriptions — you buy tokens and each paid request spends exactly one.
How it works
- 1 token = 1 request — every paid endpoint costs exactly 1 token (TZS 1).
- Free grant — creating your first API key credits 100 free tokens.
- Top up via mobile money — buy tokens with M-Pesa, Airtel or Tigo through CamelPay.
- Instant credit — once payment is confirmed, your balance updates automatically.
- Refunds — if a paid request fails (4xx/5xx), the token is refunded automatically.
Prices
| Item | Value |
|---|---|
| Minimum topup | TZS 1,000 (1,000 tokens) |
| Maximum topup | TZS 200,000 (200,000 tokens) |
| Low balance alert | Email when balance drops below 500 tokens |
Top up from your server
Zero-token endpoint. Initiates a CamelPay mobile money charge — the customer gets a USSD prompt on their phone.
curl -X POST https://tumamaoni.com/api/v2/topup \
-H "Authorization: Bearer TM-secret-your_key_here" \
-H "Content-Type: application/json" \
-d '{ "amount_tsh": 5000, "phone": "0712345678" }'
{
"success": true,
"message": "Payment initiated. Please check your phone for the USSD prompt.",
"data": {
"order_ref": "TT-42-1722...",
"reference": "cp_a1b2c3d4...",
"tokens": 5000,
"tsh_amount": 5000
}
}
After the customer completes payment, CamelPay calls your account's topup webhook and the tokens are credited to your wallet instantly.
# Feedback widget
Add a non-intrusive feedback bubble to your website in minutes. The widget is powered by a publishable key and submits feedback directly to your TumaMaoni account — no backend needed.
Install
Add this to your page, replacing apiKey with your publishable key:
<script src="https://tumamaoni.com/widget.js" async></script>
<script>
TumaMaoni.init({
apiKey: 'TM-pub-your_publishable_key',
appName: 'Tumamaoni',
auto: { enabled: true, frequency: 'twice_week' }
});
</script>
Event-triggered prompts
Ask for feedback after a specific action (for example after checkout):
// call after a user does something
TumaMaoni.askFeedback('Checkout');
Auto-prompt frequency
| Value | Frequency |
|---|---|
off | Never show automatically (event-triggered only) |
daily | Once per day per visitor |
twice_week | Twice per week per visitor |
weekly | Once per week per visitor |
# Webhooks
TumaMaoni doesn't need you to poll for payment status — when your mobile money topup is confirmed, your token wallet is credited automatically.
Topup webhook
When a topup payment succeeds through CamelPay, TumaMaoni receives a webhook at https://tumamaoni.com/api/token_topup_webhook.php and credits the customer's wallet. You never have to write code for this — it happens automatically on our side.
POST /api/v2/topup, poll GET /api/v2/balance until the balance increases, or simply watch the Token history table in your developer portal.# API reference
Complete list of endpoints. Base URL: https://tumamaoni.com/api/v2. Every paid endpoint costs 1 token.
Wallet & key management free
| Method | Endpoint | Description |
|---|---|---|
| POST | /keys | Create an API key |
| GET | /keys | List your API keys |
| PUT | /keys/{id} | Rename, suspend or update domains |
| DELETE | /keys/{id} | Revoke (suspend) a key |
| GET | /balance | Wallet balance, usage today, limits |
| GET | /usage | Request log (pagination supported) |
| POST | /topup | Initiate a CamelPay mobile money topup |
Feedback 1 token each
| Method | Endpoint | Description |
|---|---|---|
| POST | /feedbacks/submit | Submit feedback (secret or publishable key) |
| GET | /feedbacks | List feedback with filters & pagination |
| GET | /feedbacks/{id} | Get one feedback with custom answers |
| GET | /feedbacks/stats | Totals, average rating, daily trends, departments |
Analytics 1 token each
| Method | Endpoint | Description |
|---|---|---|
| GET | /analytics/overview | Headline metrics |
| GET | /analytics/trends | Feedback volume over time |
| GET | /analytics/departments | Performance by department |
| GET | /analytics/products | Performance by product / service |
| GET | /analytics/satisfaction | Satisfaction & recommendation scores |
Data 1 token each
| Method | Endpoint | Description |
|---|---|---|
| GET | /departments | List departments |
| GET | /products | List products / services |
| GET | /settings | Business settings |
| GET | /notifications | Recent notifications |
Submit feedback — fields
| Field | Type | Required | Description |
|---|---|---|---|
comments | string | Yes | The customer's feedback text |
satisfaction_score | integer | Yes | Rating from 1 to 5 |
customer_name | string | No | Defaults to "Anonymous" |
email_phone | string | No | Contact of the customer |
recommend | enum | No | yes or no — inferred from the score |
department | string | No | Department or channel |
product_service | string | No | Product or service being rated |
feature | string | No | Widget context label |
location_channel | string | No | Where the feedback was collected |
custom_answers | array | No | Answers to custom questions: [{question_id, answer}] |
List feedback — query filters
| Parameter | Example | Description |
|---|---|---|
page | 2 | Page number (default 1) |
per_page | 50 | Results per page (default 20, max 50) |
date_from / date_to | 2026-07-01 | Date range filter |
department | Support | Filter by department |
location | Mobile App | Filter by location / channel |
rating | 5 | Filter by satisfaction score |
search | fast | Search name or comments |
Example — list feedback
curl "https://tumamaoni.com/api/v2/feedbacks?page=1&per_page=20&rating=5" \
-H "Authorization: Bearer TM-secret-your_key_here"
# Error handling
Errors are always returned as JSON with a success: false flag and a human-readable error message. Failed paid requests are automatically refunded.
{
"success": false,
"error": "Insufficient token balance. Top up to continue.",
"code": "insufficient_tokens",
"balance": 0,
"topup_url": "https://tumamaoni.com/api",
"tokens_per_request": 1
}
Status codes
| Code | Meaning | Notes |
|---|---|---|
400 | Bad request | Invalid JSON or missing/incorrect fields |
401 | Unauthorized | Missing, invalid or expired key |
402 | Insufficient tokens | Top up at the topup_url returned in the body |
403 | Forbidden | Key suspended, wrong key type, or domain not allowed |
404 | Not found | Unknown endpoint or resource |
429 | Rate limited | Daily request cap reached — resets at midnight |
500 | Server error | Something broke on our side |
502 | Gateway error | CamelPay could not be reached during topup |
Refunds
Tokens are charged when a paid request begins and refunded automatically if the request ends with a 4xx or 5xx status. Refunds appear in your Token history as refund transactions.
402 by pointing the user to the returned topup_url — your app never has to hard-code the topup page.# Rate limits
Each API key has a daily request budget that resets at midnight (Tanzania time). Limits apply per key, not per account. If you have paid for tokens, there are no rate limits.
| Key type | Daily limit (Free tier) |
|---|---|
| Secret | 1,000 requests / day |
| Publishable | 100 requests / day |
When a free key hits its cap, the API returns 429 with the limit in the error payload. Zero-token endpoints (keys, balance, usage, topup) count toward your daily cap too, but never cost tokens.
# Support
We're here to help you integrate.
- Developer portal: tumamaoni.com/api — keys, billing, usage analytics
- Documentation: tumamaoni.com/docs/api
- Email: support@tumamaoni.com
- Business dashboard: tumamaoni.com/dashboard