Follow one step at a time. You do not need to be a computer expert. When you see a dark box, copy the words inside it exactly.
This key is like a house key for your TuMicha deliveries. Keep it private.
tm_live_. Copy it and keep it somewhere safe (notes app or password manager).
You will paste it into Zapier or give it only to your website helper — never post it on social media or in a public chat.
Zapier is a website that connects apps with buttons. You will send new orders to TuMicha, and you can also get delivery progress back into Zapier.
Copy this address
tm_live_YOUR_KEY with the real key you copied earlier.
Header 1 — name
Header 1 — value (put your real key after the word Bearer and a space)
Header 2 — name
Header 2 — value
Copy this message, then change the example values
{
"externalOrderId": "ORDER-10042",
"serviceType": "delivery",
"pickup": {
"address": "Shop 12, Independence Way, Lusaka",
"contact": "+260900000001"
},
"dropoff": {
"address": "Customer Home, Cairo Road, Lusaka",
"contact": "+260900000002"
},
"notes": "Leave with security if no one answers"
}
You still do Step set 1 (get the key). Then give your helper these three things:
tm_live_… key. Tell them to keep it only on the website’s private server — never in the customer’s browser.
What should happen after that:
Proof it is your business (headers)
Authorization: Bearer tm_live_YOUR_KEY Content-Type: application/json
Create a delivery
POST https://www.tumicha.co.za/v1/deliveries
Authorization: Bearer tm_live_YOUR_KEY
Content-Type: application/json
{
"externalOrderId": "ORDER-10042",
"serviceType": "delivery",
"pickup": {
"address": "Shop 12, Independence Way, Lusaka",
"lat": -15.3875,
"lng": 28.3228,
"contact": "+260900000001"
},
"dropoff": {
"address": "Customer Home, Cairo Road, Lusaka",
"lat": -15.4167,
"lng": 28.2833,
"contact": "+260900000002"
},
"notes": "Leave with security if no one answers"
}
Send two or more with { "deliveries": [ … ] } or a JSON array (at most 100). One object still returns { "delivery" }; a list returns { "deliveries", "summary", "errors" }.
Look up or cancel a delivery
GET /v1/deliveries GET /v1/deliveries/:deliveryId POST /v1/deliveries/:deliveryId/cancel
Cancel only works while the delivery is still waiting for a driver.
Create a product (same key)
POST https://www.tumicha.co.za/v1/products
Authorization: Bearer tm_live_YOUR_KEY
Content-Type: application/json
{
"name": "Blue shirt",
"price": "199",
"sku": "SHIRT-BLU",
"barcode": "6001234567890",
"stock": 12
}
Shop-style title is accepted as the name. One wrapped item also works: { "products": [{ "title": "Blue shirt", "price": "199" }] }. Send two or more in { "products": [ … ] } (or a JSON array) to create or update them in one request — same SKU, then barcode, then name matching. Posting the same product again updates it instead of creating a duplicate. For a whole catalogue with your own field names, use Incoming mapping.
Create a service (same key)
POST https://www.tumicha.co.za/v1/services
Authorization: Bearer tm_live_YOUR_KEY
Content-Type: application/json
{
"name": "Haircut",
"price": "180",
"sku": "CUT-1",
"durationMinutes": 45
}
Two or more services: { "services": [ … ] } or a JSON array, same as products (at most 100).
Prefer no coding? Website Integrations → Incoming still maps your shop JSON for orders, products, and services.
Updates TuMicha sends to your site (same Order updates URL)
Content-Type: application/json User-Agent: TuMicha-Webhooks/1.0 X-TuMicha-Event: delivery.status_changed X-TuMicha-Event: product.created X-TuMicha-Event: product.updated X-TuMicha-Event: product.failed X-TuMicha-Event: service.created X-TuMicha-Event: service.updated X-TuMicha-Event: service.failed
{
"event": "delivery.status_changed",
"occurredAt": "2026-07-14T12:00:00.000Z",
"delivery": {
"id": "8f3c2a1b-4d5e-6f70-8192-a3b4c5d6e7f8",
"externalOrderId": "ORDER-10042",
"status": "assigned",
"previousStatus": "created",
"driverName": "Chanda Banda",
"driverVehiclePlate": "ABC 1234"
}
}
Product or service result (same Update link)
{
"event": "product.failed",
"occurredAt": "2026-08-21T12:00:00.000Z",
"ok": false,
"source": "api",
"error": {
"code": "bad_request",
"message": "This photo is too large. Use a file under 5 MB."
},
"input": { "name": "Blue shirt", "sku": "SHIRT-BLU", "barcode": "6001234567890", "price": "199" },
"product": null
}
Incoming mapped products and services use the same events with "source": "incoming". Your site should answer quickly with:
{
"received": true
}
Ready-made create snippet
async function createTuMichaDelivery(order) {
const response = await fetch('https://www.tumicha.co.za/v1/deliveries', {
method: 'POST',
headers: {
Authorization: 'Bearer tm_live_YOUR_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
externalOrderId: order.id,
serviceType: 'delivery',
pickup: order.pickup,
dropoff: order.dropoff,
notes: order.notes,
}),
});
if (!response.ok) {
throw new Error(`TuMicha create failed: ${response.status}`);
}
const data = await response.json();
return data.delivery; // save delivery.id against your order
}
Ready-made listener snippet
const express = require('express');
const app = express();
app.use(express.json());
app.post('/updates/tumicha', (req, res) => {
const { delivery } = req.body || {};
if (!delivery?.id || !delivery?.status) {
return res.status(400).json({ error: 'invalid payload' });
}
// Match your store order with delivery.externalOrderId, then update the customer.
res.status(200).json({ received: true });
});
app.listen(3000);
Waiting Driver assigned Picked up On the way Delivered
Sometimes an order is cancelled or fails. That is normal to handle too.