Going Public: Two Stores, Two Rejections, Zero Chill

The launch diary · 29 September 2026 · 20 min read

Deutsch Español Français Português 中文 Italiano 日本語 한국어 Русский Türkçe Polski Nederlands Bahasa Indonesia

Moneyflow is now on the App Store and on Google Play. We would love to tell you it was smooth. It was not. Along the way we collected two rejections from Apple, taught a build script to say no, found out that a Lambo was a chequered flag all along, and fixed a bug that Google shrugged off and Apple did not.

This is the whole story, pieced together from our release notes, our runbooks and the commit messages we wrote in a hurry. It is long, it is a bit cheeky, and if you are about to launch an app of your own it contains actual advice. Grab a coffee, or a small loan against your assets.

Get it on the App Store Get it on Google Play

The short version, in dates

  1. Version 1.2.8 goes live on Google Play. The announcement follows that evening, in six languages.
  2. iOS catches up with Android at 1.2.8, after we rescue a splash screen nobody could read.
  3. Submission one goes to Apple without its in-app purchases. Submission two goes in with all 39. Apple's first answer: Information Needed.
  4. A trademark spring clean, and build 31 to put a missing key back in the app.
  5. Rejection two, from an iPad: both sign-in buttons show an error, and the reviewer cannot find the Store.
  6. The culprit is one missing parameter. Android had been quietly forgiving it all along.
  7. Build 34, signed properly. Sign in with Apple finally works.
  8. Version 1.2.9 rolls out on Google Play.
  9. Players tell us their phones are running hot. We stop the game doing that.
  10. Five versions in one weekend, from 1.2.10 to 1.3.1.
  11. The App Store link goes on our homepage. You are here.

Pre-IPO: a browser game with commitment issues

Moneyflow started life as a browser game. You pick a character with a real job, real bills and a real salary, roll the dice, and try to build enough passive income to escape the 9 to 5 and pay for two dreams. Doing both is the only way to win, in single player and multiplayer alike. There is also a wedding, a prenup and a divorce, and we will get to those.

Then we decided it belonged on your phone and found out that an app store is a different game entirely. No dice, no cards, just forms, questionnaires and a house that always wins. We wrote up the Google Play paperwork earlier, in Listing Moneyflow on the Google Play Store. This is the sequel: what happened next, on both stores, and what we would tell ourselves if we could go back.

Round one: Google Play says yes (after asking for everything)

Google Play went first, and it behaved like a bank when you apply for a mortgage: friendly, thorough and keen to see every document you own. The Data safety form, the content rating, the account deletion page, the closed testing period. The earlier post covers all of that, so here is what we changed once the first listing was done.

We stopped clicking. All 39 in-app purchases (18 pawns, 14 dice skins, 4 board themes and 3 bundles, every one of them cosmetic) were created by script instead of by hand, with RevenueCat sitting between the app and both stores so the purchase logic is the same everywhere. Releases go through the Android Publisher API too. One script opens an edit, uploads the bundle, assigns the track and commits, and if any step fails it deletes the edit, so a failed run leaves nothing behind. It is the tidiest thing in this whole story.

Play has its quirks. It refuses any build number it has ever seen, including ones you uploaded and never released, so build numbers behave like cash in the game: spend one and it is gone, whether or not you got anything for it. We also have two service accounts, and only one of them is allowed to publish. The other can open an edit, upload a whole bundle, assign it to a track and then collect a 403 at the very last step. All that effort, and a firm "no" after the cake is already on the table.

On 7 September version 1.2.8 went live. That evening we published the announcement in six languages, because if you are going to be excited in public you might as well do it in German, Spanish, French, Portuguese and Chinese as well.

Google Play said yes. Apple had other ideas.

Round two: Apple plays hard to get

While Android raced ahead, iOS was still parked at version 1.2.1 in App Store Connect. On 10 September it caught up: version 1.2.8, build 30, ten new screenshots and promotional text in eight languages. Before any of that there was the small matter of the Paid Apps agreement. Apple will not let you create a single in-app purchase until you have accepted it and filed your bank and tax details. Until then every attempt returns a 409, which is Apple's way of saying "not yet, and not until I have seen your paperwork".

Then we scripted all 39 purchases through the App Store Connect API. The first run failed on 24 of them with UNEXPECTED_ERROR. We ran it again and it came back clean. The runbook now contains the most zen sentence in the repository: re-run rather than debug.

The splash screen that wasn't

On a real phone our launch screen was unreadable, for two separate reasons. The storyboard filled the screen with square artwork, so on a tall phone it scaled until the height fitted and cropped about 54% of the width. The wordmark and the whole decorative frame went off the edge. Worse, the dark-mode versions were just the bare figure at about 5% of a cream canvas, which is an invisible logo on every phone set to dark.

We switched to fitting the artwork inside the screen on its own cream background, dropped the dark variants, and swapped in the logo lockup at 88% of the canvas. The image folder shrank from 55 MB to 9.1 MB. A first impression should not weigh 55 MB.

How to submit an app whose Store sells nothing

Here is a trap with excellent camouflage. In-app purchases are separate review items, and Apple will not review one that is not on your submission. The first time we submitted, the app went into review with all 39 products left behind at "Ready to Submit". Had it been approved, we would have shipped a game about buying and selling whose Store could sell nothing. Pulling it back cost us a Remove from Review and our place in the queue.

The trap is that Apple lets you start a draft submission from the In-App Purchases page that can never be submitted. With no app version on it, every product fails to add with "Unable to Add for Review", and submitting the draft fails with "add an app version for the selected platform". Neither message tells you the version has to go on first. We tried to script the fix, naturally. The API has no in-app purchase relationship on a submission at all. We tried three spellings before accepting that this door is UI only, and the runbook now says so, politely, so that nobody tries again.

The number that finally made us happy was forty: one app version, plus thirty-nine things to buy for it.

Rejection number one: Apple wants to know you better

On 11 September Apple replied. The subject line was Guideline 2.1, Information Needed. It was not a bug, a crash or a violation. Apple reported no defect at all. It was the questionnaire Apple sends to accounts with a short review history, and it came with a demand for a screen recording. Think of it as less of a rejection and more of a background check.

The list had seven points: a screen recording, what the app is for and who it is for, how to get in and try everything, which outside services it uses, whether anything changes by region, whether it is regulated or built on anyone else's material, and how the purchases work. They were reasonable questions, in the way a first date's questions are reasonable. The Resolution Center caps a reply at 4,000 characters and ours came to 3,917, which is the longest thing we have ever said to someone we had only just met.

Then the recording. Apple wanted the real flow at real speed on a real phone: a cold launch, a single-player game, the Store and its purchase sheet, registering, signing in, a multiplayer lobby and deleting the account again. Four minutes of iPhone footage at 60 frames a second weighs about 240 MB, which is too big to attach, so ffmpeg squeezed it to under 10 MB with the interface still readable. We wrote the whole shot list down, because if this project has taught us one thing it is that we will forget how we did anything.

The answers went in two places: the Resolution Center reply, and the review notes in the app's listing, so every future submission arrives having already answered the questions. Reviewers follow those notes literally. Write them for someone who has never seen your app, has forty seconds to spare and is holding an iPad. All three will turn out to be true.

One more thing turned up while we rehearsed. Deleting an account hung on "Deleting..." once and then worked on the second try. We suspect the server had dozed off, which to a reviewer looks exactly like a broken button. Keep your server awake while the reviewer is in town.

The trademark spring clean

While Apple had our attention, we walked through the game looking for anything that sounded like a brand. Apple's content-rights rules made us look, and we did not love what we found. Two personas owned a "BMW 3 Series (CPO)" and a "Honda Civic". The names added nothing to the game and invited plenty of trouble, so they are now a "Sports Car (CPO)" and a "Basic Sedan". The word "monopoly" left our App Store keywords.

Then there was the Lambo. It turned out the Lambo pawn was never a car at all. It was a chequered flag emoji the whole time, so the old name promised a supercar and delivered a race flag. Financially speaking, that is just marketing. It is now the Chequered Flag. The board theme called The Tank became Shark Pool.

The one rule we did not break.

We changed the display names and left every product ID exactly where it was. The chequered pawn is still pawn.lambo under the bonnet and always will be. Those IDs are live on both stores, tied to prices and named in the bundle grants, and renaming one would have revoked the item from everyone who already owns it. Names are copy. IDs are contracts.

Rejection number two: the iPad incident

On 17 September Apple came back, and this time it had found real problems. The reviewer was using an iPad Air (11-inch, M3) running iPadOS 27, because iPhone-only apps run on iPad in compatibility mode and get reviewed there. There were two findings. Guideline 2.1(a): tapping Continue with Apple or Continue with Google showed an error. Guideline 2.1(b): the reviewer could not find our 39 in-app purchases.

Both were our fault, and in a sense both were the same fault.

The bug

The sign-in plugin wants an options object with every call. On iOS, if it is missing, the plugin rejects with "Missing provider or options" before any sign-in sheet has a chance to appear. On Android the same plugin quietly assumes an empty one and carries on. So the same line of code sailed through Google Play review and fell over at the first tap on Apple's side, on every iPhone as well as every iPad.

One missing parameter. Android forgave it. iOS did not.

The Store nobody could find

The purchases were a separate misunderstanding that happened to fit the first one perfectly. Our old review notes told the reviewer that buying things needed a sign-in. The sign-in was broken. So the reviewer never reached the Store, in a closed loop of our own making.

It got worse when we looked closer, because the Store had three more ways to disappoint. If the product list loaded with no packages, the Store treated that as "nothing for sale" and hid every item you did not already own. The three bundles (5-Pawn, Themes and Starter Persona) had been hidden since June. And a guest who bought the 5-Pawn Bundle would have paid and unlocked nothing, because our server only expanded bundles into their items for signed-in players. A guest, of course, is exactly what a reviewer is. Taking someone's money and handing over an empty box is a fine financial lesson. It is just not one we wanted to teach.

The fix list, for the record. Pass the parameter. Make both sign-in sheets attach to the app's active window on iPad, because the plugin anchored on the first window and on iPadOS that is not always the visible one. Teach the Store that zero products loaded means "not loaded yet" rather than "empty". Bring the bundles back. Teach the app to expand bundles for guests. And rewrite the review notes to say, in plain words, that nothing needs a sign-in to buy and here is the exact path to the Store.

The result was 1.2.9. Its release note opens with the two sentences that cost us the most: "Sign-in fixes: Continue with Google shows the account picker on a deliberate tap, and native sign-in no longer errors out. The Store always lists its items, even before prices load." Two sentences, ten days of our lives.

Builds 32 and 33: the ones we don't talk about

You would think we could simply ship the fix. We did, twice, and it was wrong both times. On TestFlight builds 32 and 33, Google sign-in worked, but Sign in with Apple, Apple's own button in Apple's own testing programme, failed with AuthorizationError 1000.

The cause is obvious afterwards and invisible before. Entitlements travel in the code signature. Our upload script archived the app with signing switched off and left the signing to the export step, which can sign an app but cannot give it entitlements it never had. Sign in with Apple's entitlement never made it into the build. In developer terms, the app had left the house without its trousers.

The upload script now signs at archive time and refuses to upload any archive whose signature is missing the entitlement. We built a bouncer. It checks IDs. Builds 32 and 33 are dead, and build 34, the properly dressed one, is the build we sent back to Apple.

Then Apple said yes.

Hot stuff

By 24 September players had told us their phones were getting hot. iPhone 15s, iPhone 16 Pro Maxes, and the web version a bit warm too. We would love to say this was the raw sex appeal of compound interest. It was a timer.

The game ticked a counter once a second, in every mode, and every tick re-rendered the whole game: the board, every cell, every panel. Forever. Meanwhile the animated pawns were repainting up to 120 times a second on phones with fast displays, to draw a 30-frames-a-second animation. The full-screen blur behind every card was recalculated on every frame because the pawn kept moving underneath it. And the glows that made the board look alive were animating box shadows, which forces a repaint on every frame.

We fixed all four. The counter became a single timeout. The pawns draw whole frames only, and they pause when they are off screen, under reduced motion, or covered by a card. The glows and rings animate opacity and position instead of shadows, and they pulse three times and then rest. Idle work on the board fell from 624 ms to 15 ms over ten seconds of headless testing. With a card open and the dragon pawn on the board it fell from 1,188 ms to 11 ms. Our animations now show more self-restraint than we have shown anywhere else in this project.

It shipped as 1.2.10, headline "Cooler phones", alongside a fairer layoff rule. Only your salary stops when you are let go. Your side income keeps paying, and the bills are still due. Being fired should sting. It should not delete your side hustle.

The ledger: every release note, read back to back

We keep our release notes in one file, the same file that feeds both stores. Read in order, they make a strange kind of diary, so here it is with the subtext added. Dates are commit dates. The file skips from 1.0.1 straight to 1.2.6, so whatever happened in between happened without a diary. Each version number below links to its own post.

1.0.0

First release of Moneyflow. Build your financial empire across real estate, stocks, and businesses. Escape the 9 to 5 cycle, hit the Fast Track, and chase your dreams.

Earnest, brief and slightly terrified. Look how small it was.

1.0.1

Google Play Web purchases are now available at playmoneyflow.com. Stability and UX improvements throughout.

App Store Stability and performance improvements. Various bug fixes in the financial statement panel and dice animations.

Same version, two sets of notes. The stores have different ideas about what you may tell people, so we keep one set for each and try not to mix them up.

1.2.6

Taxes are in: income tax on your salary, 15% on side income, 15% capital gains on profitable sales. Personas now earn real 2025 US salaries. Rents and business returns follow the economy — thin in a bust, generous in a boom.

The taxman arrives. Nobody asked for this and everybody needed it. Every return in the game is now judged after tax, because that is the only return that matters.

1.2.7

Negotiate on deals, offers and loan quotes: one 50/50 coin flip, 20% better or 20% worse. Choose which property to sell in a Bidding War and which assets go in a divorce — or sign a Prenup.

Haggling in its innocent first form. Also the first appearance of the Prenup, which tells you what was on our minds.

1.2.8 7 Sep

Haggle twice: negotiate, then renegotiate — but the other side may walk away (10%, then 15%). Cards now fit your life: no divorce before a wedding, no stock sale without stocks. Divorce splits your net estate, and your ex can take on loans.

The romantic one. Ask twice and they get touchy. Until this version the deck could deal you a divorce before you were married, which is more chaotic than a Vegas chapel. It is also the version that took us to Apple's front door.

1.2.9 22 Sep

Sign-in fixes: Continue with Google shows the account picker on a deliberate tap, and native sign-in no longer errors out. The Store always lists its items, even before prices load.

Written under duress, by two rejections and one missing parameter.

1.2.10 26 Sep

Cooler phones: the game no longer keeps your device working hard while you play. Idle animations pulse a few times and then rest, and the board stops redrawing every second. Layoffs are fairer: only your salary stops, side income keeps paying, and expenses are still due on skipped paydays.

The one where we stopped giving your phone a fever.

1.2.11 26 Sep

New in the Buy menu: a city flat, a dry cleaner and a roadside motel. … Every card has its own artwork, and your choices sit right below the card. Invite friends to a private multiplayer room.

The most crowded release and one of the shortest lived, because 1.2.12 arrived that same evening. Private rooms are the headline for anyone who has friends: a host, two to four seats and a six-character code.

1.2.12 26 Sep

Short on cash? You now choose how to cover it, and see how close you are to bankruptcy: emergency loans in a row, borrowing room left and paydays to go. Emergency loans now cost less than a credit card.

Bankruptcy now comes with a countdown, which is the friendliest way we know to teach fear. Emergency loans now cost less than the credit card, which is more than real life will do for you. Also fixed: the dice used to roll themselves after you closed a card, which was either a bug or our most passive-aggressive feature.

1.3.0 27 Sep

24 new cards, from a roadside motel and a SaaS company to the Big Short, plus rarity: uncommon and rare cards now turn up. Hide a card to look at the board, then tap Back to card. Layoffs and emergencies can't be dismissed any more.

Twenty-four new cards, a rarity system, and quietly the most important change of the month: cards now arrive from the server. More on that below.

1.3.1 27 Sep

Borrow against your assets: any property, business or stock with no loan on it can now secure a cheaper, interest-only loan at the market rate plus 0.5%.

Leverage, again. It is a finance game and we cannot help ourselves. It followed 1.3.0 later the same day.

1.4.0 1 Oct

New Pro bots plan every move and read the economy, and every bot can now buy dreams, win and borrow against its assets. The economy bites: interest rates follow the boom-and-bust cycle, recessions cut your taxes, and your rents rise in a boom and slip in a recession.

The one where the bots learned to win. Until now none of them could, because none of them ever bought a dream. Pro bots arrived, the economy started to move rates, taxes and rents with its mood, and the app learned eight more languages.

1.4.1 1 Oct

… Mortgages now repay over 25 years, business loans over 15, car loans over 6; bank loans are interest-only, up to 67% of income. …

Mortgages finally have an end date. The loan work landed after 1.4.0 had been cut, so it shipped as 1.4.1 that same evening, along with a news card on the home screen.

1.4.2 1 Oct

One bug, fixed less than twenty minutes after 1.4.1: the Bridge Loan button now offers the amount the bank will really approve. It has no store notes of its own.

The weekend of five versions.

Saturday 26 September

Sunday 27 September

Commit times, Sofia time. Not every version reached every store as itself: on Google Play, 1.2.12 went to production in place of 1.2.11, and on iOS it was submitted in its place. Over the same weekend the deck picked up 130 illustrations, drawn in code.

The best update is the one nobody has to approve

By the end of that weekend we had learned something useful. The slowest part of shipping an update is not building it. It is waiting for a store to look at it. So 1.3.0 did something a little different: it taught the app to accept deliveries.

New cards now arrive from our servers, so most new content no longer needs an app update. It took one app release to install the machinery. After that, new cards are a deploy away, translations and illustrations included.

The Store works the same way. Apple reviews a new in-app purchase on its own, without a new build, so a new pawn no longer needs a new version either.

The clever part is the safety net. Nobody is ever dealt a card their app cannot play, so old and new versions can share a table without trouble. When we invent a genuinely new mechanic, we still go back to the queue like everyone else.

The same release brought rarity, which means some cards turn up far less often than others. How much less often is our secret, but the rarest ones show up about as often as an App Review passes first time. We drew a common.

The scoreboard

For the spreadsheet people.

What we would tell ourselves at the start

What used to be an evening of clicking is now a bump, a note and a handful of commands per store. The waiting is the only part we cannot automate. Everything else went into this list.

  1. Put the version on the submission before the in-app purchases. Apple will let you do it the other way round and then decline to say why.
  2. Write your review notes for a reviewer who has never seen the app. They have forty seconds and an iPad, and they follow the notes literally. Give them the exact path to everything.
  3. Never put a sign-in in front of your Store. Guests have wallets too, and reviewers are guests.
  4. Sign your archive, then make the script refuse to upload one that is not wearing its entitlements. Build yourself a bouncer.
  5. Make missing keys scream. Build 30 shipped without its payments key and nothing complained loudly, so the Store was simply blank. A silent failure is a rejection on a delay.
  6. Test on both platforms even when the code is shared. Android forgave what iOS refused, and one line of code had two different personalities.
  7. Rename products, never their IDs. Names are copy. IDs are contracts.
  8. Script it, make it repeatable, write it down. Apple's API sometimes just has a moment, so re-run before you debug. Our runbooks exist because we forgot everything twice.
  9. Keep separate release notes when the stores have separate rules. Same version, different sentences.
  10. Ship content from the server and save the store queue for new mechanics. The best update is the one nobody has to approve.
  11. Test on the hot hardware your players actually own. The simulator never blushed. An iPhone 16 Pro Max did.
  12. Keep the server awake while the reviewer is in town. A sleeping server looks exactly like a broken button.

Go on, take us for a spin

Moneyflow is free on the App Store, free on Google Play and free in any browser. There are no ads, and you do not need an account to start. Everything in the Store is cosmetic. Nothing in it helps you win, which in a game about money is either very principled or very bad business.

What is next? More cards, which now arrive from the server, more ways to play with friends, and, if the universe is kind, one full week without a version number.

Get it on the App Store Get it on Google Play Play in your browser

See you on the board.