FreshBooks

Lightweight, dependency-free, in-memory FreshBooks API fake for testing code that uses the FreshBooks Accounting API.

Default port: 4872

Quick start

import { FreshbooksServer } from "./services/freshbooks/src/server.js";

const server = new FreshbooksServer(4872);
await server.start();
// ... run your app/tests ...
await server.stop();

All API routes require an Authorization: Bearer <token> header (any non-empty value accepted):

const res = await fetch(
  "http://127.0.0.1:4872/accounting/account/parlelAcct/users/clients",
  {
    method: "POST",
    headers: { Authorization: "Bearer parlel", "Content-Type": "application/json" },
    body: JSON.stringify({ client: { fname: "Jane", email: "jane@parlel.dev" } }),
  }
);

Access via MCP / preview URL

Reachable at its preview URL (http://127.0.0.1:4872) and through the parlel MCP server as the freshbooks tool. Set FRESHBOOKS_BASE_URL=http://127.0.0.1:4872, FRESHBOOKS_ACCOUNT_ID, and any non-empty FRESHBOOKS_TOKEN.

Implemented operations

Response shapes

A single accounting resource is nested:

{ "response": { "result": { "client": { "id": 1001, "email": "..." } } } }

A list adds pagination siblings:

{ "response": { "result": { "clients": [ ... ], "page": 1, "pages": 1, "per_page": 15, "total": 1 } } }

Errors use { "response": { "errors": [{ "message", "errno" }] } }.

Surface coverage

This emulator faithfully replicates the API surface most application code and agents exercise. Anything below the supported lines is either an intentional design choice for a fast, zero-cost local emulator (✓ By design) or a candidate for a future release (⟳ Roadmap) — never a silent inaccuracy.

Legend: ✅ fully supported · ◐ accepted (stored, not strictly enforced) · ✓ by design · ⟳ on the roadmap.

FeatureStatus
users/me identity✅ Supported
Clients CRUD✅ Supported
Invoices list / create / get✅ Supported
Bearer auth✓ By design — Any non-empty credential is accepted — no real secrets needed
OAuth token exchange / refresh⟳ Roadmap
Payments / expenses / time-tracking / projects⟳ Roadmap
include[] sub-resource expansion⟳ Roadmap — Not modelled

Manifest

See services/freshbooks/manifest.json — name freshbooks, port 4872, protocol http, healthcheck /health, env FRESHBOOKS_TOKEN, FRESHBOOKS_ACCOUNT_ID, FRESHBOOKS_BASE_URL.

<!-- parlel:testenv:start -->

Configuration — test.env

Copy these into your test.env (used by the bridge sidecar flow). Tokens are Parlel's seeded test credentials — any non-empty value is accepted by the emulator, so you rarely need to change them. Swap in real credentials only when pointing at the live service in prod.env.

FRESHBOOKS_TOKEN=parlel
FRESHBOOKS_ACCOUNT_ID=parlelAcct
FRESHBOOKS_BASE_URL=http://parlel-bridge:4872
<!-- parlel:testenv:end -->