TL;DR

Type a scrappy job note → Sorted's AI drafts a UK invoice → it's created and sent through the PayPal Invoicing API → the customer pays on PayPal's real payer page → a verified PayPal webhook marks it paid in the ledger → overdue payers get escalating reminders, each drafted by a PayPal Agent Toolkit agent and sent only after a "Needs your OK" click. The hosted demo runs on a live PayPal sandbox by default.

What's live vs mocked

Live (PayPal sandbox): invoice create/send, payer page, QR codes, reminders and cancel through @paypal/agent-toolkit, INVOICING.INVOICE.PAID/.CANCELLED webhooks with signature verification, ledger sync.

Real AI: Groq free tier (openai/gpt-oss-20b) with free fallbacks, plus a deterministic rules engine if every model is busy. Every answer says which engine produced it.

Mocked only in demo mode: if the server has no PayPal keys, a mock PayPal and 21 seeded invoices run in the browser. Nothing is emailed.

Not verifiable in sandbox: Pay in 3 eligibility (PayPal decides on its own page, so the copy is hedged).

Inspiration

UK businesses are owed about £26bn in late payments at any one time, and 38 close every day because of it (Department for Business and Trade, 2025). Sole traders feel it most. A plumber finishes a job at 6pm, scribbles "2.5 hrs, new valve 18 quid, call out 45" on the back of a receipt, and the invoice goes out days later, if at all. Chasing it is awkward, so they don't. We wanted the paperwork to take thirty seconds and the chasing to happen without the awkwardness.

What it does

Messy notes → invoice. Type or dictate a job note. Sorted pulls out the customer, email, labour (hours × rate or a day rate), parts, call-out, VAT and payment terms, and drafts an editable invoice in GBP.

Sent through PayPal. One click creates and sends it with the PayPal Invoicing API, so the customer gets a secure link to pay by card or PayPal.

A ledger that does the maths. Every invoice lives in an AG Grid ledger: status chips, days-overdue bars, a filtered totals row and CSV export.

Chasing that escalates politely. Overdue invoices get reminders that move from a friendly nudge to a firm reminder to a final notice. For business customers, the final notice cites the Late Payment of Commercial Debts (Interest) Act 1998 and works out statutory interest and fixed compensation. Private customers never get that wording, because a guard rail blocks it.

Ask Sorted. A tool-calling agent answers "Who owes me the most?", "What did I earn in October?" or "Chase my worst payer" straight from the ledger. Anything that would contact a customer or change an invoice comes back as a "Needs your OK" card. The agent never sends anything without a click.

How we built it

Next.js 16 + TypeScript on Vercel, with Tailwind v4. It has no database: demo state lives in the browser and live state lives in PayPal.

PayPal Invoicing v2 REST: OAuth with token caching, generate-next-number, create (with idempotency keys and Prefer: return=representation), send, list/detail hydration, remind, and record payment. It retries on 429/5xx and shows PayPal debug ids in errors.

PayPal Agent Toolkit (@paypal/agent-toolkit): the model gets the toolkit's tools directly: list_invoices, get_invoice and generate_invoice_qr_code run freely; send_invoice_reminder and cancel_sent_invoice run only after you confirm. It reuses our cached OAuth token.

AI layer: one provider-agnostic adapter for any OpenAI-compatible model with native tool calling. It runs on free tiers first (Groq openai/gpt-oss-20b, then other free models) and falls through on rate limits. A provider that hits a rate limit is parked briefly so requests stay fast.

A deterministic fallback for everything: a clause-based UK job-note parser ("18 quid", "vat on top", "call out 45", "pays in 14 days"), template reminders and a rules agent. With no AI at all, the app still works, and every answer shows which engine produced it.

PayPal webhooks: a verified /api/paypal/webhook route flips invoices to paid or cancelled the moment PayPal says so; a sync diff catches anything missed.

Signed approvals: every write route needs an HMAC-signed, single-use, 10-minute approval token, so neither the model nor a stray request can send or cancel anything on its own.

AG Studio dashboard: a money-owed scoreboard, overdue heat tile, KPIs, city filter, cash-in chart with cross-filtering, and an "Ask Sorted Studio" agent.

AG Grid Community 36: custom cell renderers, an external filter driven by status chips, quick search, a pinned totals row over the filtered rows, CSV export and responsive columns.

Bring-your-own sandbox: judges can paste their own PayPal sandbox keys in "Connect PayPal sandbox". The keys stay in that browser and are pinned to the sandbox host, so they can never move real money.

Challenges

PayPal's list endpoints return summaries without line items or VAT, so we hydrate invoice details in small parallel batches.

The Agent Toolkit returns PayPal errors as data rather than throwing, so a reminder on a paid invoice looked like a success until we caught it.

generate-next-invoice-number doesn't reserve the number, so creates retry on duplicates and failed drafts are cleaned up.

Keeping free LLM tiers usable meant frugal design: one call per parse, a 10-minute cache, at most three tool rounds, and no nested model calls.

Accomplishments

A full live sandbox loop works end to end: create → send → customer pays → webhook → remind → cancel.

An agent that's genuinely useful but can't act without consent.

It works with zero configuration, so anyone can open the link and try it in ten seconds.

195 unit checks, a 26-check production smoke test and a 24-step live sandbox E2E.

What we learned

Agentic commerce works best when the agent drafts and the human approves. The money-moving step should always be one deliberate click. We also learned that UK late-payment law is a big help to sole traders, and almost nobody uses it.

What's next

Live (non-sandbox) PayPal onboarding, scheduled automatic nudges with approval by text, recurring jobs, a Making Tax Digital export, and Welsh-language reminders.

Built With

  • ag-grid
  • gpt-oss
  • groq
  • nextjs
  • paypal-agent-toolkit
  • paypal-invoicing-api
  • react
  • tailwindcss
  • typescript
  • vercel
  • web-speech-api
Share this project:

Updates

Submission history