<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>I Fired Google Voice and Built My Own Texting on ErrorZap</title><link>https://errorzap.com/texting/</link><description>Recent content in I Fired Google Voice and Built My Own Texting on ErrorZap</description><image><title>ErrorZap</title><url>https://errorzap.com/og.png</url><link>https://errorzap.com/og.png</link></image><generator>Hugo</generator><language>en-US</language><copyright>ErrorZap</copyright><lastBuildDate>Fri, 02 Oct 2026 23:38:00 -0600</lastBuildDate><atom:link href="https://errorzap.com/texting/index.xml" rel="self" type="application/rss+xml"/><item><title>What It Costs and What I'd Tell You</title><link>https://errorzap.com/texting/lessons/</link><pubDate>Fri, 02 Oct 2026 23:38:00 -0600</pubDate><guid>https://errorzap.com/texting/lessons/</guid><description>The actual monthly cost of running my own texting, how my AI assistants now work with my texts, what&amp;#39;s still broken, and what I&amp;#39;d tell anyone thinking about leaving Google Voice.</description><content:encoded><![CDATA[<div class="ez-dossier-lede"><span>MY OWN TEXTING · MESSAGE 08 · THE RECEIPT</span><p>Google Voice was free. This costs a little. Here's exactly how little, and what it bought me.</p></div>
<h2 id="the-bill">The bill</h2>
<p>I pulled these numbers straight from Telnyx&rsquo;s usage records while writing this.
This is the last 30 days for <strong>all</strong> my lines, not just my main number:</p>

<div class="tx-cost">
  <h4>What Telnyx actually billed me, last 30 days (read Oct 2, 2026)</h4>
  <div class="tx-cost-row"><span>AI receptionist</span><b>$10.55</b>
    <span class="tx-cost-bar" aria-hidden="true"><i style="width:100%"></i></span><small>about 155 calls the AI answered across all my lines</small></div>
  <div class="tx-cost-row"><span>Texting</span><b>$2.48</b>
    <span class="tx-cost-bar" aria-hidden="true"><i style="width:24%"></i></span><small>332 texts in and out, pictures included</small></div>
  <div class="tx-cost-row"><span>Phone trunk</span><b>$1.13</b>
    <span class="tx-cost-bar" aria-hidden="true"><i style="width:11%"></i></span><small>regular calls to and from my office phone system</small></div>
  <div class="tx-cost-row"><span>Call recordings</span><b>$0.62</b>
    <span class="tx-cost-bar" aria-hidden="true"><i style="width:6%"></i></span></div>
  <div class="tx-cost-row"><span>Call control</span><b>$0.54</b>
    <span class="tx-cost-bar" aria-hidden="true"><i style="width:5%"></i></span><small>my server deciding where each call goes</small></div>
  <div class="tx-cost-row total"><span>Usage total</span><b>$15.32</b><small>Not included: about $1 a month per phone number, the $10/month texting campaign fee, and roughly $10/month for the cloud server that runs my office phone system.</small></div>
</div>

<p>The texting itself, the thing this whole story is about, was <strong>$2.48 for 332
messages</strong>. Add the fixed costs from the note under the table and the whole
setup, AI receptionist included, comes to about $45 a month. That&rsquo;s less than most
cell phone plans.</p>
<h2 id="my-ai-teammates-using-the-front-door">My AI teammates, using the front door</h2>
<p>Here&rsquo;s a part of the payoff I didn&rsquo;t expect. On September 28 my AI assistants got
their own way into my texts: a small command-line tool that talks to my server (plus a version
they can plug into directly) that can list unread threads, read a conversation,
check calls and voicemails, and <strong>draft</strong> a reply.</p>
<p>Drafting is as far as it goes. Nothing gets sent until I approve the exact words and
the exact person.</p>
<p>It also took some retraining. Twice, an assistant went looking for a text in my old
Google apps out of habit. I told it the same thing both times:</p>
<figure class="tx-thread" role="group" aria-label="Sep 28"><div class="tx-thread-head">Sep 28</div>
  <span class="tx-b me"><small>Me → Leo</small>We don&rsquo;t use Google Messages. We use the [KCCS Text] app that we developed.</span>
</figure>

<p>That&rsquo;s now a standing rule for every assistant I run. My texts live on my server,
and that&rsquo;s the only place anyone, human or AI, goes to read them.</p>
<h2 id="still-on-the-list">Still on the list</h2>
<p>It&rsquo;s ErrorZap, so here&rsquo;s what&rsquo;s still broken. While writing this, I tried
searching my texts through the assistants&rsquo; tool, and every search came back
empty, even for common words. The texts are all there. The search isn&rsquo;t working,
so that&rsquo;s next on the fix list. I&rsquo;ll bet it&rsquo;s something small. It usually is.</p>
<h2 id="if-you-want-to-do-this">If you want to do this</h2>
<p>You don&rsquo;t have to build an app to get most of the benefit. Here&rsquo;s what I&rsquo;d tell a
friend:</p>
<ol>
<li><strong>Export first.</strong> Run Google Takeout on Google Voice before you touch anything.
Ten years of texts are worth an hour of downloading.</li>
<li><strong>Practice on a new number.</strong> Get a cheap number at a carrier like Telnyx and live
on it for a while before porting the one that matters.</li>
<li><strong>Do the 10DLC paperwork early, and use your real documents.</strong> Make sure your
business name and tax ID match your IRS letter exactly. Put SMS terms and a
privacy policy on your website before you apply.</li>
<li><strong>Check your two-factor codes.</strong> Some services won&rsquo;t text codes to VoIP numbers.
Move important accounts to an authenticator app before port day.</li>
<li><strong>Push, don&rsquo;t poll.</strong> If you build anything, have the server tell the app about
new messages. Polling caused my worst bug.</li>
<li><strong>Test against a fake carrier.</strong> A staging copy that fakes the carrier&rsquo;s API caught
more bugs than anything else, and it never sent a single real text.</li>
<li><strong>Watch the whole path, not just the server.</strong> My worst failure produced no
errors at all. A monitor that tests the <em>outcome</em> (does a VIP call actually
ring?) would have caught it in minutes instead of days.</li>
</ol>
<h2 id="was-it-worth-it">Was it worth it?</h2>
<p>My business number is mine now. It&rsquo;s not a feature of somebody else&rsquo;s free product.
Every text I&rsquo;ve sent or received since September 15 sits in a database I own. My
phone makes a different sound for each person. My AI assistants can help with my
texts without scraping anything. And when a stranger calls while I&rsquo;m under a desk,
a robot politely takes a message for about seven cents.</p>
<p>I&rsquo;d do it again. I&rsquo;d just put the monitor in on day one.</p>
<p><a href="/texting/">← Back to the inbox</a></p>
]]></content:encoded></item><item><title>The Robot Answers the Phone (and the Three Silent Days)</title><link>https://errorzap.com/texting/ai-answers/</link><pubDate>Fri, 02 Oct 2026 23:37:00 -0600</pubDate><guid>https://errorzap.com/texting/ai-answers/</guid><description>Once calls to my business number ran through my own server, an AI could answer for me. Then a routing change quietly dropped my VIP list and my voicemail safety net, and nothing was watching. Here&amp;#39;s the fix, and the alarm that watches now.</description><content:encoded><![CDATA[<div class="ez-dossier-lede"><span>MY OWN TEXTING · MESSAGE 07 · THE CALLS</span><p>The scariest failure isn't the loud one. It's the one where everything looks fine.</p></div>
<h2 id="why-let-an-ai-answer">Why let an AI answer?</h2>
<p>When I&rsquo;m under a desk at a client&rsquo;s office with a screwdriver in my hand, I can&rsquo;t
take a call. Voicemail works, but most people hate leaving one. What I wanted:</p>
<figure class="tx-thread" role="group" aria-label="Sep 21"><div class="tx-thread-head">Sep 21</div>
  <span class="tx-b me"><small>Me → my AI teammates</small>I want someone to be able to call my lines, be able to use the AI, and not have to bother me.</span>
</figure>

<p>Once the number lived at Telnyx, that became possible. Telnyx has a feature called
<strong>Call Control</strong>: every time a call comes in, Telnyx asks <em>your</em> server what to
do with it, and your server answers with commands like &ldquo;answer,&rdquo; &ldquo;transfer&rdquo; or
&ldquo;hang up.&rdquo; My texting server already handled Telnyx&rsquo;s texting webhooks. Now it
handles calls too.</p>
<h2 id="the-rules">The rules</h2>
<p>Here&rsquo;s what happens when you call my business number today:</p>
<ol>
<li><strong>On my VIP list?</strong> Family and the people I most need to hear from (31 right now) ring straight
through to my phones, showing their real caller ID, just like a normal call.</li>
<li><strong>Blocked?</strong> The call ends. Spammers don&rsquo;t get an AI to chat with.</li>
<li><strong>Everyone else</strong> gets an AI receptionist. It says up front that it&rsquo;s an AI and
that the call is recorded, then takes the message: who you are, what you need,
how to reach you.</li>
<li><strong>I get a summary</strong> in Telegram right away, plus a digest every morning at 7:30.</li>
</ol>
<p>At night (10 PM to 7 AM), only family and urgent VIPs ring through. Everyone else
gets the AI. I can change any of it from Telegram with commands like <code>/vip</code>,
<code>/block</code> and <code>/night</code>, with no app or website needed.</p>
<p>Want to see the whole route a call takes? The diagram on the
<a href="/texting/#how-a-text-gets-to-me-now">section front page</a> has a &ldquo;Someone calls&rdquo; button.</p>
<h2 id="the-three-silent-days">The three silent days</h2>
<p>The move from &ldquo;my office phone system answers my number&rdquo; to &ldquo;my server answers my number&rdquo;
happened on the night of September 21. The AI part worked. Calls got answered and
messages showed up in Telegram.</p>
<p>What nobody noticed: the old path had been doing two jobs the new one didn&rsquo;t.</p>
<ul>
<li><strong>The VIP list stopped ringing through.</strong> My family and best clients were getting
the AI too.</li>
<li><strong>The voicemail safety net was gone.</strong> If the AI couldn&rsquo;t start, the call just
ended. If my server was down, there was nothing behind it at all.</li>
</ul>
<p>Nothing errored. Nothing alerted. The calls looked handled. It took <strong>three days</strong>
before a full review of the phone setup on September 24 turned it up.</p>
<h2 id="the-fix">The fix</h2>
<p>On September 25 I told Leo to fix all of it, and it went in that night:</p>
<ul>
<li><strong>VIP ring-through is back,</strong> transferring the call to my office phone system so it
rings my phones. That surfaced a sneaky gotcha. By default, a Telnyx transfer
shows the <em>number that was dialed</em> as the caller ID, not the person calling. My
phone system saw &ldquo;my number calling my number,&rdquo; didn&rsquo;t recognize a VIP, and sent my VIPs to
voicemail. The transfer now passes along the real caller&rsquo;s number.</li>
<li><strong>If the AI can&rsquo;t start,</strong> the call goes to my regular phone system and voicemail
instead of hanging up.</li>
<li><strong>If my server is down,</strong> Telnyx falls back to a small backup responder on the
office phone system, so a call always lands somewhere.</li>
<li><strong>Spending caps</strong> on outbound calls, so a bug can&rsquo;t run up a bill.</li>
<li><strong>A monitor</strong> that checks the whole call path every five minutes and pings my
Telegram the moment anything drifts from how it should be.</li>
</ul>
<p>That round shipped with 100 of 100 tests passing. The monitor is the part I care
about most. The three silent days weren&rsquo;t caused by bad code. They were caused by
a change with nothing watching it.</p>
<h2 id="what-it-costs">What it costs</h2>
<p>In the last 30 days, the AI receptionist answered about <strong>155 calls</strong> across all my lines,
for a total of <strong>$10.55</strong>. That&rsquo;s about seven cents a call to never get
interrupted by an extended-warranty robot again.</p>
]]></content:encoded></item><item><title>Making It Mine</title><link>https://errorzap.com/texting/making-it-mine/</link><pubDate>Fri, 02 Oct 2026 23:36:00 -0600</pubDate><guid>https://errorzap.com/texting/making-it-mine/</guid><description>Version 0.3 of the KCCS Text app added the things no off-the-shelf texting app would give me: per-contact sounds, nagging reminders, quiet hours, VIPs, a desktop page and business voicemail.</description><content:encoded><![CDATA[<div class="ez-dossier-lede"><span>MY OWN TEXTING · MESSAGE 06 · THE GOOD PART</span><p>Once it's your app, "I wish it could…" stops being a complaint and turns into a to-do item.</p></div>
<h2 id="version-03-the-same-night">Version 0.3, the same night</h2>
<p>Version 0.2 went live at 6:27 PM on September 23. Version 0.3 went live at 7:38 PM.
That hour was mostly testing, because the features had been built that afternoon
alongside everything else. Here&rsquo;s what I got.</p>
<p><strong>A sound for every person.</strong> Each contact can have its own notification sound and
vibration. Under the hood, the app makes a separate Android notification channel
for each person, since that&rsquo;s the only way Android lets an app give different
alerts different sounds. Now I know who&rsquo;s texting before I look.</p>
<p><strong>Priorities and VIPs.</strong> Every contact is Standard, Priority or Silent, and anyone
can be a VIP. VIPs sit at the top of my People list and always count as priority.</p>
<p><strong>Reminders that don&rsquo;t quit.</strong> If a priority text sits unread, the app reminds me
again, on a schedule I set per person (every 10 minutes, up to twice, for
example). Reading it or replying cancels the reminders. They survive the phone
rebooting, too.</p>
<p><strong>Quiet hours and snooze,</strong> so all of the above leaves me alone at night unless it
really matters.</p>
<p><strong>A setup checklist.</strong> Android has a handful of settings that silently wreck
alerts: battery optimization, exact alarms, Do Not Disturb access. The settings
screen checks each one and gives you a <strong>Fix</strong> button that jumps straight to the
right system page.</p>
<div class="tx-shots">
<figure><img src="shot-conversation.webp" alt="A conversation in the KCCS Text app with a made-up contact, chat bubbles with sent and delivered marks, and quick-reply buttons like On my way above the text box." loading="lazy" width="390" height="844"><figcaption>A conversation, with quick replies above the keyboard. (Made-up contact from the test harness.)</figcaption></figure>
<figure><img src="shot-contact.webp" alt="Contact settings in the KCCS Text app showing priority, a VIP checkbox and a list of sounds: KCCS Chime, KCCS Priority, KCCS Urgent, phone default, silent." loading="lazy" width="390" height="844"><figcaption>Every contact gets a priority, a VIP switch and its own sound.</figcaption></figure>
<figure><img src="shot-people.webp" alt="Settings screen showing Fix needed buttons for exact alarms, battery optimization and Do Not Disturb access, then a People and priorities list with Standard, Priority and Silent contacts." loading="lazy" width="390" height="844"><figcaption>The checklist that finds alert-killing settings, then People &amp; priorities.</figcaption></figure>
</div>
<h2 id="the-upgrade-trick">The upgrade trick</h2>
<p>Here&rsquo;s a small detail I love. The first rebuilt app had been installed under a
test package name. Instead of switching to a &ldquo;proper&rdquo; name and making me log in
again and redo every contact&rsquo;s sound, the real release <strong>kept that package name
and signing key</strong>. Android treated each new version as an update, so my login and
all my per-contact sounds carried over every time. Not pretty, but it worked
every time.</p>
<h2 id="goodbye-to-the-old-app">Goodbye to the old app</h2>
<p>For about a day I had <strong>two</strong> apps on my phone with the same name: the old
React Native one and the new one. Same name, different insides. I asked Leo to get
rid of the old one, and it came off both phones. Its 7-second polling stopped for
good on September 24.</p>
<h2 id="the-desk-page">The desk page</h2>
<p>Most of my day is at a PC, so on September 24 the same server got a desktop page:
texts <strong>and</strong> calls in one list, call and voicemail cards right inside each
conversation, keyboard shortcuts for everything, and a Ctrl+K search box for
jumping to anyone. It went through 31 automated checks before going live that
night.</p>
<div class="tx-shots">
<figure><img src="shot-desk.webp" alt="The KCCS Text desk page: a dark list of made-up conversations and calls on the left, and a welcome panel with unread counts and keyboard shortcuts on the right." loading="lazy" width="1600" height="950"><figcaption>The desk page: everything in one list, with keyboard shortcuts. (Test data.)</figcaption></figure>
</div>
<h2 id="voicemail-moves-in">Voicemail moves in</h2>
<p>My office phone system already turned voicemails into emails and transcripts. On
September 26 the app got a <strong>Voicemail</strong> button with a badge. Tap it to play a
message, read the transcript, call back or mark it heard. There&rsquo;s a second tab for
&ldquo;AI took a message,&rdquo; which you&rsquo;ll understand after the next message.</p>
<p>The same weekend the app learned to <strong>open on my main line by default.</strong> My server
sends from more than one number, and the app had been guessing.</p>
<h2 id="the-full-test">The full test</h2>
<p>On September 26 we test-called <strong>every line</strong> I own and sent test texts across all
of them: 22 calls and 9 texts. It found one problem I never would have guessed.
One of my phones had been sitting on manual Do Not Disturb since the 22nd, so
calls rang silently and showed up as missed. No app bug. Just a setting. That&rsquo;s
exactly why the setup checklist exists.</p>
]]></content:encoded></item><item><title>Tear It Down, Build It Right</title><link>https://errorzap.com/texting/rebuild/</link><pubDate>Fri, 02 Oct 2026 23:35:00 -0600</pubDate><guid>https://errorzap.com/texting/rebuild/</guid><description>How the KCCS Text app went from a web app with instant updates to a full rebuild of the server, the web app and an Android shell in a single afternoon, and what testing against a fake Telnyx caught.</description><content:encoded><![CDATA[<div class="ez-dossier-lede"><span>MY OWN TEXTING · MESSAGE 05 · THE REBUILD</span><p>The app was never the hard part. The hard part was everything the app assumed would just work.</p></div>
<h2 id="step-one-stop-asking-start-listening">Step one: stop asking, start listening</h2>
<p>The old app asked the server &ldquo;anything new?&rdquo; every 10 seconds. The fix is to flip
it around and have the server <strong>tell</strong> the app the moment something arrives.</p>
<p>On September 19 Leo shipped a web app version of the app built that way:</p>
<ul>
<li><strong>Server-Sent Events</strong> keep one quiet connection open to my server, and a new
text shows up on screen the instant it lands. No polling, so no redraws
stomping on my typing.</li>
<li><strong>Web Push</strong> wakes the phone when the app is closed. Leo wrote that part from
the spec and checked it against the official test vectors instead of trusting a
library.</li>
<li><strong>A login per device</strong> that I can revoke one at a time, contact names, sharing
photos into the app, and a Back button that actually goes back.</li>
</ul>
<p>It passed 46 of 46 acceptance checks, and a real text from my main number to my 4040 line
arrived in under six seconds.</p>
<h2 id="never-miss-an-alert">&ldquo;Never miss an alert&rdquo;</h2>
<p>Two days later I&rsquo;d used it enough to know what was still wrong. I wanted different
sounds for different people. I wanted reminders that keep nagging until I answer.
The way I put it to Leo:</p>
<figure class="tx-thread" role="group" aria-label="Sep 21"><div class="tx-thread-head">Sep 21</div>
  <span class="tx-b me"><small>Me → Leo</small>Something I can use all day long and absolutely count on to never miss an alert.</span>
</figure>

<p>A web page can&rsquo;t do that on Android. It can&rsquo;t give each contact its own sound, and
it can&rsquo;t keep reminding you after you swipe it away. A real Android app can. So the
design became a <strong>shell</strong>: a small native Android app that hosts the web app, plus
the native pieces a web page can&rsquo;t do:</p>
<ul>
<li>a background service that holds the live connection to my server,</li>
<li>real Android notifications with <strong>reply right from the notification</strong>,</li>
<li>per-contact sounds, reminders and quiet hours (that&rsquo;s message 06).</li>
</ul>
<h2 id="september-23-one-afternoon">September 23: one afternoon</h2>
<p>On the 23rd I told Leo the app was still buggy. It still deleted what I was typing
sometimes, it jumped around while scrolling, and Back exited the whole app. Leo
stopped patching and rebuilt it.</p>
<p>At 2:34 PM it snapshotted the live code. Then three builder agents worked in
parallel: one on the <strong>server</strong>, one on the <strong>web app</strong>, one on the <strong>Android
shell</strong>, all working to one written contract for how the pieces talk.</p>
<h2 id="a-fake-phone-company-for-testing">A fake phone company for testing</h2>
<p>You can&rsquo;t test a texting app by spamming real texts all afternoon. So the rebuild
came with a <strong>staging harness</strong>. It&rsquo;s my real server code, wired to a <em>fake</em> Telnyx
that never touches the network. Send a text and the fake carrier answers like the
real API, then a second later plays back a &ldquo;delivered&rdquo; receipt through the same
code path real receipts use. It can also inject fake incoming texts and fake
picture messages on command.</p>
<p>Every screenshot of the app in this story comes from that harness, with made-up
people in it.</p>
<h2 id="what-testing-caught">What testing caught</h2>
<p>The server review turned up <strong>18 bugs</strong> in code that had been &ldquo;working.&rdquo; A few
favorites:</p>
<ul>
<li><strong>Vanishing texts.</strong> In a conversation over 500 messages long, the app loaded the
<em>oldest</em> 500. New texts were in the database but never showed up.</li>
<li><strong>Lost-forever texts.</strong> The server marked an incoming webhook as handled
<em>before</em> saving the message. If the save failed, Telnyx would retry, the server
would say &ldquo;already got it,&rdquo; and the text was gone for good.</li>
<li><strong>&ldquo;Retry&rdquo; that didn&rsquo;t.</strong> The retry button never actually re-sent anything.</li>
<li><strong>A freezing server.</strong> A few slow network calls blocked everything else while they
waited.</li>
<li><strong>A sneaky picture.</strong> A picture message pretending to be a certain kind of image
could have run code inside the app with one tap. Now only normal photo and video
types open inline, and everything else downloads as a plain file.</li>
</ul>
<p>Then putting it all together on real phones caught more. My favorite: the app and
the server got into a &ldquo;mark as read&rdquo; argument that fired <strong>647 times in two
minutes</strong>. Another: Android never told the web page it was in the background, so the
page kept marking texts read and <em>cancelling my notifications</em> while the phone
sat in my pocket.</p>
<h2 id="shipped">Shipped</h2>
<p>By the end of the afternoon: 43 server tests, 72 web app tests, 28 of 28 checks
on my Pixel and 27 of 28 automatic checks on my TCL (the last one, replying from
the notification, I checked by hand). At 6:27 PM, version 0.2 went live on both
phones, with a rollback copy saved in case it didn&rsquo;t hold.</p>
<p>It held. So that night, we kept going.</p>
]]></content:encoded></item><item><title>Six Hours Later: The First App</title><link>https://errorzap.com/texting/first-app/</link><pubDate>Fri, 02 Oct 2026 23:34:00 -0600</pubDate><guid>https://errorzap.com/texting/first-app/</guid><description>The first KCCS Text app was a fork of an open-source VoIP app. It got texts onto my phone fast. Then it started eating what I typed.</description><content:encoded><![CDATA[<div class="ez-dossier-lede"><span>MY OWN TEXTING · MESSAGE 04 · VERSION ZERO</span><p>The fastest way to learn what you want is to use something that isn't it.</p></div>
<h2 id="the-question">The question</h2>
<p>My first instinct on port day was to skip apps entirely. I live in Telegram, so I
asked for a bot that would let me text through it &ldquo;so I don&rsquo;t have to deal with a
weird app.&rdquo; That works for alerts. It&rsquo;s miserable for actual conversations with
forty different people.</p>
<p>So at 3:29 that afternoon:</p>
<figure class="tx-thread" role="group" aria-label="Sep 15 · 3:29 PM"><div class="tx-thread-head">Sep 15 · 3:29 PM</div>
  <span class="tx-b me"><small>Me → Orion</small>Is there a way to have a Google Voice-like texting app on my phone?</span>
</figure>

<p>Orion came back with a short list of open-source options. Fifteen minutes later:</p>
<figure class="tx-thread" role="group" aria-label="Sep 15 · 3:45 PM"><div class="tx-thread-head">Sep 15 · 3:45 PM</div>
  <span class="tx-b me"><small>Me → Orion</small>Privacy app: modify it… Don&rsquo;t ask me any questions. Do it.</span>
</figure>

<h2 id="forking-an-open-source-app">Forking an open-source app</h2>
<p>Orion found <strong>VoIPSuite-Mobile</strong>, an open-source texting app from a privacy project.
It&rsquo;s built in React Native, and it already knew how to talk to a VoIP carrier.
Orion forked it, pointed it at my own server, and named it <strong>KCCS Text</strong>.</p>
<p>Within two days it was on both of my phones. By September 17 it was at version
0.7.0, with a desktop-and-mobile &ldquo;business hub&rdquo; growing next to it on the server.
For a forked weekend project, that&rsquo;s fast.</p>
<p>Then I actually used it all day.</p>
<h2 id="bug-one-the-silent-alarm">Bug one: the silent alarm</h2>
<p>The point of a texting app is knowing when a text arrives. On September 17 we found
that Android had been quietly marking <strong>every single notification from the app as
SILENT</strong>. The notification channels had been created with sound and vibration
off, and once Android creates a channel, the app can&rsquo;t simply change it later.</p>
<p>The fix was new channels with new IDs, plus a lesson I&rsquo;d keep relearning for the
rest of this project: <strong>on Android, notification settings are sticky.</strong> If you get
them wrong on the first install, you have to version your way out.</p>
<h2 id="bug-two-the-text-eater">Bug two: the text eater</h2>
<p>The one that drove me nuts showed up the next day:</p>
<figure class="tx-thread" role="group" aria-label="Sep 18"><div class="tx-thread-head">Sep 18</div>
  <span class="tx-b me"><small>Me → Orion</small>Look into the [KCCS Text] app. When I&rsquo;m typing on it on my Pixel 7, it keeps erasing stuff.</span>
</figure>

<p>Here&rsquo;s what was going on. The app checked the server for new messages <strong>every 10
seconds</strong>, and each check redrew the screen, including the box I was typing in.
Phone keyboards keep a little &ldquo;work in progress&rdquo; state while you type (the word
being autocorrected, the swipe in flight). Redraw the box under it and the keyboard
loses its place. Letters vanish. Sometimes a whole sentence.</p>
<p>Orion&rsquo;s answer was a redesign, version 0.6.1. When Leo reviewed it, it caught a
trap: the &ldquo;new&rdquo; version had the <strong>same internal version
number</strong> as the 0.7.0 already installed, and it was missing picture messages and
saved drafts. Installed over the top, it would have been a downgrade wearing a
new coat of paint.</p>
<h2 id="the-audit">The audit</h2>
<p>That night I told Leo what I really wanted. Roughly: make this the ultimate texting
app for my number, not a half-baked thing I can kind of put up with.</p>
<p>Leo&rsquo;s audit was blunt:</p>
<ul>
<li>The whole app was <strong>one giant file</strong> on a React Native version from 2022.</li>
<li>There were <strong>three copies</strong> of the code drifting apart in different folders.</li>
<li>The <strong>10-second polling</strong> was the root of the typing bug, the battery drain <em>and</em>
the slow delivery.</li>
<li>Patching it would mean fighting an old framework forever.</li>
</ul>
<p>The recommendation: freeze the old app, stop polling, and rebuild around a server
that <strong>pushes</strong> new messages the instant they arrive. That&rsquo;s message 05.</p>
]]></content:encoded></item><item><title>The Paperwork Boss Fight, Then Port Day</title><link>https://errorzap.com/texting/port-day/</link><pubDate>Fri, 02 Oct 2026 23:33:00 -0600</pubDate><guid>https://errorzap.com/texting/port-day/</guid><description>Registering a small business for texting, the letter that moves a phone number, and the morning my ten-year-old number walked out of Google Voice.</description><content:encoded><![CDATA[<div class="ez-dossier-lede"><span>MY OWN TEXTING · MESSAGE 03 · THE MOVE</span><p>Moving a phone number is mostly forms. Then one morning, it's just done.</p></div>
<h2 id="cant-i-just-forward-it">Can&rsquo;t I just forward it?</h2>
<p>The first question in September was the lazy one: could I leave the number in
Google Voice and just forward everything to Telnyx? No. Telnyx won&rsquo;t attach its
texting service to a Google Voice number. To own the texting, I had to own the
number. That meant porting.</p>
<h2 id="the-10dlc-boss-fight-round-two">The 10DLC boss fight, round two</h2>
<p>This round, Orion (ChatGPT&rsquo;s Codex) drove the paperwork with me. On September 8,
in one long evening:</p>
<ol>
<li><strong>ID check.</strong> Telnyx verified my identity with a photo ID and selfie, which
unblocked the account.</li>
<li><strong>Business details.</strong> We caught that a draft of my business info didn&rsquo;t match
my actual IRS letter, threw it out, and used the real paperwork instead. Mismatched
tax details are one of the most common reasons a 10DLC brand gets rejected.</li>
<li><strong>Brand submitted</strong> at 4:51 PM. <strong>Verified</strong> at 8:47 PM.</li>
<li><strong>Website pages.</strong> The carriers want to see SMS terms and a privacy policy on
your site, including how STOP, START and HELP work. Those went up on my
business site the same night.</li>
<li><strong>Campaign submitted</strong> at 9:02 PM as &ldquo;Customer Care,&rdquo; which is exactly what my
texting is: talking to people who already know me.</li>
</ol>
<p>The fees, so you know what you&rsquo;re in for: <strong>$4.50</strong> for the brand, <strong>$15</strong> for each
campaign review, and <strong>$10 a month</strong> for the Customer Care campaign. The campaign
sat in &ldquo;pending&rdquo; with the carriers for two days, then went active on September 10.</p>
<h2 id="the-letter">The letter</h2>
<p>Porting a number runs on a <strong>Letter of Authorization</strong> (LOA). It&rsquo;s a signed
statement that you own the number and want it moved, plus proof, usually a
screenshot or bill showing the number on your account. Google Voice also has you
unlock the number for transfer first.</p>
<p>By September 11 the port order was filled out and waiting on one thing: my
signature. We asked for the earliest activation slot: <strong>Tuesday, September 15,
at 10 AM Mountain.</strong></p>
<h2 id="port-day">Port day</h2>
<p>There&rsquo;s no fanfare when a number ports. Nobody calls you. At some point in the
morning, the old carrier lets go and the new one picks it up.</p>
<p>Here&rsquo;s the message I sent my AI teammate at 10:42 that morning:</p>
<figure class="tx-thread" role="group" aria-label="Sep 15 · 10:42 AM"><div class="tx-thread-head">Sep 15 · 10:42 AM</div>
  <span class="tx-b me"><small>Me → Orion</small>It looks like my number ported over. Google Voice shows no phone number at all now. Can you check [my number] and see how all that&rsquo;s working? We&rsquo;ll test everything.</span>
</figure>

<p>Ten years in Google Voice, gone from the app in one quiet refresh. Texts to my number
were now landing on Telnyx and getting passed to my server. The first test texts
went in and out. It worked.</p>
<h2 id="the-2fa-scare">The 2FA scare</h2>
<p>One thing did rattle me that afternoon. A service I use refused to send a login
code to my number, with an error saying it doesn&rsquo;t send codes to VoIP numbers.</p>
<p>That&rsquo;s a real thing to plan for. Some banks and apps won&rsquo;t text verification codes
to internet-based numbers. If you do this, check where your
two-factor codes go <em>before</em> port day, and move the important ones to an
authenticator app.</p>
<h2 id="six-hours-later">Six hours later</h2>
<p>The number was mine. The texts were reaching my server. There was just one problem:
I had nothing good to read them <em>on</em>. That afternoon I asked the question that
started the second half of this story.</p>
]]></content:encoded></item><item><title>We Built a Phone Company in One Night</title><link>https://errorzap.com/texting/phone-company-overnight/</link><pubDate>Fri, 02 Oct 2026 23:32:00 -0600</pubDate><guid>https://errorzap.com/texting/phone-company-overnight/</guid><description>Before risking my real number, Leo and I built a complete business phone system on a fresh number in one night, then spent a few weeks learning what a carrier actually expects from you.</description><content:encoded><![CDATA[<div class="ez-dossier-lede"><span>MY OWN TEXTING · MESSAGE 02 · THE PRACTICE RIG</span><p>Rule one of moving something important: build the new house before you move out of the old one.</p></div>
<h2 id="dont-practice-on-the-real-number">Don&rsquo;t practice on the real number</h2>
<p>Porting a phone number is a one-way door. Once my number left Google Voice, there was
no clicking &ldquo;undo&rdquo; if the new setup couldn&rsquo;t ring my phone. So the plan was to
build everything on a <strong>new</strong> number first, live with it, and only move my real number once
the new system had proven itself.</p>
<h2 id="the-night-of-june-27">The night of June 27</h2>
<p>Starting just before midnight on June 27, Leo (Claude, my main AI teammate) and I
built a full business phone system from nothing:</p>
<ul>
<li><strong>A carrier account at Telnyx.</strong> Telnyx sells phone numbers, calling and texting
to businesses, and every piece of it has an API. A number costs about a dollar a
month.</li>
<li><strong>A phone system on a rented cloud server.</strong> It runs FreePBX, a free,
open-source office phone system built on Asterisk. That&rsquo;s the software behind a
lot of real business phone systems. It runs on a small cloud server that costs
about $10 a month.</li>
<li><strong>A new business line, (719) 530-4040,</strong> wired through Telnyx into that phone
system. Today an AI receptionist answers it.</li>
</ul>
<p>By morning I had extensions, voicemail, call routing and a number that rang.
It was the kind of thing a phone company used to charge a monthly fee per desk to
set up.</p>
<p>That same night we also pulled my entire Google Voice history out with Google
Takeout and turned it into a searchable archive with three copies. Whatever
happened next, those ten years of texts were safe.</p>
<h2 id="making-it-trustworthy">Making it trustworthy</h2>
<p>A phone system that <em>usually</em> works is worse than none, because you stop checking.
The next few sessions were all about the boring parts:</p>
<ul>
<li><strong>Voicemail to email,</strong> so a message never sits unheard in a box I forgot about.</li>
<li><strong>Follow-me to my cell,</strong> with a &ldquo;press 1 to accept&rdquo; check. Without that, my
cell&rsquo;s own voicemail would grab the call and the phone system would think I&rsquo;d
answered.</li>
<li><strong>Telegram alerts</strong> for every missed call and new voicemail. Telegram is my
pager. If it buzzes, something needs me.</li>
<li><strong>A fire drill.</strong> We called in, left messages and made sure every alert actually
fired before calling it done.</li>
</ul>
<h2 id="first-texts-on-my-own-server">First texts on my own server</h2>
<p>On July 5, the first real milestone for texting: a text sent to the 4040 number
landed on a little webhook service, which forwarded it to my Telegram and email.
For the first time, a text to my business was data <em>I</em> had, not data Google had.</p>
<p>Receiving worked right away. <strong>Sending</strong> ran into a wall with a very boring name.</p>
<h2 id="meet-10dlc">Meet 10DLC</h2>
<p>In the US, if a business wants to send texts from a regular 10-digit phone number,
the carriers want to know who you are first. The system is called <strong>10DLC</strong>
(10-digit long code). You register:</p>
<ol>
<li><strong>A brand:</strong> your business, verified against your tax records.</li>
<li><strong>A campaign:</strong> what kind of texts you&rsquo;ll send (customer care, marketing,
reminders) with examples, opt-out wording, and a privacy policy on your website.</li>
</ol>
<p>Skip it and your texts get filtered or blocked. My first try at registering the
brand bounced with &ldquo;Account unverified,&rdquo; because the Telnyx account itself hadn&rsquo;t
passed an identity check yet. My account balance was sitting at $4.51 and slowly
draining, and I wasn&rsquo;t ready to fight that fight yet.</p>
<p>So I let it sit for the summer and had my AI teammates do the homework instead: what
texting really costs, how 10DLC works, exactly how you get a number out of Google
Voice, and what the alternatives were. Four research write-ups later, the answer
was clear. The practice rig worked. The next step was the paperwork, then the real
number.</p>
]]></content:encoded></item><item><title>Ten Years on a Borrowed Number</title><link>https://errorzap.com/texting/borrowed-number/</link><pubDate>Fri, 02 Oct 2026 23:31:00 -0600</pubDate><guid>https://errorzap.com/texting/borrowed-number/</guid><description>Google Voice was free and it worked. It also kept my business phone number, ten years of texts, and every automation idea I had locked in a box I couldn&amp;#39;t open.</description><content:encoded><![CDATA[<div class="ez-dossier-lede"><span>MY OWN TEXTING · MESSAGE 01 · THE PROBLEM</span><p>Free is a great price until you want to do something the free thing doesn't allow.</p></div>
<h2 id="a-great-deal-for-a-while">A great deal, for a while</h2>
<p>I got my business number through Google Voice in November 2015. It was perfect for a
one-person shop. One number rang every device, texts showed up on my phone and my
PC, voicemails got transcribed, and it cost nothing.</p>
<p>So everything went there. Customers. Vendors. Family. Every &ldquo;your appointment is
tomorrow&rdquo; and &ldquo;your package was delivered.&rdquo; When I finally exported it all in
June 2026, the archive held:</p>
<ul>
<li><strong>86,252</strong> texts</li>
<li><strong>10,900</strong> calls</li>
<li><strong>3,014</strong> voicemails</li>
<li><strong>5,045</strong> contacts</li>
</ul>
<p>That&rsquo;s not a phone number anymore. That&rsquo;s the memory of my business.</p>
<h2 id="the-wall">The wall</h2>
<p>The trouble started when I wanted my computers to <em>help</em> with any of it.</p>
<p>I run a lot of automation. I have AI assistants that read my email, track my
tasks, and draft replies. They can do all of that because email has real tools
for it. Google Voice has none. There&rsquo;s no official API for texts or calls. Your
own software can&rsquo;t read your own messages.</p>
<p>There was one crack in the wall: Google Voice can forward <em>received</em> texts to
email. So for months I had a scraper pulling text notifications out of Gmail
every day. It was held together with tape:</p>
<ul>
<li><strong>Sent texts were invisible.</strong> Email forwarding only covers what comes in. Half
of every conversation, my half, never made it out.</li>
<li><strong>Group texts arrived empty.</strong> The notification email for a group message has
no message in it. Just &ldquo;you have a new message.&rdquo;</li>
<li><strong>Sending was off the table.</strong> Google&rsquo;s rules don&rsquo;t allow automated sending, and
I wasn&rsquo;t going to risk the number on a hack.</li>
</ul>
<p>I had a note in my to-do list for a long time that said, more or less, <em>find an
unofficial way to scrape Google Voice until I migrate.</em> &ldquo;Until I migrate&rdquo; was
doing a lot of work in that sentence.</p>
<h2 id="the-part-that-kept-me-up">The part that kept me up</h2>
<p>The bigger worry wasn&rsquo;t convenience. It was this: the number my whole business
depends on was tied to a free consumer Google account.</p>
<p>If that account ever got locked, or Google changed the product, or decided to
retire it the way Google retires things, the failure would be silent. Clients
would call, nobody would answer, and they&rsquo;d never learn why. When I sat down and
listed the single points of failure in my business, that number was near the top
of the list.</p>
<p>I didn&rsquo;t need Google Voice to be bad. I needed it to stop being the only door.</p>
<h2 id="what-i-wanted-instead">What I wanted instead</h2>
<p>Written down, the wish list was short:</p>
<ol>
<li><strong>Own the number,</strong> with a carrier that sells to businesses and has an API.</li>
<li><strong>Own every message,</strong> sent and received, in a database I can search and back up.</li>
<li><strong>Let my tools in.</strong> My AI assistants should be able to read a text and draft a
reply without anyone screen-scraping anything.</li>
<li><strong>Never miss anything.</strong> Whatever replaced Google Voice had to be at least as
reliable on my phone as Google Voice was.</li>
</ol>
<p>Number 4 turned out to be the hard one. Next up: before I touched my real number
at all, I built a whole phone system on a brand-new number to practice on.</p>
]]></content:encoded></item></channel></rss>