How AudioFlow came about — a service that transcribes WhatsApp voice notes automatically, on your personal number. A case study told without jargon: the decisions, the bug that overcharged people for three months, the wall WhatsApp put up halfway through, and the economics that make it work.
TL;DR — 40 seconds
You get a four-minute voice note. You're in a meeting, on the train, next to someone who's asleep. You can't listen to it. You'll deal with it later. Later becomes never, and three days on someone asks why you never replied.
It's a small, universal problem — the kind almost everyone has and almost nobody solves, because solving it is more work than it looks. AudioFlow is my attempt: you connect your WhatsApp once, and from then on every voice note that arrives comes back as text, in the same chat, without you doing anything.
This is the case study behind it. It isn't a technical manual — I wrote it for people who don't code. But it isn't a marketing piece either: the mistakes are in here, including one that cost real money and another I very nearly reported wrong.
There are two ways for software to talk to WhatsApp. Choosing between them decides what product you're even able to build — and it was AudioFlow's first decision.
Meta (which owns WhatsApp) offers an official door called the WhatsApp Business API. It's what companies use to send you "your order is out for delivery". It works well and it's stable.
But there's a toll: it requires a business account, approval from Meta, a phone number separate from your own, and per-conversation billing. For a company, that's normal. For an individual who just wants to read their own voice notes, it's a hard stop — nobody is going to register a business account and change phone numbers to transcribe messages from their family.
There's another way in, and you already use it: WhatsApp Web. When you open WhatsApp on your computer and scan that QR code, your phone is authorising a companion device — one more device allowed to see your conversations.
That's where AudioFlow comes in. It presents itself as another device linked to your account, exactly the way WhatsApp Web would. The difference is that instead of drawing a screen in front of you, it sits there waiting for voice notes.
Why this matters so much: it's the difference between "install this app, register a business account and change your number" and "scan a code, done". The entire product depends on people being able to use the number they already have.
That choice has a price, and I'm still paying it: it isn't the official door. When WhatsApp changes something, I find out at the same time as everyone else. I'll come back to that in section 5 — that's where I took the hardest hit.
From your side it's simple: audio in, text out. Underneath, a dozen steps run in sequence. I'll walk through all of them, because that's where the interesting decisions live.
Someone sends you a voice note
│
▼
[1] AudioFlow notices something arrived
│
▼
[2] Is this worth transcribing? ── no ──▶ dropped, zero cost
│ yes
▼
[3] Audio becomes text (Whisper)
│
▼
[4] Text clean-up (punctuation, corrections, filters)
│
▼
[5] Long recording? ── yes ──▶ [6] Write a summary (Claude)
│ no │
▼ ▼
[7] Do you still have quota on your plan?
│ yes
▼
[8] Text goes back to your WhatsApp
│
▼
[9] Audio and text are deleted. Only the duration remains.
Before spending a cent, the system asks: should this actually be transcribed? You configure that. You can skip very short recordings, skip specific contacts, skip groups, or also transcribe the voice notes you send.
It sounds like a detail, but it's what separates a viable service from one that burns cash. Every voice note that gets past this filter costs real money. Every one stopped before it costs nothing.
This is where Whisper comes in, an AI model that specialises in listening and writing down what it heard. It understands over 100 languages and works out which one is being spoken on its own — you don't have to tell it.
I use a provider called Groq, which runs that model very fast and very cheaply. I also keep a second provider on standby, OpenAI, in case the first one goes down. That standby arrangement has already taught me an expensive lesson — it's in section 6.
Raw transcription comes out as one solid block, with weak punctuation and sometimes no capital letters. It's technically correct and unpleasant to read.
So the text goes through a tidy-up: breaking into paragraphs, fixing capitalisation, applying corrections you registered yourself (handy for proper nouns and industry jargon — if Whisper always misspells your boss's name, you fix it once and never again), and optionally filtering profanity or translating.
This is the part people like most. If the recording ran past 30 seconds, a second AI model (Claude) reads the transcription and writes a summary of the main points.
And there's a design detail that seems trivial and isn't: the summary comes before the full transcription in the message you receive. On a phone, that means you read the gist without scrolling. If you want the whole thing, it's right below. Flipping that order would turn the product's most useful feature into something nobody ever sees.
Each plan gives you a number of minutes per month. Before sending the reply, the system checks whether you still have balance. That check became a case of its own — it's the whole of section 3.
After sending you the text, the audio and the transcription are discarded. They don't go to a database, they don't go to disk, they don't live anywhere.
What's left is the bare minimum to make the accounting work: how long the recording was, what language it was in, what it cost, whether it succeeded. The sender's number is stored scrambled by a process that only runs one way — you can tell that two voice notes came from the same person, you can't work out who that person is.
This isn't marketing decoration. It's an architecture decision with a practical consequence: even if someone broke into the entire database, there isn't a single message of yours to leak. The content simply isn't there.
This is the most uncomfortable story in the case study, and the most useful.
The system has to deduct the time it transcribed from your quota. The original calculation was written like this: take the duration in seconds, divide by 60 to get minutes, throw away the fraction, then add 1.
The intent was to round up — someone using 90 seconds should pay for 2 minutes, not 1. Except that formula doesn't round up. It rounds down and then adds a whole extra minute. The result:
| Actual recording | Deducted from your quota | Error |
|---|---|---|
| 5 seconds | 1 minute | 12× too much |
| 30 seconds | 1 minute | 2× too much |
| exactly 60 seconds | 2 minutes | 2× too much |
| 119 seconds | 2 minutes | fine |
| exactly 120 seconds | 3 minutes | 1.5× too much |
Look at the 5-second case. A five-second "sure, works for me" ate a whole minute of the plan. On the free tier, which gives 30 minutes, thirty short voice notes wiped out the quota — even though together they added up to two and a half minutes of actual audio.
It wasn't a user complaining. It was someone on the most expensive plan looking at their dashboard and finding it odd: the minutes-consumed number didn't match how much they felt they'd used. They were right. It read 799 minutes when real usage was 423.
And here's the part I don't enjoy telling. The bug was diagnosed, the fix was planned, the database was prepared to hold the correct count — and then it stopped. The task sat marked "in progress" for three months.
That whole time the system kept charging wrong, because preparing the database changes nothing on its own: it's like buying the paint and never painting the wall. The missing half was exactly the half that mattered.
The lesson: "in progress" is the most dangerous state a task can be in. "Not started" nags at you and demands attention. "Done" is settled. "In progress" looks like somebody's on it — and nobody is.
Correcting the formula was the easy part: count real seconds, rounded to the nearest second, adding nothing.
The hard part was fixing the past. Everyone had an inflated number on record. Each person's consumption had to be recalculated from the real history.
The original plan was to add up the duration of every transcription in the billing cycle. Before running it, I simulated the result — and just as well, because it was wrong again.
The reason is subtle. The system records the transcription before checking whether you have quota. That makes sense: first it transcribes, then it works out whether it's allowed to deliver. But it means there are recorded transcriptions that were never charged for — the ones that hit the limit and were blocked.
Adding everything up would charge people for audio they never received. In the simulation, one free-tier user would show 65 minutes when the real charged amount was 11. Six times too much. And all fifteen users with any consumption would have been hit, without exception.
The fix was to add up the history with a ceiling at the plan's limit. That way nobody enters the new model already over the line because of audio they never paid for.
With the correction live, everyone got quota back:
| Plan | Was showing | Actual usage | Returned |
|---|---|---|---|
| Advanced | 799 min | 423 min | 376 minutes |
| Business | 364 min | 106 min | 258 minutes |
| Basic | 157 min | 97 min | 60 minutes |
| Light | 115 min | 57 min | 58 minutes |
| Free | 120 min | 30 min | 90 minutes |
Nobody came out worse. It was the least that could be done — but it took three months longer than it should have.
This one is short and worth more than the last, because it's about how we fool ourselves when measuring.
While investigating the billing bug, I noticed an inconsistency: the system had 2,200 transcriptions on record, but only 1,429 billing events. Seven hundred and seventy-one transcriptions with no matching charge.
I pulled the thread. It turns out there are two paths a voice note can take: the main path, robust, which records everything properly; and a backup path, simpler, which kicks in when the main one fails. The backup path doesn't record the billing event.
I counted how many of the day's voice notes had gone down each path. It came to 70% on the backup path. In other words: the system's most expensive, best-engineered infrastructure was being bypassed most of the time.
I wrote that up as a serious finding. I was wrong.
I had counted by day. When I redid the same count by hour, the story changed completely:
| Hour | Main path | Backup path |
|---|---|---|
| 04:00 | 0 | 89 |
| 05:00 | 41 | 18 |
| 09:00 onwards | 6 | 0 |
It wasn't a chronic problem. It was an outage. A piece of the infrastructure had gone down two weeks earlier and come back that very morning, after a repair. Everything before 05:00 was the outage; everything after 09:00 was healthy.
By summing the whole day, I'd mixed the broken window with the normal one and arrived at a number describing a problem that no longer existed.
The lesson: averages hide events. A number aggregated over a period that contains an outage doesn't describe the normal state — it describes the outage, diluted. When a number looks alarming, look at its distribution over time before you go telling the story.
There is a real problem underneath — very long recordings still blow past a technical limit and fall onto the backup path. But it's rare and only affects long audio, not 70% of anything. It's documented with the right measurement and will get handled at the pace it deserves.
Remember how choosing the "side door" had a price? The bill arrived.
Around June 2026, WhatsApp started requiring a passkey to link a new device. A passkey is that fingerprint or face-recognition sign-in that replaces passwords — the key lives on your phone, in a compartment even you can't open and copy.
From a security standpoint it's excellent, and it was coming. From AudioFlow's standpoint, it's a wall.
The problem isn't in the code, it's in the design of the standard. The passkey rule says, in essence: this key can only be used on a page belonging to whatsapp.com. That's precisely the rule that stops a fake site asking for your fingerprint while pretending to be your bank.
AudioFlow isn't whatsapp.com. So it can't ask. And generating its own key doesn't help — the server rejects it, because the key has to be the one you created.
Before investing in working around this, I went to see how every other tool in the world was coping. The result was clarifying: they all hit the same wall, and none of them got over it.
Every one converged on the same answer — ask the user to produce the authorisation inside WhatsApp's own site, via a one-click browser extension, and relay that authorisation to the service. Including the paid providers: one commercial vendor uses exactly the same technique and admits on its own blog that it doesn't scale to hundreds of numbers.
That changed how I read the situation. The friction isn't a failure on my part — it's everybody's ceiling. AudioFlow's solution sits level with the best that exists.
The lesson: when you hit a wall, spend a day looking at how others dealt with it before spending a month trying to knock it down. If nobody got through, the problem probably isn't yours — and the conversation stops being "how do I solve this" and becomes "how do I live with it".
And one detail saves the product: the passkey is only requested at the moment you connect, once. After that, reconnections happen on their own. It's an extra step at sign-up, not a daily annoyance.
One of the things that surprised me most on this project was how cheap AI has become.
| Item | Cost per minute |
|---|---|
| Transcription (audio → text) | US$ 0.00067 |
| Summary (about half of recordings need one) | US$ 0.00075 |
| Total | US$ 0.0014 |
A seventh of a cent. A minute of audio transcribed and summarised by artificial intelligence costs well under one cent. A hundred minutes cost about fourteen cents.
| Plan | Price | Minutes | AI cost | Margin |
|---|---|---|---|---|
| Starter | R$ 29.90 | 120 | R$ 0.87 | 97% |
| Light | R$ 49.90 | 240 | R$ 1.74 | 96% |
| Basic | R$ 79.90 | 480 | R$ 3.47 | 96% |
| Pro | R$ 149.90 | 960 | R$ 6.94 | 95% |
| Business | R$ 499.90 | 3,840 | R$ 27.75 | 94% |
And the free plan, with its 30 minutes, costs about four cents a month per person. Cheap enough to work as a front door rather than a loss.
Here's the thing that flips your intuition: the AI cost is irrelevant. The cost is infrastructure that has to stay switched on.
Four of the six servers can't sleep. The WhatsApp connection has to stay up around the clock — if the server hibernates, your session drops. That means fixed cost running 24 hours a day, with one user or a thousand.
It comes to roughly US$ 20 a month in servers, plus the database. And that cost exists with zero customers.
The business conclusion: in a service like this, the bottleneck is never cost-per-use — it's conversion. Every new subscriber is almost pure profit, because the variable cost is negligible. What decides whether the business works is how many free users become paying ones, not how many minutes they transcribe.
One detail that nearly became an unpleasant surprise. Remember the standby transcription provider? It costs nine times more than the primary one.
While the primary works, the standby never fires and costs stay at the floor. But the standby engages by itself, silently, whenever the primary fails. If half the transcriptions started landing on it, transcription costs would quintuple without anyone noticing — until the invoice arrived.
And something worse than expensive already happened: the primary provider's key expired, the standby took over — and took over broken. It was misconfigured and returned the audio duration as zero. Since the system skips zero-length recordings, it started silently dropping everything. Two defects hiding behind each other: a plan B nobody exercised, concealed by a plan A that never failed.
The lesson: a backup plan that's never exercised isn't a plan, it's an assumption. If it only runs once everything else has already gone wrong, it will rot in silence — and you'll find out on the worst possible day.
AudioFlow was built with a method where the specification comes before the code: first you write what the system should do, then how, then you break it into small tasks and implement them one by one. Each task has a state — draft, in progress, in review, done.
It works well. Until it stops working.
In a recent audit, I compared what the documentation claimed against what was actually running. The result:
None of this broke the product. But it's exactly the sort of thing that costs the next person — or you, six months from now — an afternoon following instructions that don't work any more.
The lesson: documentation doesn't rot slowly and evenly. It freezes on a date. The code keeps moving and nobody tells the document. The question that exposes this isn't "is the documentation good?" — it's "when did someone last compare what's written against what's running?"
The fix was checking each claim against the production database and the live endpoints, not against what the task said about itself. Laborious, and the only approach that works.
AudioFlow is live today, transcribing real voice notes for real people. It's a small product with a disproportionate number of interesting decisions behind it.
If I had to sum up what I learned building it, it'd be this:
The technical choice that looks like a detail defines the product. Picking WhatsApp's side door over the official one wasn't an engineering preference — it's what made a product for individuals possible at all. It's also what left me exposed when WhatsApp changed the rules. Both came in the same package.
A billing error isn't like other errors. A misaligned button annoys people. A billing error takes money or service away from someone who trusted you. And it was the one that stayed open longest, precisely because it didn't shout — nobody files a ticket saying "I think I was charged 4% too much".
Measuring wrong is worse than not measuring. Not measuring leaves you uneasy, and unease makes you check. Measuring wrong gives you confidence — and confidence makes you act. I nearly prioritised weeks of work on top of a number describing an outage that had already been fixed.
Not every wall is meant to be knocked down. The passkey barrier has no solution today, for anyone, anywhere. Accepting that freed up time to work on what can actually be improved.
And finally: the cost of artificial intelligence has stopped being the problem. Well under a cent per minute of audio processed by two different models. The expensive part of an AI product today isn't the AI — it's everything that has to stay standing around it.
AudioFlow — automatic transcription of WhatsApp voice notes.
Case study written on 2026-07-29, with figures measured in production on the same day.
Built in Go and Next.js, running on Fly.io.