Inspiration

A friend's family runs a small batik workshop in Yogyakarta. They lose tenders to bigger suppliers whose prices look lower on paper. Once shipping, customs and import VAT are added, those quotes often cost the buyer more. Nobody does that math when comparing bids, so the small workshop loses anyway.

There's a trust problem too. A hotel in Berlin won't pay a stranger in Indonesia upfront, and a six-person workshop can't wait two months to get paid. We wanted to build a tender where both of those problems go away, and where the small maker gets some help writing bids and answering questions, the way a big company has a sales team for that.

What it does

A tender owner types a few sentences about what they need. Their AI turns that into a proper tender and asks about anything left out, like size or packing. The owner checks it and publishes.

On the other side, a maker tells their agent what they make and roughly what it costs. The agent looks for tenders that fit, asks the owner questions, and seals a bid using the maker's own prices. While bidding is open, the owner's AI answers questions from the published tender. If it can't answer something, the question waits for the owner. Every bidder sees every answer, but nobody sees who asked.

Bids stay on the server until bidding closes. When it closes, FairBid compares every bid at what it costs delivered, ranks them, and the owner picks a winner. Payment goes through PayPal straight to the maker, in steps, as the order is made and shipped. Both sides get updates and a summary from their agent in the app and on Telegram.

How we built it

The app is Next.js 16 with Prisma and Postgres, running on Google Cloud Run. The AI parts use Gemini through Vertex AI.

Delivered cost is plain arithmetic in integer cents. For goods $g$, shipping $s$, duty $d$ and fees $f$:

$$D = g + s + d + f$$

Import VAT, $r_v(g + s + d)$, is added on top for buyers who can't reclaim it.

We decided early that the AI would never rank bids. Code works out the cost, lead-time and completeness scores and the weighted total, $T = \sum_i w_i s_i / 100$. The AI only scores the things code can't measure, such as whether something is really handmade. It sees each bid as a letter, without the bidder's name or price, and has to give a reason for every score. Code also flags pairs of bids that look coordinated. The AI explains each flag, and a person decides what to do with it.

For payment we use PayPal's Orders API in sandbox, with the maker as the payee from the start. The buyer approves a hold, and each milestone is captured when they confirm it. The final capture releases whatever wasn't used. FairBid never touches the money.

Everything that happens on a tender goes into a hash-chained log that can't be edited. Makers who want to use their own AI agent, Claude for example, can connect it through an MCP endpoint with the same rules as ours.

Challenges we ran into

PayPal holds expire after 29 days and can't be extended, and real orders often take longer than that. We ended up splitting longer orders into phases, each with its own hold, so no single hold has to last more than 28 days.

With the maker as payee, the sandbox wouldn't let us void or refund. At first that felt like a dealbreaker. In the end we made the first payment a deposit the buyer agrees to upfront, and let the final capture hand back the rest.

The AI agents run in the background after a page has already responded, and Cloud Run kept throttling the CPU and freezing them halfway through a conversation. That took us a while to figure out.

Getting two agents to talk through a sealed tender without leaking anything was fiddly too. A question can't reveal who asked it, and an answer can't change a price.

Accomplishments that we're proud of

You can watch a bidder's agent ask a question, the owner's agent answer it, and both sides get a short summary on Telegram, and none of it is scripted. The PayPal side really works in sandbox: real holds and real captures, paid directly to the maker. And if the AI goes down, the app falls back to scripted answers and says so, so the demo never breaks.

What we learned

PayPal's limits shaped the product more than we expected, mostly for the better. Phased payments and an upfront deposit are easier to explain to a buyer than what we started with.

We also learned to give the AI less authority, not more. Once we said plainly "code ranks, the AI explains", the whole thing got easier to trust and easier to pitch.

What's next for FairBid

Moving off sandbox to live payments, adding customs rules for more countries, and letting tender owners bring their own agent the way bidders already can. We'd also like a maker's track record of delivered orders to follow them from one tender to the next.

Built With

Share this project:

Updates

Submission history