Inspiration
Ask any freelancer what they hate most and it's rarely the work. It's the admin around getting paid: building invoices line by line, remembering who hasn't paid, and writing awkward "just following up…" emails. Late payments are common, and many freelancers never chase them because it feels uncomfortable. PayPal already has great invoicing and checkout rails. We wanted an agent that operates them for you, in plain English, without ever sending something you didn't approve.
What it does
FreelancerPay Agent is a chat assistant sitting on top of the PayPal Invoicing v2 and Orders v2 APIs.
- Bill in one sentence. Type "Invoice Sarah Lee from Lumen Labs ([email protected]) for 12 hours of logo design at $85/hr plus $40 for licensed fonts, due in 21 days." The agent drafts professional line items with scope descriptions and shows an invoice preview card. Click Confirm & send and it generates the next invoice number, creates the draft, and sends it through PayPal.
- Know who owes you. A live dashboard and the agent show outstanding, overdue, and collected totals from PayPal.
- Chase politely. Say "Send Maya a friendly reminder." The agent writes a reminder whose tone fits how overdue the invoice is. You edit it if you want, confirm, and it goes out through PayPal's remind endpoint.
- Get paid instantly. It creates a PayPal Checkout (Orders v2) Pay-now link for any unpaid invoice. When the client pays, the app captures the order and records the payment on the invoice, so the dashboard flips to Paid on its own.
- Mark offline payments. "Maya paid me cash" records the payment on the invoice, again after confirmation.
Verified on the live PayPal sandbox. The demo video is a real run through the app's UI against api-m.sandbox.paypal.com, nothing mocked:
- AI-drafted invoice confirmed and sent:
INV2-AMSP-9G64-NMMZ-8CUU(#0011, USD 1,060.00, statusSENT). - Edited reminder sent for overdue invoice
INV2-59TZ-X95U-QCSN-MLTL(#0002):remindreturned 204. - Pay-now link: Orders v2 order
06P77078E8284861K. The buyer paid on PayPal's hosted sandbox checkout (guest, sandbox test card), PayPal redirected to our return URL, and the app captured it: capture93159563BV797072J,COMPLETED. - The payment was recorded on the invoice (
EXTR-626758510P232040G), and #0002 flipped toMARKED_AS_PAID.
How we built it
- Backend: Python + FastAPI. A small typed PayPal REST client covers OAuth2 client credentials,
generate-next-invoice-number, create/list/get/send/remind/record-payment on/v2/invoicing/invoices, and/v2/checkout/orderscreate + capture. - Agent: An OpenAI-compatible function-calling loop with 6 PayPal tools. It is provider-agnostic, so the same code runs on Groq, Gemini, OpenAI, or a local Ollama model. We developed and tested on Qwen2.5-3B-Instruct running locally on CPU via Ollama.
- Human-in-the-loop gate: Tools that email a client or change the books are proposed, not executed. The UI renders a confirmation card, and only the Confirm button triggers the PayPal call.
- Grounding guardrails:
- The client email must appear in what the user typed.
- Every price must be one the user stated.
- Totals are cross-checked against a deterministic parser.
- Reminders citing the wrong invoice number or amount are replaced with a safe template.
- Each turn, the model gets a live snapshot of the real open invoices.
- Violations go back to the model as tool errors so it corrects itself.
- Faithful mock PayPal: We swap the server, not the client. The real client sends real HTTP requests through an in-process fake that returns sandbox-shaped responses and PayPal-format errors. The whole app runs with zero credentials, and switching to the sandbox is just
PAYPAL_MODE=sandbox. - No-key fallback: A deterministic planner emits the same tool calls, so judges can try the full flow without any AI key.
- Frontend: Hand-written HTML/CSS/JS with no build step: chat, tool-call trace chips, confirmation cards, and an invoice dashboard.
- Tests: 30 pytest tests. 28 run offline and cover the PayPal client and mock, the parser, the agent (with a scripted fake LLM that checks gating, grounding, and fallback), and the HTTP API end to end. 2 opt-in live tests hit the real sandbox: create → send → get/list → remind → Orders v2 link → capture-before-approval is rejected (422) → cancel, plus bad credentials → 401.
- Honest disclosure: This project was built with substantial help from an AI assistant (Grok Bot).
Challenges we ran into
- Small models hallucinate in exactly the wrong places. Our local 3B model once invoiced "1 × $85" for "12 hours at $85/hr," appended ".example" to a client's email, and invented invoice IDs. We didn't just hope for a bigger model. We built grounding checks and fed it live invoice context, and it went from 2/5 to 5/5 correct tool calls in our scenario tests.
- Making the demo work without credentials, without faking the integration. A mocked client would have hidden real bugs, so we mocked the PayPal server. That way OAuth, headers, JSON bodies, and error handling all run through production code.
- The sandbox caught a bug the mock didn't. Paying the same invoice a second time failed at capture with
DUPLICATE_INVOICE_ID, because every order reused the samepurchase_units[].invoice_id. We gave each order a unique suffix and taught the mock to enforce the same rule, with a regression test. - Closing the loop on Pay-now links. An Orders v2 payment isn't automatically tied to an invoice, so the return URL captures the order and then records the payment on the invoice.
Accomplishments that we're proud of
- An end-to-end agentic commerce flow, from natural language to a PayPal invoice to a reminder to a captured payment to Paid, that never sends anything without an explicit click.
- It runs on a free local model on a laptop CPU, and gets better with any hosted model.
- One-command setup and a real test suite.
What we learned
- Agent safety in commerce comes less from the prompt and more from where you put the gates and how you validate tool arguments against the user's own words.
- PayPal's invoicing API is rich: send, remind, record payments, QR codes, recurring series. It's a natural fit for agents.
What's next for FreelancerPay Agent
- Recurring invoices (
/v2/invoicing/recurring-invoices) for retainers, and automatic reminder schedules. - Webhooks (
INVOICING.INVOICE.PAID) for real-time status and thank-you notes. - Creating invoices from email threads or contracts, multi-currency, and tax handling.
- Venmo and Pay Later options on the Pay-now page.