Inspiration

Informal agreements happen where independent freelancers communicate: WhatsApp, Slack, DMs, and email threads. Turning those sign-off messages into an official invoice requires toggling between chat apps and the PayPal dashboard, manually re-typing line items, looking up payment terms, and calculating totals.

The biggest friction isn't just the typing—it's the fear of costly mistakes. A wrong currency code, an overlooked milestone price, or accidentally triggering an automated invoice email to an unprepared client damages professional relationships. Most "AI invoice" tools act as reckless black boxes that guess missing details or trigger external financial actions autonomously. We wanted to build an agentic commerce tool that respects freelancer sovereignty: AI prepares, links source evidence, and flags ambiguities—while the human approves every money-moving and client-facing gate.

## What it does Freelance Invoice Copilot guides freelancers through a transparent, guarded transaction lifecycle:

1. **Extraction with Character-Level Provenance Spans:**
  * Paste an informal client agreement or project sign-off message.
  * The copilot extracts client billing details, multi-deliverable
  line items, amounts, currency, and payment terms or due dates.
  * **Zero Guessing:** Every extracted field is linked to its exact
  character offset (`sourceSpan: { start, end, text }`) in the
  original message. Selecting any field in the review form highlights
  the exact quote in the source text.
  * **Explicit Clarification:** Ambiguous or unpriced items (such as
  `"$20/month"` recurring maintenance, `"revisions included"`, or
  missing currencies/payment terms) are never hallucinated or silently
  dropped—they are surfaced as required clarification questions before
  draft creation is allowed.

2. **Gate 1 — Create PayPal Draft (`POST /v2/invoicing/invoices`):**
  * After reviewing or editing the extracted fields, the freelancer
  explicitly approves **Gate 1**.
  * Pending form edits are auto-saved, validated against strict
  schemas, and sent to PayPal Invoicing v2 with a deterministic
  `PayPal-Request-Id` idempotency key.
  * PayPal creates an editable `DRAFT` invoice and returns its
  official invoice ID without emailing or notifying the client.

3. **Gate 2 — Send Invoice to Client (`POST/v2/invoicing/invoices/{id}/send`):**
  * Requires an existing PayPal draft and a second, separate human
  confirmation dialog summarizing the recipient, total amount, and
  payment terms.
  * Once confirmed, PayPal transitions the invoice to `SENT` and
  provides the hosted payer payment URL (`recipient_view_url`) and
  invoicer dashboard link.

4. **Gate 3 — Follow-up & Reminder Copilot (`POST
/v2/invoicing/invoices/{id}/remind`):**
   * For unpaid `SENT` invoices, the copilot drafts contextual
   follow-up messages across three selectable tones (`Gentle`,
   `Professional`, `Urgent`) grounded in the invoice's exact
   deliverables, total amount, and due date.
   * Requires explicit **Gate 3** confirmation before calling PayPal's
   `/remind` endpoint, enforces PayPal's maximum of **2 reminders per
   day** to prevent client spam, and automatically locks once the
   invoice status reaches `PAID`.

5. **Zero-Friction Judge Evaluation (Recorded Sandbox Simulation
Mode):**
   * Out of the box, judges can run `npm start` and evaluate the entire
   3-gate workflow—including Gate 3 reminders and simulating buyer
   payment (`SENT` -> `PAID`)—without needing PayPal Sandbox
   credentials or paid LLM API keys. When `PAYPAL_CLIENT_ID`,
   `PAYPAL_CLIENT_SECRET`, and `OPENAI_API_KEY` are configured, the app
   seamlessly switches to live PayPal Sandbox and OpenAI-compatible AI
   calls.

How we built it

* **Backend & Domain Layer (Node.js + TypeScript + Zod):**
  * `src/schema.ts`: Zod data contracts, `SourceSpan` provenance
  models, reminder notification schemas, and the PayPal Invoicing v2
  payload builder.
  * `src/approval.ts`: Pure, unit-testable state machine enforcing
  transitions (`proposed` -> `draft_created` -> `sent`) and Gate 3
  daily rate-limiting (`canSendReminder`, max 2/day).
  * `src/extractor.ts` & `src/aiExtractor.ts`: Dual-engine extraction
  architecture combining an offline `DeterministicExtractor` with an
  `OpenAiExtractionProvider` that verifies every LLM-quoted substring
  against the raw input text.
  * `src/reminderDrafter.ts`: Context-aware
  `DeterministicReminderDrafter` and `OpenAiReminderDrafter` supporting
  `gentle`, `professional`, and `urgent` tones.
  * `src/paypal.ts`: Direct REST client for PayPal Invoicing v2
  (`/v1/oauth2/token`, `/v2/invoicing/invoices`, `/send`, `/remind`)
  with in-memory OAuth token caching and a strict sandbox-by-default
  guardrail.
  * `src/workflow.ts`: `InvoiceWorkflowService` orchestrator with
  per-session concurrency locks (`withSessionLock`) and
  `RecordedPayPalGateway` for zero-key simulation.
* **Frontend Web UI (`public/`):**
  * Zero-build-step, accessible Single-Page Application using semantic
  HTML5 (native `<dialog>` confirmation modals, ARIA live regions), CSS
  container queries, and interactive quote highlighting.
* **Automated Verification (`test/`):**
  * **44 automated tests across 8 Vitest suites** (`approval`,
  `extractor`, `aiExtractor`, `reminderDrafter`, `paypal`, `workflow`,
  `server`, and `ui`) plus zero-error TypeScript static checking.

Challenges we ran into

1. **Official SDK Coverage Gap for Invoicing v2:**
  * While inspecting `@paypal/paypal-server-sdk` v2.5.0, we found
  controllers for Orders, Payments, and Subscriptions, but no
  controller for **Invoicing v2**. We built a clean, strongly typed
  native `fetch` REST client in `src/paypal.ts` with OAuth 2.0 token
  caching, idempotency headers, `204 No Content` handling, and a
  hostname guardrail that blocks accidental calls to live production
  PayPal unless explicitly overridden.
2. **Eliminating Hallucinated Quotes & Silent Line-Item Drops:**
  * LLMs frequently paraphrase text instead of quoting it verbatim,
  and naive regex parsers silently ignore unpriced list items like
  `"3. Monthly Maintenance: $20/month"`. We solved both by verifying
  exact substring offsets against the source message and turning
  unpriced or recurring list lines into explicit clarification items
  that block Gate 1 until resolved.
3. **Preventing Race Conditions & Stale Form Approvals:**
  * Double-clicking an approval button or clicking "Approve Draft"
  with unsaved form edits could cause duplicate drafts or stale
  invoices. We added per-session in-flight locks (`withSessionLock`),
  reusable `PayPal-Request-Id` keys per draft version, and automatic
  form-save synchronization prior to Gate 1.

Accomplishments that we're proud of

* **True Human-in-the-Loop Agentic Commerce:** Designing an AI workflow
that refuses to guess missing financial terms and enforces three
distinct human approval gates across draft creation, invoice sending,
and overdue follow-ups.
* **44 Automated Tests & Zero TypeScript Errors:** Comprehensive test
coverage across pure state machines, provenance preservation when line
items are edited or removed, REST endpoints, and UI controllers.
* **Turnkey 30-Second Judge Experience:** Anyone can clone the
repository, run `npm install && npm start`, and test the complete
lifecycle immediately without configuring API keys—or plug in PayPal
Sandbox and OpenAI credentials for live execution.

What we learned

* PayPal's Invoicing v2 REST API is rich and expressive, supporting
multi-item deliverables, standard payment terms (`DUE_ON_RECEIPT`,
`NET_10`, `NET_14`, `NET_30`, etc.), hosted payer views, and native
`/remind` notifications.
* In financial software, autonomy without clear boundaries is a
liability. Users want autonomous *extraction and drafting*, paired with
deliberate, well-informed *human approval* before external side effects
occur.

What's next for Freelance Invoice Copilot

* **PayPal Webhook Listener (`INVOICING.INVOICE.PAID` /
`INVOICING.INVOICE.SCHEDULED`):** Real-time status updates and
automated project handoff checklists the moment a client completes
payment.
* **Tax, Discount & Multi-Milestone Templates:** Supporting VAT/GST tax
profiles and splitting multi-phase project sign-offs into linked
deposit and final-milestone PayPal invoices.
* **Multi-Channel Thread Ingestion:** Browser extension and
email-forwarding hooks so freelancers can send threads directly from
Gmail, Slack, or WhatsApp into their Copilot workspace.

Built With

Share this project:

Updates

Submission history