Inspiration
Freelancers do two kinds of unpaid admin work. First they turn a messy client message (“did the logo, 2 revision rounds, rush fee, $150 deposit already paid”) into an invoice. Then they chase the payment. I wanted an agent that handles both, but I didn’t want one that silently sends money requests on my behalf. A wrong amount or the wrong client costs trust, and trust is hard to win back.
That made the hackathon theme a good fit. The agent does the tedious thinking, and a human stays in control of every action that moves money or contacts a client.
What it does
- Paste a messy client message.
- Extract. The AI agent pulls out the client, email, line items (rush fees become their own item), currency, deposit already paid, and due date.
- Review. You edit anything in a review screen. Nothing has touched PayPal yet.
- Approve. One click creates and sends a real invoice through the PayPal Invoicing API (sandbox).
- Track. PayPal webhooks flip the invoice to PAID on the dashboard, with polling as a fallback.
- Remind. When an invoice goes overdue, the agent drafts a polite, context-aware reminder for you to review.
How we built it
Backend: Java 21 and Spring Boot 3, with a small service layer (PayPalClient, LlmExtractor, InvoiceService, and controllers for the API and webhooks).
PayPal: OAuth client-credentials flow, POST /v2/invoicing/invoices to create the draft, then /send. Webhook signatures are verified with PayPal’s verify-webhook-signature endpoint.
AI: an LLM (Groq API) turns unstructured text into a strict JSON object. A second prompt drafts overdue reminders.
Frontend: a single static page with an editable review form and an AG Grid dashboard that polls for live status.
Challenges we ran into
Modeling a deposit. A “$150 already paid” amount isn’t a normal line item. I apply it as an invoice-level discount and had to check that PayPal accepted that request shape.
Webhook payload shape. I had to confirm where the invoice ID sits in the event and keep polling as a safety net.
Swapping LLM providers mid-project. I moved the extraction layer between providers, which meant updating the code, the config, and the README so they all matched.
Demoing “overdue” without waiting. A real due date takes days to pass, so I added a “Simulate overdue” action to show the reminder flow in the video.
Accomplishments that we're proud of
A complete, working loop on the real PayPal sandbox. You can paste a messy message, review the draft, approve it, pay it as a sandbox buyer, and watch the dashboard flip to PAID. It’s a genuine end-to-end flow, not a mockup.
Human approval enforced in code. The model can only produce a draft. The single path to PayPal is the approve endpoint, so no prompt, including a malicious one inside a client message, can make the agent send an invoice.
Messy input handled sensibly. Rush fees become their own line item, a deposit already paid is applied as a discount, and missing amounts default to 0 rather than being invented, so gaps show up in the review screen instead of on a client’s invoice.
Reliable status tracking. PayPal webhooks with signature verification, backed by polling, mean the dashboard stays accurate even when a tunnel drops.
An agent that follows up. Overdue invoices get a context-aware reminder draft, and the “Simulate overdue” action lets the whole flow be shown in under three minutes.
A submission that’s easy to run. An MIT license, a README with setup steps, sample input, and webhook instructions, and a clean build from a fresh clone.
Shipping solo on a tight clock
What we learned
In agentic commerce, the guardrails are the product. Getting an LLM to extract an invoice is the easy part. Deciding exactly where it may act, and making that boundary impossible to bypass, is the real design work.
Let the model interpret and let code decide. Structured JSON output plus deterministic validation (totals, email format, positive amounts, required fields) was far more dependable than trusting the model to do both.
Webhooks need a safety net. Local development requires a tunnel, and event payloads don’t always match your assumptions, so polling as a fallback made the demo trustworthy.
The PayPal sandbox is powerful. Separate business and personal accounts let me test the full lifecycle, including paying as a buyer, without risking real money.
Treat user-supplied text as untrusted. Client messages are input from outside the system, so the extraction prompt only extracts facts and the approval gate backstops it.
Provider-agnostic design pays off. Swapping the LLM provider mid-project was manageable because the extraction layer sat behind one small class.
Submission polish is part of the work. A detectable open source license, a runnable README, and a demo video under three minutes matter as much as the code.
What's next for InvoicePilot
Drafting invoices from documents Multi-currency and tax handling Recurring invoices and saved client rates Duplicate-message detection Sending approved reminders through PayPal’s native remind endpoint Accounting exports