Skip to content

Testing with the Demo Company

LuciBook has no separate sandbox environment. Instead, every user can open a demo company — a pre-seeded, fictional organisation — inside the same production system your app already talks to. Connect your app to a partner's demo company to test the full OAuth, read, write and webhook flow before they connect it to their real books.

How to get a demo company

A demo company is a normal LuciBook organisation flagged as a demo company, created on demand from the product UI — there is no signup option or admin action that provisions one for you as a developer. To get one for testing:

  1. Sign in to LuciBook with any account.
  2. Trigger "Open demo company" from the app (this posts to the demo-open endpoint, which gets or creates the org for the signed-in user).
  3. You land on a short holding page while the company is seeded with sample data, then on its dashboard.

Each user gets at most one demo company at a time — it's provisioned per user, not per app or per partner account, and re-opening it always returns the same org until it's reset or deleted. Connect your app to it from that org exactly as you would to any real organisation, via the normal OAuth consent screen.

What works and what doesn't

Area Behaviour in a demo company
OAuth consent Works normally. A demo company can appear in the org picker and grant a connection like any other org — there is no demo-specific consent restriction.
Third-party app policy Same as any org: a demo company allows third-party and unverified apps by default, and an owner can still turn those off in org settings.
Reading data Works normally — bills, invoices, contacts, and every other read endpoint behave exactly as they would for a real org.
Writing data Works normally for what the partner API exposes: creating bills, invoices and credit notes is not blocked or special-cased for a demo company. Note this reflects the API's own limits, not a demo restriction — these are create-only endpoints (each document lands as a DRAFT, with no update endpoint), and there is no contacts-write endpoint at all, whether the org is a demo company or not.
Webhooks Fire normally. Subscribed events (including invoice, bill and credit note events) are delivered to your app for a demo company the same way they are for a real one.
Outbound email Suppressed. Actions that would send an email on the company's behalf — invoice/bill/credit-note/quote/statement emails and PDF-by-email — are silently skipped. Nothing is sent to a real inbox.
Rate limits and quotas Same limits and quotas as any other organisation — there is no separate demo tier.
Real filings and payments Blocked or silently skipped. VAT, Corporation Tax, Self Assessment, and MTD Income Tax (ITSA) submissions, plus Companies House filings, bank-feed connections, payment-provider connections/checkout, billing checkout, and inviting teammates are all refused with a clear "not available in the demo company" response, or — for scheduled ITSA and VAT submission jobs specifically — silently skipped instead of surfacing an error. Either way, nothing reaches a real bank, a real filing authority, or a real payment.

In short: everything you'd use to validate your integration — consent, reads, writes, webhooks — works exactly as it would against a real organisation. The only things suppressed are outbound email and the handful of actions that would otherwise send something to a real external system (a filing, a payment, a bank connection, an email, an invite).

Reset and purge: what it means for your connection

A demo company is disposable, and the owner (the user who opened it) can reset or delete it at any time from the product UI.

  • Reset is not a data wipe of the same organisation — it's destroy and replace. The existing demo company is permanently deleted and a brand new one, with a new organisation id, is provisioned in its place. Nothing about the old organisation survives.
  • Your connection does not carry over. A connection is tied to the specific organisation id it was created for. Once that organisation is deleted, your connection to it is gone — calls that used to succeed will start failing because the organisation no longer exists.
  • You will need to reconnect. To keep testing, the partner needs to go through OAuth consent again for the new organisation id and your app needs to treat it as a brand-new connection, not a refresh of the old one.
  • The signal is a 403, not a 404. Once the old organisation is gone, every call your app makes against its id fails with 403 org_not_connected — the same error you'd get from a token that was never connected to that org in the first place, not a 404. Treat that error code as "this connection is gone, prompt the user to reconnect."
  • You should get a connection.revoked webhook too, but treat it as best-effort, not authoritative. Resetting or deleting a demo company revokes every affected connection the normal way — revoked_at is stamped and connection.revoked fires for each one, the same as a manual DELETE /api/v1/connections/{connection_id}. Because the organisation itself is destroyed in the same operation, delivery isn't guaranteed: the fan-out can still be in flight when the organisation (and the rows behind its webhook delivery) disappear. Build your reconnection logic on the 403 org_not_connected responses described above, and treat any connection.revoked you do receive as an earlier, non-guaranteed heads-up rather than the thing you wait for.
  • Delete is the same underlying operation without re-provisioning: the organisation is gone and the user is returned to the org picker.

Automatic purging

LuciBook also purges demo companies automatically, on a nightly sweep, for two reasons:

  • Inactivity. A demo company with no recorded activity for 90 days is hard-deleted, the same way a manual reset deletes it.
  • Cleanup after a failed reset/delete. If a reset or delete didn't finish cleanly, the leftover organisation is swept regardless of age.

Either way, the effect on your connection is identical to a manual reset: the organisation disappears and your connection to it starts returning 403 org_not_connected. The same best-effort connection.revoked webhook described above may also arrive, but the 403 is the signal to build on — it doesn't depend on that webhook's delivery succeeding.

Using the demo company through your app's API calls counts as activity. Every authenticated request your app makes to an organisation-scoped endpoint for the company — reads and writes alike, over any connection you hold to it — resets the inactivity clock. OAuth token requests and refreshes on their own don't count, and neither do requests refused before they reach the organisation (403 org_not_connected, org_policy, insufficient_role).

On the LuciBook UI side, only actions recorded in the company's activity log count, such as approving (authorising) an invoice or sending one by email. Signing in, browsing, and creating drafts (including contacts or draft invoices) don't.

A demo company that has seen neither kind of activity for 90 days is purged. The API-usage stamp is written asynchronously and is best-effort, so don't rely on a single call on day 89 — but an app that is actively integrating against the company keeps it alive without any manual UI workaround.

  1. Connect. Have your test user open their demo company and go through your app's OAuth flow against it, exactly as a real partner would.
  2. Read. Pull a sample of contacts, invoices, bills and credit notes to confirm your read paths and pagination work against real (if fictional) data shapes.
  3. Write. Push a bill, invoice or credit note through your app (these are create-only endpoints — each lands as a DRAFT, and there is no update endpoint or a contacts-write endpoint) and confirm it appears correctly in the demo company's dashboard.
  4. Webhooks. Subscribe to the events you care about and confirm deliveries arrive for the reads/writes above — this is a faithful test, since webhooks are not suppressed for demo companies.
  5. Before you consider your integration finished, also handle the disconnection case: what your app does when a previously-working organisation id starts returning 403 org_not_connected, since that's exactly what a demo-company reset or purge looks like from your side.

What partners can never do

Partners testing against a demo company can never reset or delete a real organisation — reset and delete only operate on organisations flagged as demo companies, and the underlying operation refuses outright if you point it at anything else. All data in a demo company is fictional sample data, seeded for testing; it does not represent a real business, and nothing you do there reaches a real bank, a real tax authority, or a real customer.