Developer Integration Guide

Connect your app to LedgerLine accounting infrastructure.

LedgerLine gives app builders API-key-authenticated access to customers, estimates, invoices, payments, documents, vendors, bills, reports, webhooks, embedded settings, and accounting workflows. This public guide uses fake examples only and is safe to read before dashboard setup.

API keys are server-side credentials. Do not expose them to React client components, browser bundles, mobile apps, logs, screenshots, or AI prompts. Use fake placeholders in docs and prompts, then store real test keys only in server-side env vars.

Setup

Create a connected app in LedgerLine, choose test or live mode, and create an API key. API keys must stay server-side. Test keys start with `ll_test_`; live keys start with `ll_live_`.

LEDGERLINE_BASE_URL=https://api.your-ledgerline-domain.com
LEDGERLINE_API_KEY=ll_test_replace_me
LEDGERLINE_WEBHOOK_SECRET=whsec_test_replace_me

Use bearer authentication on every public API request:

Authorization: Bearer ll_test_replace_me

LedgerLine derives organization, connected app, environment, and API key context from authentication. Public APIs reject trusted client-submitted scope fields such as `organization_id`, `connected_app_id`, `app_environment_id`, `environment`, and `mode`. Valid business ids like `customer_id`, `invoice_id`, `vendor_id`, `bill_id`, `expense_account_id`, and `cash_account_id` remain allowed where documented.

Enable the modules that match your workflow in connected app setup. Money-in uses customers, estimates, invoices, and payments; money-out uses vendors and bills/A/P; documents use the documents module; reports use reports, with A/P and 1099 summaries also tied to bills/A/P or 1099 support. These are setup guidance and soft-warning signals today. Hard module enforcement and `module_disabled` responses are planned for a future opt-in rollout.

Integration Quickstart Sequence

Use this order when wiring a SaaS app to LedgerLine. It keeps secrets server-side, proves connectivity before mutations, and makes accounting impact review part of the integration instead of a late surprise.

Step 1

Server setup

Create server-only env vars, normalize the LedgerLine base URL, and keep the API key out of browser bundles.

GET /api/v1/auth/check

Step 2

Read-only starter

Use the repo-local Next.js starter to prove auth and reports before creating records.

examples/nextjs-ledgerline-starter

Step 3

Test-mode workflows

Run opt-in money-in and money-out scripts only with fake data, a non-placeholder ll_test_ key, and explicit mutation approval.

examples/test-mode-workflows

Step 4

Webhook receiver

Use the fake-only receiver for signature verification, fast 2xx handling, safe logs, and idempotency design.

examples/webhook-receiver

Step 5

Accounting impact review

Check which calls create journals, which stay operational, and where reports should tie back to source records.

/developers/accounting-model

OpenAPI Spec

LedgerLine serves the current manual OpenAPI source as public developer documentation at /developers/openapi.yaml. The source file remains docs/openapi/ledgerline.v1.yaml in the repository and must be updated when public `/api/v1` routes change.

The spec is documentation-only. LedgerLine does not generate route behavior, SDK code, or accounting behavior from it yet. Local validation is available with `npm run validate:openapi`; a public JSON route and generated route/schema tooling remain future work. Versioning, changelog, and deprecation policy for the current `/api/v1` surface is documented on the public changelog page.

First API Calls

These examples use fake ids and fake keys. They show the normal shape of an app-server integration without requiring Stripe, SendGrid, Plaid, OCR, AI, IRS, or tax filing providers.

Check authentication

GET /api/v1/auth/check
Authorization: Bearer ll_test_replace_me

Create a customer

POST /api/v1/customers
Authorization: Bearer ll_test_replace_me
Content-Type: application/json

{
  "external_customer_id": "cus_demo_123",
  "name": "Acme Holdings",
  "email": "billing@example.com"
}

Create an invoice

POST /api/v1/invoices
Authorization: Bearer ll_test_replace_me
Content-Type: application/json

{
  "external_invoice_id": "inv_demo_123",
  "customer_id": "00000000-0000-4000-8000-000000000001",
  "invoice_number": "INV-1001",
  "issue_date": "2026-05-20",
  "due_date": "2026-06-19",
  "line_items": [
    {
      "description": "Platform subscription",
      "quantity": 1,
      "unit_amount_cents": 25000
    }
  ]
}

Post an invoice

POST /api/v1/invoices/00000000-0000-4000-8000-000000000002/post
Authorization: Bearer ll_test_replace_me

Record a payment

POST /api/v1/payments
Authorization: Bearer ll_test_replace_me
Content-Type: application/json

{
  "external_payment_id": "pay_demo_123",
  "invoice_id": "00000000-0000-4000-8000-000000000002",
  "amount_cents": 25000,
  "received_at": "2026-05-20",
  "source": "manual"
}

Create an estimate

POST /api/v1/estimates
Authorization: Bearer ll_test_replace_me
Content-Type: application/json

{
  "external_estimate_id": "est_demo_123",
  "customer_id": "00000000-0000-4000-8000-000000000001",
  "issue_date": "2026-05-20",
  "line_items": [
    {
      "description": "Implementation package",
      "quantity": 1,
      "unit_amount_cents": 50000
    }
  ]
}

Create a vendor

POST /api/v1/vendors
Authorization: Bearer ll_test_replace_me
Content-Type: application/json

{
  "external_vendor_id": "vendor_demo_123",
  "vendor_type": "contractor",
  "display_name": "Jordan Smith",
  "email": "jordan@example.com",
  "is_1099_eligible": true
}

Create a bill

POST /api/v1/bills
Authorization: Bearer ll_test_replace_me
Content-Type: application/json

{
  "vendor_id": "00000000-0000-4000-8000-000000000003",
  "external_bill_id": "bill_demo_123",
  "bill_number": "BILL-1001",
  "issue_date": "2026-05-20",
  "due_date": "2026-06-19",
  "line_items": [
    {
      "description": "Contractor services",
      "quantity": 1,
      "unit_amount_cents": 75000
    }
  ]
}

Post a bill

POST /api/v1/bills/00000000-0000-4000-8000-000000000004/post
Authorization: Bearer ll_test_replace_me

Read report summaries

GET /api/v1/reports/summary?from=2026-01-01&to=2026-12-31
Authorization: Bearer ll_test_replace_me

SDK Helpers

LedgerLine includes local TypeScript helpers in lib/sdk/index.ts. They are not a published npm package, and they should be called from server-side app code only so LedgerLine API keys stay out of browser bundles.

Current helpers cover auth checks, customers, invoices, invoice posting, payments, provider payout clearing through the current processor-payout compatibility helpers, events, estimates, document shares/renders, Document Center files, settings/defaults, report summaries, vendors, bills, bill posting/reversal, and vendor payment create/list/read/update/void/post/reverse workflows. Helpers throw LedgerlineApiError for failed public API responses.

API Recipes

The public API Recipes page collects server-side workflow patterns for money-in, estimates, money-out, documents, reports, embedded settings, webhooks, error handling, and test/live environments. It uses fake placeholders only and keeps API keys server-side.

Errors and Safe Handling

`/api/v1` routes use the standard public API error envelope. Connected apps should branch on `error.code`, not message text.

{
  "error": {
    "code": "validation_failed",
    "message": "Validation failed.",
    "details": [],
    "request_id": "optional-request-id"
  }
}

Trusted scope-field rejections use `trusted_scope_field_not_allowed`. Error responses must not expose stack traces, raw database errors, API key hashes, service-role credentials, storage paths, or provider secrets.

A future hard module enforcement phase may return `module_disabled` with HTTP 403 when a connected app calls a route for a disabled required module. That error contract is prepared in docs and OpenAPI components, but current public API routes are not broadly wired to block by module state.

Events and Webhooks

Connected apps can send events to `POST /api/v1/events`. Valid `payment.received` events can process into the existing payment flow; accepted non-payment events are stored only. Use idempotency keys for repeated external operations and review the Webhook Event Schema Registry for active versus planned event types.

POST /api/v1/events
Authorization: Bearer ll_test_replace_me
Content-Type: application/json
Idempotency-Key: event-demo-001

{
  "event_type": "payment.received",
  "external_event_id": "evt_demo_001",
  "payload": {
    "external_payment_id": "pay_demo_123",
    "external_invoice_id": "inv_demo_123",
    "amount_cents": 25000,
    "received_at": "2026-05-20"
  }
}

LedgerLine outbound webhooks use signature headers documented in the public webhook registry and dashboard developer docs. Stripe webhook ingestion is optional and limited to supported signed event paths.

Documents and Embedded Settings

Public document share and render routes expose safe metadata for invoice and estimate artifacts. Document Center APIs support private evidence files and record links without exposing storage paths.

Embedded settings APIs expose document branding, invoice defaults, and estimate defaults when the connected app environment has the relevant active capability. Hosted embedded settings UI and public settings components remain future work.

Accounting Boundaries

  • Estimates are non-accounting until converted and posted through invoice workflows.
  • Invoice posting creates Accounts Receivable and revenue.
  • Customer payments reduce Accounts Receivable; payments do not create revenue.
  • Bills do not affect accounting until posted.
  • Bill posting creates expense and Accounts Payable.
  • Vendor payment posting reduces Accounts Payable and credits cash, bank, or clearing.
  • Reversals create reversing journal entries and keep original journals immutable.
  • Documents, PDFs, share links, hosted payment-instructions pages, and email drafts do not mutate accounting.
  • 1099 Summary is CPA/tax-support reporting only, not IRS filing or tax advice.

Current Product Boundaries

  • Stripe is optional; LedgerLine accepts provider-neutral payments and events.
  • Real email sending is not enabled; email draft/copy workflows exist.
  • Hosted payment collection is not built; read-only payment-instructions pages exist through invoice share tokens.
  • Customer portal access is token-scoped, not login/account based.
  • Document Center files are evidence records; OCR, AI parsing, and automatic bill extraction are future work.
  • Vendor bills, A/P, vendor payments, posting, reversals, A/P reports, and 1099 Summary support are built within documented boundaries.