Features

Everything Njiwa does, and the things it does not

Which channels Njiwa handles and what each of them can do, what the people answering see when they open the Desk in the morning, and how a message you send from your own code gets there. The last section is the things it does not do, which is the part worth reading twice.

The message types, scopes, retry schedule and pacing on this page are read out of the running product when the site is built, so what you see here is what the API does today.

Start a 7 day trial Read the documentation

Channels

One inbox, whichever way the customer reached you

A channel is a place customers write to you from. Njiwa handles WhatsApp, Facebook Messenger and Instagram direct messages today, and a conversation is a conversation whichever of them it arrived on: the same list, the same reply box, the same history.

WhatsApp, on a number you already own

Link it by scanning a code from the phone, the same way you would link a laptop, or use the number Meta issues you on the Cloud API if you have been through their verification. Both look identical from the inbox and from your code, and Njiwa always says which of the two a number is on.

Facebook Pages, with one button

Connect the Page and its Messenger conversations appear beside your WhatsApp ones. A reply typed in Njiwa arrives in Messenger as the Page. Nobody is asked for an app id, a token or a webhook address, because the Facebook app is ours rather than something each business has to create.

Instagram direct messages

Connect the Instagram professional account attached to your Page and its direct messages land in the same list. The person who answers customers does not need the Instagram password, which is usually the actual reason those messages go unanswered.

Every conversation says where it came from

A small mark on the row and in the conversation header, in that channel's own colour with the channel's name beside it, so whoever is answering always knows which channel their reply is going out on. WhatsApp is marked too: leaving the commonest one blank means the answer to 'which channel is this' is the absence of a mark, which nobody can see.

One question above the list: where did this come from

One menu, and it narrows the Desk to a channel or to one of your own numbers. Not both at once, because a number belongs to exactly one channel and asking for Instagram and the shop's WhatsApp line together is a filter that can only return nothing. It narrows on the server rather than in the browser, which matters more than it sounds: the browser holds one page of conversations, so filtering there empties the quiet channel out as soon as the busy one has more than a page of its own.

Comments, not only messages

A comment on a Facebook or Instagram post is public and sits under somebody's post where their customers are reading it, so it is not a conversation and Njiwa does not file it as one. It has a screen of its own, described below.

The 24 hour rule, said out loud

Facebook and Instagram let you reply for 24 hours after the customer's last message and then close the conversation until they write again. That is Meta's rule and not ours. Njiwa counts it down on the conversation rather than letting a reply fail silently. It uses one of Meta's message tags and only one: the Human Agent rule, which gives a person answering a customer up to 7 days where the Page is approved for it. It goes on a reply somebody typed and never on an auto-reply or a campaign, which is what that feature is granted for - the marketing tags that reopen a window for promotions are how businesses lose their Page, and Njiwa does not touch them.

New channels arrive in the same list

The inbox, the search, the roles, the per-member access, the media handling and the deletion all key off the account rather than the channel. So adding a channel is work for us and nothing for you: it turns up in the list you already read.

Sending

One endpoint, and the body says what kind of message it is

Everything goes to the same URL. What you are sending is decided by which key is in the body, so there is one request shape to learn rather than one per message type.

Eight kinds, and the key you use is the type:

  • text
  • image
  • video
  • audio
  • document
  • sticker
  • location
  • contact

Numbers in the format you already have

A number with a plus and spaces, a bare international one, or a local one resolved against the country code of the number you are sending from. A business in Lagos reaches a Nigerian number and one in London reaches a British number, without either of them normalising a database first. Where Njiwa genuinely cannot tell which country a local number belongs to, it says so and tells you what to send instead, rather than guessing and delivering to a stranger.

Files three ways

By public URL, by direct upload, or by a media id you stored earlier and can reuse across as many sends as you like. The type is read from the file's own bytes rather than from what it is called, so a PDF somebody renamed .jpg still arrives as a PDF.

An answer while you are still looking at the terminal

Add wait=true and the call holds for up to fifteen seconds and returns the real outcome. Your first message is a result you can see rather than a promise you have to go and check.

Safe to retry

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

Paced on purpose

Messages leave a number at a set interval rather than as fast as the socket allows, and the interval belongs to the number, so a careful one and a busier one can move at different speeds. Blasting is the fastest way to lose a number.

Whichever of your numbers you meant

One account can hold several. Name one per call, or leave it out and the account's default sends, so a business with a single number never has to mention it at all.

Receiving

Replies come back as a conversation, not as a second log

An API that only sends is half a product. Somebody answers, and what happens next decides whether anyone outside the engineering team can use this.

Inbound on your webhook

A reply reaches your endpoint usually within a second of being sent, carrying who it came from, the text or the media, and the conversation it belongs to.

One thread per person, both sides

What they sent and what you sent, oldest to newest, in one place. Not outgoing messages in one list and incoming ones in another, which is two lists nobody can read as a conversation.

Answer from the console

Open a thread and reply to it. This matters more than it sounds, because the person who needs to answer a customer is almost never the person who wrote the integration.

Or answer without anybody there

Auto-reply rules belong to a number: match what arrived, send a reply. Out of hours, an acknowledgement while a human gets to it, a menu of options. Rules are tried in the order you put them in and the first match wins, so one message never produces two replies - which the customer would blame on you rather than on the rule list.

What they send you is kept

A photograph of the damaged part, a signed form, a screenshot of the error. Media on an inbound message is stored with its real type, size and checksum, and the webhook carries a link to it that expires rather than a public URL sitting on the internet forever. The inbox opens it; the next section is about that.

The history is queryable

List conversations, read one in full, or fetch a single message by its id. What is in the console is in the API.

The Desk

Everything waiting for an answer, in one list

The screen a business actually lives in. Every channel arrives here, and the organising question is not which channel a conversation is on but whether anybody has dealt with it.

Unanswered, then answered

The list is in two parts, and a conversation moves between them on its own. Not 'waiting on you', because whether a reply is warranted is a judgement and who spoke last is a fact.

And an answer is a real answer

A reply that failed to send is not one. Neither is an auto-reply, nor a message somebody deleted, nor a campaign that happened to go to that customer. Njiwa compares when they last wrote with when somebody last actually answered them, so a blast to four thousand old conversations does not quietly mark four thousand people as dealt with.

Most of what arrives needs no reply

'Thanks', a thumbs up, a wrong number. Settle it and it leaves Unanswered without anybody pretending to have answered. If that person writes again they are waiting again, because it is a moment rather than a flag.

Read is for the team, not for you

A conversation a colleague has opened stops being bold for the other four. A shared inbox where everybody carries their own unread count is five people each checking the same message.

A bell that rings for three things

A customer wrote. Somebody commented on a post. A message you sent failed. That last one is the reason the bell exists: a failed send is not in the inbox, nobody is waiting for it, and the first sign of it is usually a customer asking why they never heard back. Your own colleagues answering customers is not news and does not ring.

And a sound, for the half of the day nobody is watching

A short tone when a customer writes or comments, a lower one when a send fails, and several arriving together make one sound rather than one each. It is off until you switch it on, and it belongs to the browser you switched it on in rather than to the account, because whether your machine should make a noise is not a decision for whoever set the account up.

A reply typed on the phone is a reply

Somebody picks up the handset and answers a customer there. That message is in the thread, labelled as having come from the WhatsApp app rather than from Njiwa, and the conversation stops being unanswered. Nothing is billed for it, because you did not send it through us.

Send a failed one again

One button on the message that failed. It is a new message rather than the old one dragged back to life, and a double click is still one message.

Search, and narrow to what matters

Search across conversations, or narrow to one channel, to one of your own numbers, to groups or to people, to only the unanswered, or to only the unread. The narrowing happens on the server, so 'show me Instagram' means every Instagram conversation rather than the Instagram ones that happened to be in the page the browser had - and 'show me groups' finds the ones older than anything on the screen.

Write to somebody who has never written

The Desk could only ever answer, and starting a conversation meant leaving it for another screen, which left you in a message log rather than in the thread you had just begun. There is a control in the page head now: give a number, and Njiwa checks it is on WhatsApp before you type, then holds a row for it on the left until the first message makes it real.

Inside a conversation

Open one and the photograph is a photograph

Everything a customer sends opens where it arrived: the photograph is a photograph, the invoice is readable, and the voice note plays.

Pictures and video, in the thread

They open where they arrived, at the shape they were taken in, so a thread of six photographs is six photographs rather than six identical grey rows. Tap one and it fills the screen, with the arrow keys moving through the rest of what that person sent. Video plays in place, with the controls the browser already has.

Documents read without being downloaded

A PDF invoice, a signed form, a delivery note: it opens inside the conversation and you read it there. Nothing lands in a downloads folder to be found again later, and nothing has to be opened in another application to see whether it is the right one. Every file still has a Save on it, for the one you do want to keep.

Voice notes play where they are

The one message type nobody can skim. It sits in the thread with its length on it and plays on a tap, so a two minute explanation of what went wrong is something you listen to rather than something you promise to get to.

A dropped pin and a shared contact are readable

A location arrives with whatever the customer named it and a link that opens it in a map. A shared contact arrives with the name and the number out of the card, rather than as an attachment nobody can open.

Names, not numbers

A conversation is headed by the name you saved for that person, or the one WhatsApp reports if you have not saved one. A list of phone numbers is a list nobody can read at a glance, and finding the right thread should not be an exercise in remembering digits.

Ticks that mean what they mean elsewhere

One tick for sent, two for delivered, two in colour for read, and something visibly wrong for a message that failed. The same shorthand everybody already reads, so nobody has to be taught this screen.

Reply with a file in one go

Attach a photograph, a document or a recording, add a caption if it needs one, and send. It uploads and sends in the same step rather than asking you to store the file first.

Write it the way it will be read

Bold, italics, strikethrough, a bulleted list, a numbered one and a quote, with the buttons for them in the composer. They put WhatsApp's own markers on the text rather than markdown, so what the button does and what the customer sees are the same thing, and the box grows as the message does instead of keeping a long reply inside two lines.

Change what a message says

Correct a price or a time in a message you already sent and the customer's phone shows the new wording, marked as edited, the same as if you had done it in WhatsApp. It is your own text messages, on a number linked by scanning a code, for about fifteen minutes - WhatsApp's window, not ours - and Njiwa only rewrites its own copy once WhatsApp has taken the change, because a record that disagrees with the phone it was sent to is worse than no edit at all. What it said before is kept.

A pasted link arrives as what is behind it

The title, the description and the picture the page carries, drawn as a card under the message, both for links a customer sends you and for one you are about to send. A site that is slow, down or private is a plain link and never a slow conversation. On your own message the card is a switch, so a reply that should be the words and not somebody else's artwork can be sent without one.

Everything else the thread carried

Reactions sit under the message they are about. Stickers arrive as stickers. A poll shows its question and its options and says plainly that the votes cannot be read, because WhatsApp encrypts those with a key only the person who made the poll holds. A message type WhatsApp has and Njiwa does not understand says so rather than appearing empty.

Groups, by the name of the group

A group conversation is headed by its subject and says how many people are in it, so a delivery group and a supplier group are two different threads rather than two rows both called Group chat.

You can take a message back

Deleting one you sent withdraws it from the customer's phone as well, inside the two days WhatsApp allows and on a number you linked by scanning a code. Past that, or on somebody else's message, all that is left is removing it from your own record, and Njiwa offers that as a separate and clearly labelled thing rather than dressing it up as the first one. Either way the line stays as a marker saying a message was deleted, because a conversation that quietly loses a line is one nobody can trust.

React without sending a message

A thumbs up on the message it is about. It is not a message: it is not paced, it is not billed, and it does not count against your allowance. Tap the reactions under a message and it says who left which one, which in a group of nine is the whole of the information.

Or remove the whole conversation

An owner or an admin can delete one outright, which clears the messages and the files and gives the space back. It clears your copy and nothing else, exactly as deleting a chat on WhatsApp itself does, and the console says so in those words before it asks. Unlike one deleted message it leaves no markers behind, because four hundred of them would not be a deleted conversation.

Signals

What your customers asked for, counted

Njiwa's third part. Core sends and receives, the Desk is where people answer, and Signals reads what came through both and says what it means - what people wanted that you could not serve, where conversations die, and which advertising brought them. Nobody is opted into it: it is agreed to once, by an owner, and the paid half is prepaid rather than charged to a card.

A report with no AI in it

Terms and phrases out of your own messages, ranked by how many different people said them rather than how many times they were typed - so one customer sending forty messages about one thing is one person who wanted one thing. What is rising this week, when messages actually arrive, and how long your first reply takes. Free, however often you open it.

Reply times counted twice

Once with your autoresponder and once without it. A robot answering in four seconds is not you answering, and a median that mixes the two is a number that flatters you into leaving people waiting.

A deep read of whole conversations

The paid half reads what somebody asked for, what you said back and how it ended - so "tyres" becomes "195/65 R15", and "they went quiet" becomes "they stopped replying after you gave the price". You are told what it will cost before it runs, worked out from the actual text rather than an average.

Every figure opens onto the people behind it

A report saying thirteen people were never answered is worth nothing if you cannot find the thirteen. Click the figure and they are there by name, and clicking one opens that conversation in the Desk with the reply box under it. The list and the figure are always the same count.

Reading again pays only for what changed

Read a month on Monday and again on Friday, and Friday charges for the conversations that moved. The report still covers the whole month: one that covered only the new conversations would rank a month of demand by what four people asked this week.

Groups in or out, and marked either way

A group on a business number is usually the staff rota or the suppliers' thread, so groups are left out by default. Switch them in and the report says how much of every figure came from a group, and you can look at either half on its own.

Which advert brought them

A click-to-WhatsApp advert attaches its id to the first message somebody sends, and Njiwa keeps it - so the spend and the conversation it bought are one record. An advert id that arrived before you switched Signals on is gone for good; there is no archive to recover it from.

Prepaid, with a statement

Credit you top up rather than a bill that arrives. Every top-up and every charge is on a statement you can download as a spreadsheet or have sent to a WhatsApp number as a document. Switching Signals off does not touch the balance, and unused credit can be refunded to the card that bought it.

Meetings

Book the meeting the conversation asked for, without leaving it

A customer asks to meet on Thursday. Answer it from the composer: pick the day, and the invitation goes out of your own Google Calendar without opening another tab or typing their address from memory.

A month, not a date field

Picking a day for a meeting is a question about which day of the week it lands on and how far away it is, and a text box answers neither. Pick the day, the time and how long, add a Google Meet link if it is that kind of meeting, and book it.

Their address is already in the box

Filled in before anybody types it, from the last meeting somebody booked with that person or from their contact record, and the panel says which of the two it came from - because an address that appears out of nowhere is a thing people delete, and one that says where it came from is a thing they check. Booking writes it back onto the contact, so the address book learns from the meeting. It never writes over an address the contact already had.

More than one guest

The customer, and whoever else needs to be there. One address, several separated by commas, or a list from the API.

It is your own calendar, not the account's

A colleague connects their own Google account: the meeting goes in their calendar, the invitation is sent from their address, and the reminder buzzes on their phone. Nobody else on the account can see, use or disconnect it, not even an owner. Somebody with a work Gmail and a personal one can connect both and choose, and somebody who answers customers for two businesses connects it once.

Njiwa asks Google for less than it could

Permission to create and change events, and nothing else. Not to read the calendar's settings, not to see the other calendars on the account, not to delete one. A consent screen that asks for less is also a consent screen more people finish.

The customer is told twice, and you see it first

Google emails them the invitation, with who it is from at the foot of it, following the same signature switch your messages follow. Then the booking drops into the reply box as a message saying what was booked and when, with the Meet link if there is one - in the box rather than sent, because a message to a customer should be read by the person sending it first.

What it will not book

A meeting in the past, one that ends before it starts, one longer than a day, or a time zone that is not a real one. All four are what a broken integration sends, and all four would otherwise be a real event in somebody's real calendar.

Comments

The public half of a Facebook or Instagram Page

Somebody asking the price under your post is a customer, and they are asking in front of everybody else who is reading it. Comments have a screen of their own, and it is deliberately not the inbox with a different noun on it.

Grouped by the post, not by the person

Three comments under one photograph is one job. The same person commenting on two posts is two. So the list is a stack of posts with what was said under each, which is the shape of the work rather than the shape of the database.

Answer in public, as the Page

Type a reply and it appears under their comment, from your Page or your Instagram account. It is sent to Facebook first and stored second, so a reply you can see in Njiwa is a reply that went out: 'did that actually post' is the one question this screen must never leave open.

Hide, rather than delete

Facebook would let a Page delete anybody's comment. Njiwa will not. Hiding takes it off the post for everybody but its author and the people who follow them, it is reversible, and Facebook never tells them - which is the honest tool for spam and for abuse. Deleting is offered only for your own replies, and a deleted one leaves a marker rather than a gap.

Facebook and Instagram, told apart

Every post carries the same channel mark the Desk puts on a conversation, and a chip narrows the list to one of them. They are not sorted into blocks: this is a queue of things waiting for an answer, and burying the oldest unanswered comment on the quiet channel under every new one on the busy channel is how a customer gets forgotten.

You are told how many are waiting

On the navigation and on the overview, and in the same bell that tells you a customer wrote. A comment nobody has answered is the most visible unanswered question a business has, because it is sitting on their own post.

Delivery

Once we answer with an id, sending it is our problem

The id comes back before the message has gone anywhere. That is deliberate, and it is only honest if everything after it holds.

  1. accepted
  2. sent
  3. delivered
  4. read

And failed, which can happen at any of those points and always arrives with a reason attached.

Accepted is not delivered, and we will not pretend otherwise

WhatsApp taking a message is not the same as a person receiving it. Treating those as one thing is how a dashboard ends up green while nothing is arriving, which is a real way to lose a week.

Njiwa records the acknowledgement separately from the delivery. A message WhatsApp accepted and never delivered sits visibly at sent, because that is what actually happened to it.

It waits for a phone that is switched off

Nothing is thrown away for being early. The message goes when the number comes back, without you holding it and trying again later.

Retried, and safe across a restart

A send that fails for a moment is retried with a widening gap. If we restart in the middle of one, it is picked back up and finished rather than quietly lost.

Sent, then delivered, then read

Each stage is posted to your endpoint as WhatsApp reports it, and stored, so 'did they actually get it' is a question you can still answer months later.

A failure says why

A message that genuinely cannot go is marked failed with a code and a sentence somebody can act on. Nothing is left sitting in a queue nobody is watching.

Webhooks

Signed, retried, and on the record

Everything Njiwa learns about a message it tells you the same way: a POST to your endpoint that you can prove came from us.

Six attempts on a widening gap, and then the delivery is marked failed rather than retried into next week:

  • at once
  • 30s
  • 2m
  • 10m
  • 1h
  • 6h
Verifying a delivery, in full
import hashlib, hmac

def verify(raw_body: bytes, header: str, secret: str) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    signed = parts["t"].encode() + b"." + raw_body
    expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts["v1"])

You can prove it came from us

Every delivery carries a signature header holding a timestamp and an HMAC SHA-256 over that timestamp and the exact body. Your handler verifies it in about four lines, and a request somebody captured cannot be replayed at you tomorrow.

Named and identified

One header says which event this is and another identifies the attempt, so a duplicate arriving after a timeout is recognisable as the same delivery rather than a second one.

Every attempt is on the record

What we sent, what came back, the status code and the body. When your endpoint was down for an hour, that hour is in the log rather than in somebody's memory of it.

Send one again

Once the endpoint is fixed, resend a delivery from the console or the API instead of asking a customer to place the order again.

And the signing secret can be read back

The secret your handler verifies with is shown again to an owner who types their password, on the same terms as an API key, so rebuilding a server does not mean rotating a secret and redeploying everything that holds it.

Numbers

Linking a number takes about a minute

A number is a WhatsApp account Njiwa sends from. Add it, link it, and everything else on this page applies to it.

Scan a code, or type one

Scan a QR code from the phone the way you would link a laptop, or have an eight character pairing code sent to it and type that in instead. The console shows the socket state live, so you know it worked rather than hoping.

As many numbers as your plan covers

Each with its own name, its own webhook, its own pacing and its own rail. One of them is the default, and it is the one that sends when a call does not say.

And the name can be changed

The name is what the send screen offers, what the Desk puts on a conversation to say which of your lines it came in on, and what somebody picks when an account has more than one. A business that outgrows what it called a number can rename it without disconnecting anything.

Two rails, always labelled

The Web rail speaks the same protocol WhatsApp Web speaks, using a number you already own. The Cloud rail is Meta's official Business Cloud API. Your code is identical either way, and every number says which one it is on.

Stop it and start it

Log a number out, reconnect it, or move the default to another number, without going to find the phone.

Contacts and campaigns

A list of people, and a careful way to message them

Most businesses have the list already, in a spreadsheet somebody maintains. This is what happens once it is somewhere useful.

Contacts, not a spreadsheet

A name, a number and the fields you care about, held against the account and reachable from the API. Import many at once rather than one call per row.

Check who is actually on WhatsApp

Ask which of a list of numbers have WhatsApp at all before you send anything. Messaging numbers that were never going to receive is wasted, and it is a good way to look like a nuisance to WhatsApp.

Lists, so the audience is a choice

Put contacts on a named list and send to that: the customers who bought last month, the parents of one class, the tenants of one building. A list is membership rather than a copy, so deleting one deletes nobody, and correcting somebody's number once corrects it everywhere they appear.

Campaigns that walk rather than run

Send to a list, or to everybody, at the number's own pace. Watch it go and pause it if something looks wrong. A campaign is a thing you can stop, which a for loop in a script is not.

More than one message each

A photograph, a second photograph and the words underneath are three messages to every recipient, and Njiwa sends them in order rather than making you run the campaign three times. It also says out loud what that costs: each one is another message to everybody, so three messages to four hundred people is twelve hundred against your allowance and three times as long to finish.

Per recipient, not just per campaign

Who it reached, who it did not, and why not. A total that says 'sent 4,000' without saying to whom is a number nobody can act on. Progress counts what has been attempted rather than what has been delivered, because a campaign where everything failed sitting at nought percent looks like a campaign that never started.

Your team

More than one person can answer, and you decide what each can see

One login shared around an office is how a WhatsApp number ends up with nobody accountable for it. So people have their own, and what they can reach is a decision somebody made rather than an accident.

Every package includes a number of people, and that number is the limit. Starter 2, Growth 4, Scale 8, Team 15, Business 30, and more on the high volume packages. An invitation past what your package covers is refused rather than accepted and billed, and the refusal names the package that would carry them. Removing somebody frees their place immediately, and the invoice is the package and nothing else: an account cannot grow a bill by adding somebody. The pricing page lists what each package carries.

Invite by email, in a minute

They get a link, choose a password and land in the account. Nothing is installed and there is nothing to configure. Somebody who already uses Njiwa at another business keeps the password they have.

Four roles, and the difference is real

An owner runs the account including the plan and the billing. An admin does everything except change the plan. An agent reads conversations and replies to customers. A viewer reads and cannot send. Every refusal happens in the API, whatever the screen drew.

Per number, not per account

A business with a sales number and an HR number can put the sales team on the sales number only, and the HR conversations stay where they belong. It fails closed: somebody restricted to a number they no longer have access to sees nothing rather than everything.

Withdraw access without losing the history

Suspending somebody stops them signing in on their next request and keeps every message they ever sent attributed to them. Somebody who leaves is removed, not deleted, because who answered a customer in March is a fact worth keeping.

The account always has an owner

Removing the last one, suspending them, or moving them off the role is refused. An account with no owner cannot change its own plan or appoint anybody, which makes it a support ticket rather than a business.

A record of who changed what

Every invitation, role change, suspension and removal is written down with who did it, when, and from where. It is your record, in your console, and it is the thing that settles an argument about when somebody was added.

Who sent it

Every outgoing message carries who sent it

An inbox that cannot tell you who replied is a filing cabinet. This is the part that makes a shared number workable, and the part that lets your own software appear in it without paying for anything.

Your users, in the inbox, at no cost

Send a name with the message and that is who the inbox says sent it. A shop with four hundred sellers can show which seller sent an order confirmation without any of them being a Njiwa user, because a name on a message is a label and not an account. Nothing about it touches what you pay.

Four kinds of sender, told apart

A person in the console, an API key, an automation like an auto-reply or a campaign, or Njiwa itself. They are recorded differently because they mean different things when something has gone wrong, and the inbox says which without anybody having to work it out.

The name is kept, not looked up

Whoever sent it is written onto the message as it goes. Somebody who leaves the company two years later does not silently erase their name from six thousand messages, and renaming a key does not rewrite history.

The customer does not see any of this by default

WhatsApp shows the recipient one business number. There is no per agent identity on a shared number, so who replied is something your console knows and your customer does not. We would rather say that plainly than let anybody assume otherwise.

Unless you switch signatures on

One setting puts the sender's name in front of the message, in wording you choose, so a customer knows they are talking to Wanjiru. It is off until you turn it on, because adding characters to somebody's message without being asked is changing what they said. It never touches an API send or an auto-reply, where a person's name would be a lie about who wrote it.

It is in the API too

The sender comes back on every message the API returns, as a ready made line you can print and the parts underneath it if you want to lay it out yourself. What the console shows, your own screens can show.

Keys and access

A live key on day one, and scopes when you need them

Access is decided by the key, so what a key can do is worth being able to say precisely.

Ten of them, and a key holds exactly the ones you gave it:

  • messages:send
  • messages:read
  • instances:read
  • instances:write
  • media:read
  • media:write
  • webhooks:read
  • webhooks:write
  • contacts:read
  • contacts:write

A live key and a test key

The test key validates every request, stores every message and fires real webhooks, and delivers nothing to WhatsApp. Build against it, rehearse the whole thing, then change one key. It sends from your own number, so what you rehearsed is what will happen.

Locked to one number

A key can be tied to a single number. A key that leaks out of a repository then cannot send from the others.

Readable behind your own password

Lose the one copy of a key and an owner can read it back, by typing their password: a handful of attempts and then a wait, never while somebody is supporting your account, and every reveal written into the log with who did it and when. It saves minting a replacement and finding every place the old one was pasted. The key itself is sealed with a secret that is not in the database, so a stolen copy of the database opens nothing on its own. Some older keys are stored only as a hash and can never be shown, because we genuinely do not know them - the console marks which, and those are replaced rather than read.

Revoke without downtime

Mint the replacement, deploy it, revoke the old one. Nothing has to stop while you rotate a key.

The console

A screen for the people who did not write the integration

Everything the API does has somewhere to be looked at, because the person asking whether a customer got their invoice is rarely holding a terminal.

Grouped by the job, not by the table

The Desk, the comments and the contacts together, because that is a day's work. Sending a message, a campaign and the auto-replies together, because those are the messages that leave without a customer having written first. Connecting a channel is its own group, and so is everything only a developer needs.

The developer half is named so it can be skipped

API keys and webhooks sit under a heading that says Developers, because for most accounts that is nobody's job. A group whose name tells the majority to stop reading does more for them than two unexplained items filed under something they do need.

Every message, and what happened to it

The flat log with its filters, for the morning something did not arrive and you need to know why. It is the record, so it shows what a conversation view hides.

Send one by hand

Type a message and send it from a linked number. For the one off, and for proving the whole path works before any code does.

What you have used, and when it runs out

Messages sent and received and media stored, against what the package covers. Njiwa writes at eighty percent and again at the ceiling, for messages and for files both - storage fills up by customers sending photographs, which nobody presses a button to do, so nothing else would announce it until an upload failed. It also does the arithmetic nobody does: four days into a cycle at four hundred a day against five thousand reads as sixteen percent used and is a package that ends on the thirteenth, so it says the date while there is still something to do about it.

Photographs are made smaller on the way in

A phone camera writes four thousand pixels and a conversation shows three hundred, so a stored photograph is re-encoded to something nearer what anybody looks at. Never if it would not save enough to be worth it, never for video or a PDF, and never at the cost of the message: a file a codec could not handle is stored exactly as it arrived. Your storage allowance goes several times further and nobody had to do anything.

It works on the phone in your pocket

Which is where a lot of this is actually read. The whole console, not a cut down version of it: the Desk, the conversation, the composer and the emoji panel all work at the width of a handset.

Integrations and SDKs

For the shops, none of this is code at all

If your orders live on one of these, an integration sends the messages and you write nothing. Everything above still applies, because underneath it is the same API.

All 9, and what each one sends

Writing it yourself instead? There are thin SDKs for PHP, Node and Python, and not one of them is compulsory. It is an HTTP API, so curl is a supported client.

The edges

What it does not do

Four things worth knowing before you build on this rather than after. None of them is a plan to fix; they are what this product is.

Taking a message back is two days, and changing one is fifteen minutes

A message you sent can be withdrawn from the customer's phone for about two days, and its wording changed for about fifteen minutes. Both are WhatsApp's own windows rather than ours, both are only on a number you linked by scanning a code, and changing one is only your own text messages. Past those, and on the Cloud rail, what left is what they have. Nothing can be taken back or changed in a Facebook or Instagram conversation at all.

The Cloud rail has a window

Outside twenty four hours opened by the customer writing to you, the Cloud rail carries only templates you got approved in advance. That is Meta's rule and not ours, and it is the main reason to know which rail a number is on.

The Web rail is not an official Meta product

It speaks the same protocol WhatsApp Web speaks, from a number you already own, with no verification to pass and nothing per message. Meta does not endorse it, and we will never tell you otherwise. The comparison page is blunt about what that means.

It is not a blasting tool

Pacing is the default rather than a setting somebody remembers, and campaigns walk. If the plan is to reach ten thousand strangers this afternoon, this is the wrong product, and the number would not survive it anywhere else either.

The two rails, compared side by side

Send one and see

A test key that rehearses the whole thing against your own number and delivers nothing, and 3 seconds between messages by default because the number is yours to keep. No card.

Start a 7 day trial