Everything a storefront for your store needs to talk to Soko Sensei: which headers to send, the endpoints available, and what they return.
Your details
| API base URL | https://app.sokosensei.com/api |
Store ID (X-Store-Id) |
YOUR_STORE_ID |
API key (X-Store-Key) |
Your storefront API key |
Keys are generated under Settings → Integrations → Storefront API key. A new key is shown once; regenerating it stops the old one immediately.
Headers
Send these on every request:
| Header | Value |
|---|---|
Accept |
application/json |
X-Store-Id |
Your Store ID (all endpoints except store resolve) |
X-Store-Key |
Your storefront API key |
- A wrong key is rejected with
401. - A missing key is accepted for now, and store resolve returns a warning in
data.warnings. Once key enforcement is switched on, requests without a valid key are rejected with401. - The key travels with browser requests, so anyone inspecting your site's traffic can see it. It ties requests to your storefront; never use it as a password or put other secrets in your frontend.
Responses
Every response uses the same envelope:
{ "success": true, "message": "Products retrieved successfully", "data": { } }
Errors have "success": false, a readable message, and for validation errors (422) the field errors in data.
| Status | Meaning |
|---|---|
400 |
A required header is missing |
401 |
Invalid (or, once enforced, missing) API key |
404 |
Store, product, service or order not found |
422 |
Validation failed, or the request can't be completed (e.g. slot taken) |
429 |
Too many requests; slow down and retry |
502 |
A payment gateway could not be reached |
List endpoints return data.items and data.pagination (current_page, per_page, total, last_page). Use page and per_page (1–100, default 15) to page through results.
1. Load the store
GET /store/resolve — call this first. Send X-Store-Host (your site's domain) instead of X-Store-Id.
Returns the store's name, branding, contact details, socials, theme, payment_methods and warnings. Show only the payment options listed in payment_methods:
"flow": "stk_push"(M-Pesa): ask for a phone number, call itsendpoint, then poll the payment status."flow": "redirect"(Pesapal): call itsendpointand send the customer to the returnedredirect_url."test_mode": truemeans the store is on sandbox; no real money moves.
2. Products
GET /products— filters:search,category(category id),on_sale,is_featured(true/false); sort withsort_by(product_name,product_cost,created_at) andsort_dir(asc/desc).GET /products/categories— categories that have products, withproducts_count.GET /products/{id}— one product with its images.
3. Services and appointments
GET /services— filters:search,on_sale,requires_appointment,pricing_type; sort withsort_by(service_name,price,created_at).GET /services/{id}— one service with its images.GET /services/{id}/slots?date=YYYY-MM-DD— available time slots.POST /services/{id}/slots/{slotId}/book— body:guest_name,guest_email,guest_phone,description(required);guest_age,guest_gender,preferred_specialist_gender(optional).
For a paid service the booking response includes payment.order_type ("service") and payment.order_id; use them to take payment (section 5).
4. Checkout (products)
POST /checkout — body:
{
"items": [{ "id": "<product id>", "quantity": 2 }],
"firstName": "Jane",
"lastName": "Wanjiku",
"email": "jane@example.com",
"phone": "0712345678",
"delivery": "pickup",
"orderDescription": "Optional note"
}
delivery is pickup or delivery. The response's data.id is the order id to pay with (order_type "product").
5. Payments
POST /payments/mpesa— body:order_id,order_type(productorservice, defaultproduct),phone. Sends an M-Pesa prompt to the customer's phone.POST /payments/pesapal— body:order_id,order_type, optionalcallback_url(must be https on your store's own domain; defaults tohttps://<your domain>/checkout/complete). Returnsredirect_url.GET /payments/{order_type}/{order_id}/status— returnspayment_statusandpaid. Poll this every few seconds after starting an M-Pesa payment, or when the customer returns from Pesapal.
Payment endpoints allow 10 requests per minute per visitor.
6. Leads
POST /leads — body: name (required), email or phone (one required), interest, business_type, message, source (optional). Use it for contact or enquiry forms. Allows 10 requests per minute per visitor.