How it works

How it works, from signing up to answering a customer

Two things happen here and they are worth separating. Customers write to you on whichever channel they use, and somebody on your team answers them - that needs no code at all. And messages you would rather not type by hand go out on their own, which is where the integrations and the API come in. The four steps below cover both.

  1. Start your trial

    An email address and a password. Seven days, no card, and nothing is cut down: the trial is a Starter account with a clock on it.

  2. Connect your channels

    A WhatsApp number is a code you scan from the phone, exactly as you would link a laptop, and the console shows the connection live so you know it worked. A Facebook Page or an Instagram account is a Connect button and a list of the Pages you already run. Nothing asks you for a token or a webhook address.

  3. Answer, from one place

    Every conversation on every connected channel arrives in one list, marked with the channel it came from and sorted by whether anybody has dealt with it yet. Comments on your Facebook and Instagram posts have a screen beside it. Your colleagues each get their own login and a role, so somebody can answer customers without being able to touch your plan or your keys.

  4. Automate whatever you would rather not type

    Order updates, invoices, reminders. An integration does it if your shop runs on a platform we support, or one HTTP call does it if you would rather write it. Both send from the same number and land in the same conversation history.

Inbound

What happens when a customer writes to you

This is most of what Njiwa does.

  1. It arrives in about a second

    Whichever channel it came in on. A photograph is stored as a photograph, a PDF is readable in the conversation, a voice note plays where it landed.

  2. Everyone who should see it, does

    Every colleague with a login sees the conversation, unless you have restricted them to particular numbers, which fails closed. Nobody is passing a handset around and nobody is waiting for the person who has it.

  3. A reply goes back out the way it came in

    Type it and it returns on that channel, as your business. The customer sees your name and your number, not the name of whoever answered - unless you switch signatures on and decide they should.

  4. And it is on the record

    Every outgoing message keeps the name of whoever sent it, whether that was a person, one of your keys, or an auto-reply. So "who told the customer that" has an answer.

What a conversation looks like when somebody opens it

Peter MwangiActive now
Today

Saw your post about the drill sets

16:02

Hi Peter - the 18V set is in, 7,900.

16:05

Can I collect tomorrow morning?

16:06

Yes, we open at 8. I will set one aside.

16:07

Outbound

Where a message you send actually starts

Four ways, and most businesses never touch the second. A reply typed by a person in the inbox is the commonest of all and needs none of this; what follows is for the messages nobody should have to type.

Your shop runs on a platform we integrate with

Install the integration, paste your key, and tick the order statuses that should reach the customer. There is no code in this route at all. Nine platforms have one: WooCommerce, Shopify, Magento 2, PrestaShop, OpenCart, Shopware 6, Medusa, ERPNext and Frappe, and Odoo. Every event is off until you switch it on, so installing one sends nothing to anybody until you say so, and the wording of every message is yours to edit.

See the nine platforms

The software is your own

One POST to /v1/messages, from whatever you already write in. There is no SDK you are obliged to use: if your language can make an HTTP request, it can send a WhatsApp message. There are thin SDKs for PHP, Node and Python if you would rather not write the HTTP yourself. You get a message id back straight away, and the delivery updates arrive on your webhook as WhatsApp reports them.

Read the quickstart

Nothing happened, it is simply time

Appointment reminders, renewal notices, the delivery window on the morning it opens. No order changed state and no customer did anything: a job ran. It is the same call, fired from cron or whatever runs your scheduled work. Send an Idempotency-Key with it and a job that runs twice still sends once, which matters more here than anywhere else.

Somebody writes back

A message you send is the start of a conversation, not the end of one. Replies arrive at your endpoint within a second as message.received, signed the same way the delivery updates are. If you would rather not build an inbox, the console already is one: every contact is a single thread with both sides of what was said, oldest to newest, and you can answer straight from it.

If you are writing it yourself
curl -X POST https://njiwa.upeo.ai/v1/messages \
  -H "Authorization: Bearer sk_live_your_key" \
  -d '{"to": "0712345678", "text": "Your order has shipped"}'
What comes back
{
  "id": "msg_01J9ZK4Q7M2X8P0R3V6T5W1YHD",
  "status": "sent",
  "to": "254712345678",
  "type": "text",
  "created_at": "2026-08-31T09:14:02Z"
}

After the call returns

What happens to a message once we have it

The id comes back before the message has gone anywhere, and that is deliberate. Once Njiwa has answered with an id, sending it is our problem rather than yours.

  • If the number is offline, the message waits for it. Nothing is thrown away for being early.
  • If a send fails for a moment, it is retried with a widening gap. If we restart in the middle of one, it is picked back up.
  • As WhatsApp reports it, message.status is posted to your endpoint: sent, then delivered, then read.
  • When somebody replies, message.received arrives the same way, usually within a second.
  • Every delivery is signed with HMAC SHA-256 and timestamped, so your handler can prove the request came from us and a captured one cannot be replayed at you later.
  • A message that genuinely cannot go is marked failed with a reason you can read, rather than left in a queue nobody is watching.

Send an Idempotency-Key and a repeat of the same request returns the same message id instead of a second message, so a timeout on your side stops being a decision about whether to risk sending twice.

WhatsApp only

Which WhatsApp rail you are on

Njiwa can put a message on WhatsApp by two roads, and they look identical from your code. The Web rail speaks the same multi-device protocol WhatsApp Web speaks: no approval, a number you already own, nothing per message from Meta, and about five minutes to the first message. The Cloud rail is Meta's official Business Cloud API: business verification, a dedicated number, and a charge per conversation.

It matters for more than billing. Outside a twenty four hour window opened by the customer, the Cloud rail only carries templates you got approved in advance. Every number in Njiwa is labelled with its rail, in the console and in the API, so you always know which one you are on.

The two rails, compared side by side

What people send

The messages this ends up being

Invoices and receipts

Attach the PDF your system already generates and send it to the number on the order. It arrives in the same app the customer is already reading.

Delivery and order updates

Tell someone their order has shipped without paying per message for an SMS that may not be read.

Appointment reminders

Fire them from a cron job. Replies come back to your webhook, so a customer answering the reminder reaches a person.

Two way support

Incoming messages arrive at your endpoint within a second. Reply from your own system, or from the console, where each customer is a single thread showing both sides of what was said.

Start with the test key

Every account has two. The one beginning sk_test_ checks every request, stores every message and fires real webhooks, and delivers nothing to a phone. The one beginning sk_live_ sends for real, to real people. Build against the test key, rehearse the whole thing, then paste in the live key. Nothing else changes.

Start a 7 day trial Read the documentation