It started the way these things always start. My family kept fumbling the same problem every week: everyone wanted different snacks, drinks, lunches, and dinners, but we still had to place one grocery order. Sticky notes. Texts. “Did you add the coffee?” Somebody always forgot the coffee.
So I decided to build the obvious thing — a shared app where each family member adds what they want, and it combines everything into one organized shopping list.
Cool. A CRUD app with some grouping logic. Done that before.
Except the app was the easy part. The part that ate my evenings for weeks wasn’t the code — it was a deceptively simple question: how do I connect a grocery list to a real store?
Spoiler: in the US, in 2026, as an individual building something non-commercial, you mostly can’t. Here’s the whole ride.
The part that actually was simple
Let me get this out of the way, because I don’t want to undersell it: the core of FamCart came together nicely.
It’s a Next.js PWA on top of Supabase. Supabase does a lot of heavy lifting here — auth, Postgres with row-level security so every query is scoped to a household, and realtime so when my wife adds milk on her phone, it shows up on mine a second later. Family members each keep their own requests and favorites, and FamCart consolidates the overlaps.
The one bit of logic I’m actually proud of is that consolidation preserves who asked for what. If three people each want bananas:
Samuel: 4, Sarah: 3, Aiden: 2
the store should just see “Bananas ×9.” But FamCart still remembers the 4/3/2 split, so nobody’s request quietly disappears into a total. That “combine the quantity, keep the allocation” rule sounds trivial and absolutely is not once recipes, meal plans, pantry staples, and manual adds all feed the same list.
From there it grew the way these things do — recipes (with URL and photo import), a weekly meal planner that scales ingredients, pantry tracking, and a little household activity feed. What starts as “just a grocery list” quickly turns into a system.
I even added voice. More on that in a second, because it’s the fun part.
The point is: none of that was the wall. The wall was Walmart.
The retailer-data rabbit hole
FamCart was always designed to be retailer-neutral — it figures out what the family needs, and the retailer handles buying, pricing, and fulfillment. That separation was intentional and it saved me. But I still needed a retailer to actually match my list to real products.
I shop at Walmart. So I applied for Walmart’s Online Pickup & Delivery (OPD) API — the one that gives you store-specific products, pricing, and pickup availability. That’s exactly what I wanted.
What I got back was a recommendation to use the Affiliate Marketing API instead.
Here’s the thing about the Affiliate API: it’s genuinely nice to work with. App-to-app auth with a signed request, no client secret, and you’re pulling product data in an afternoon. (One gotcha that cost me an hour: the signing functions live in Postgres’s extensions schema, and my security-definer function ran with an empty search_path, so gen_random_bytes “didn’t exist” until I schema-qualified it. Classic.)
But the Affiliate API has a ceiling you cannot design your way past:
It returns Walmart’s national catalog. It has no idea which store is mine.
So “available” means “available somewhere on walmart.com,” not “on the shelf at my store today.” I’d match an item, click through to check it, and get a “We couldn’t find this page.” I searched “ground turkey” and got two results — both brands we don’t buy. It works great for what it is. What it is just isn’t store-accurate.
I went back and asked Walmart, politely, whether OPD was still on the table or if Affiliate was the final answer. The reply: “Affiliate API recommendation is the final response to that request.”
Okay. Off the table. Or so I thought — but hold that thought.
So I went shopping for other doors
If Walmart wouldn’t open OPD, maybe someone else had store-accurate data. I evaluated the whole landscape. Quick tour:
Instacart Developer Platform — technically perfect for this: turn a list into a hosted cart across local retailers. Except they’ve stopped accepting new developer applications. Door closed before I could knock.
MealMe — a genuinely impressive API. Search across a million+ stores, real localized inventory, cart, checkout. Exactly the capability I wanted. But it’s a commercial B2B platform: access is gated behind a “what’s your company” form, no public pricing, no free tier. My honest use case — private, single household, non-commercial — is precisely the profile a transaction-fee business passes on.
Pepesto — the best-designed option I found, and individual-friendly too: pay-as-you-go credits, no commercial gatekeeping, clean recipe-to-cart endpoints. One problem. It covers 26 supermarkets across 11 European countries. Zero US stores. Perfect tool, wrong continent.
A RapidAPI “grocery” endpoint — cheap, easy, and… a scraper of Walmart/Amazon search results with ~12-second latency and someone else’s affiliate tags baked into the links. Still national, still fragile. Pass.
See the pattern? In the US, a grocery API that’s store-accurate, individual-accessible, and affordable basically doesn’t exist. That combination only shows up in Europe or behind a commercial contract. It’s not a gap in my Googling — it’s the actual shape of the market.
The scraping temptation (and why I didn’t)
At my lowest point I asked the obvious question: could I just scrape my own Walmart store?
I sat with the ethics honestly. For personal, low-volume use, reading prices I can already see with my own eyes isn’t some great moral crime. But it violates Walmart’s terms of service, it risks getting my own Walmart account — the account this app exists to help me shop with — suspended, and doing it reliably means defeating bot detection, which I’m not going to build.
So, no. The reliably-correct, zero-risk version of “shop at my real store” already exists: it’s Walmart’s own app, where I’m logged in and looking at my actual store. FamCart’s job is to hand off a clean, consolidated list; I finish there. That’s not a sad compromise. It’s the intended path, and it sidesteps every problem above.
The fun detour: talking to my groceries
While the API drama played out, I built the feature my family actually uses most: voice quick-add. Standing in the kitchen, you say “we’re out of pasta, add two boxes,” and it lands on the shared list.
I went deterministic instead of reaching for an LLM. A small parser strips filler words, pulls quantities and units, and figures out intent — “out of X” zeroes the pantry item and adds it to the list; “I still have three boxes of spaghetti” just updates the pantry. The satisfying bug to fix: “out of pasta, add two boxes” splits on the comma, and “add two boxes” has no noun of its own — so the quantity was getting orphaned. The fix was to carry a trailing quantity back onto the previous item. Little grammar, big payoff.
It talks to a token-authenticated endpoint, so an iPhone Shortcut (“Hey Siri, FamCart”) or the in-app mic button both hit the same code. No always-on listening, no creepy background mic. Tap or wake-word only.
What I’d tell past me
A few things crystallized on this one:
- Build the parts nobody can gatekeep first. FamCart’s real value — shared lists, consolidation, recipes, meal plans — never depended on a single API. Because I built that core standalone, the retailer saga was a disappointment, not a blocker. The app is fully useful today.
- Put the volatile stuff behind an interface. Every retailer lives behind a provider boundary. Walmart Affiliate is just the current implementation; swapping in OPD or MealMe later is a contained change, not a rewrite.
- Non-commercial projects hit walls commercial ones don’t, and that’s worth knowing before you fall in love with a feature. The most capable grocery APIs assume you’re a business with transaction volume. Plan around it.
- The honest hand-off beats the fragile integration. A great list handed to the retailer’s own app will always beat an approximate, ToS-violating, breaks-every-Tuesday scrape.
The complexity was never in the CRUD. It was in the rules — and in who’s willing to hand you the data.
The twist ending
Remember “Affiliate is the final response”? A few days later, a new email showed up in the same thread:
“Adding product team… Looping in our product team, who will be able to assist.”
Front-line support could only ever hand me the public Affiliate API — that’s why they kept pointing there. But pushing, politely and specifically, on what I actually needed got the request escalated to the people who can actually say yes. My subscription’s still marked Pending, not Rejected.
So the door I thought was closed is cracked open again. I’m framing the ask as narrowly as I can — read-only localized catalog data, checkout stays entirely with Walmart — and we’ll see.
Either way, FamCart already does the thing I set out to build: my family shows up with one organized list, and nobody forgets the coffee. The retailer integration is a nice-to-have chasing a moving target. The system underneath it is the real project.
And if Walmart’s product team says yes? That’s a very good problem to have.