Lemon Squeezy

Lightweight, dependency-free, in-memory Lemon Squeezy API fake for testing code that uses the Lemon Squeezy JSON:API REST surface (and the official @lemonsqueezy/lemonsqueezy.js SDK).

Default port: 4873

Quick start

import { LemonSqueezyServer } from "./services/lemon-squeezy/src/server.js";

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

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

const res = await fetch("http://127.0.0.1:4873/v1/products", {
  headers: {
    Authorization: "Bearer parlel",
    Accept: "application/vnd.api+json",
  },
});

Access via MCP / preview URL

Reachable at its preview URL (http://127.0.0.1:4873) and through the parlel MCP server as the lemon-squeezy tool. Set LEMONSQUEEZY_BASE_URL=http://127.0.0.1:4873 and any non-empty LEMONSQUEEZY_API_KEY.

Implemented operations

Response shapes (JSON:API)

Single resource:

{ "jsonapi": { "version": "1.0" }, "data": { "type": "products", "id": "1", "attributes": {} }, "links": {} }

Collection:

{ "jsonapi": { "version": "1.0" }, "meta": { "page": { "currentPage": 1, "total": 1, ... } }, "data": [ ... ], "links": {} }

Errors use { "jsonapi": {...}, "errors": [{ "status", "title", "detail" }] }.

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
Products / orders / subscriptions / stores list+get✅ Supported
Checkouts list / create✅ Supported
users/me✅ Supported
JSON:API single + collection envelopes✅ Supported
Bearer auth✓ By design — Any non-empty credential is accepted — no real secrets needed
include / filter / sparse fieldsets⟳ Roadmap — Ignored
Real cursor pagination◐ Single page only
Webhooks / license keys / discounts⟳ Roadmap

Manifest

See services/lemon-squeezy/manifest.json — name lemon-squeezy, port 4873, protocol http, healthcheck /health, env LEMONSQUEEZY_API_KEY, LEMONSQUEEZY_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.

LEMONSQUEEZY_API_KEY=parlel
LEMONSQUEEZY_BASE_URL=http://parlel-bridge:4873
<!-- parlel:testenv:end -->