Appearance
Sandbox
Every organization gets a sandbox: a realm named after the organization (for example ExampleCo Sandbox) that answers the TenkeyBridge API from sample data instead of a real QuickBooks company file. Use it to build and test your integration before you connect QuickBooks, and in CI.
- Same API, same OAuth flow, same JSON as a real realm. Only the realm id differs: it's the id shown on the sandbox in the portal.
- No QuickBooks, Windows machine or Web Connector involved.
- Free: sandboxes aren't billed, don't count toward the trial's one-realm limit, and keep working after a trial ends.
Find your sandbox
Sign in to the portal and open Realms. The sandbox carries a sandbox badge. Copy its realm id from the list. Your organization's sandbox is created when the organization is; if yours is missing, recreate it from Realms or with the Admin API.
Connect to it the same way you would to a real company file: create an OAuth client, run the authorization flow with the sandbox's realm id as realm_id.
Use a separate OAuth client for testing
If your app already runs in production against a real realm, give testing its own OAuth client with your development redirect URI. Approving the sandbox through your production client's redirect would replace that connection.
Sample company
A new sandbox is loaded with ExampleCo Landscaping, a fictional landscaping business: a chart of accounts, 45 customers, vendors, employees, service and non-inventory items, sales tax, classes and terms, and a year of invoices, payments, bills, bill payments, deposits and a transfer, with a mix of open and paid balances. 477 records in all.
Record ids are the same in every sandbox and after every reset, so tests can hard-code them:
| Record | Id |
|---|---|
| Checking (Bank account) | 80000001-1767225600 |
| Savings (Bank account) | 80000002-1767225600 |
| Landscaping Services (Income account) | 8000000C-1767225600 |
| Fuel (Expense account) | 80000010-1767225600 |
| Avery Bishop (Customer) | 8000004F-1767225600 |
| Green Valley Nursery (Vendor) | 8000007C-1767225600 |
| Sam Rivera (Employee) | 80000048-1767225600 |
| Lawn Mowing (Service item) | 8000001E-1767225600 |
| Mulch (Non-inventory item) | 8000002A-1767225600 |
Records you create get new ids from the sandbox's own counter.
What the sandbox covers
The entity matrix has a Sandbox column for every entity. In short:
- Read and write: Customer, Vendor, Account, Class, Term, PaymentMethod, TaxCode, Invoice, SalesReceipt, Payment, Estimate, CreditMemo, RefundReceipt, Bill, BillPayment, VendorCredit, PurchaseOrder, Purchase, JournalEntry, Deposit, Transfer, TimeActivity, Employee, InventoryAdjustment, Item (Service, NonInventory and Inventory). Writes follow the same rules as real QuickBooks Desktop, including the compatibility notes for each entity.
- Read-only: the entities that are read-only everywhere (TaxRate, TaxAgency, CustomerType, CompanyCurrency, ExchangeRate, CompanyInfo, Preferences).
- Employees and SSNs: a sandbox accepts an employee SSN but does not store or return it (QuickBooks Desktop never returns one either). Don't enter real SSNs or other real personal data in a sandbox.
- Inventory: the sandbox does not track quantity on hand, so an InventoryAdjustment is stored and returned (with a value computed from the item's purchase cost) but never changes an item's quantity.
- Change Data Capture and batch work as usual.
- Fixed captures: reports and Budget serve captures of the sample company's reports. Most are real QuickBooks Desktop captures; a few detail and sales reports are generated from the sample data until they can be recaptured. Dates, filters and column splits are accepted but ignored, and the report header says so (
SandboxStaticReport). They don't change when you write to the sandbox. The sample company has no budgets, so Budget queries return an empty list.
Anything the sandbox doesn't emulate returns 400SANDBOX_UNSUPPORTED naming the request. It never fails silently.
Custom fields
Every sandbox has the same five Desktop-style custom fields (data extensions) so you can try CustomField writes: Sales Rep (Customer, Vendor, Invoice, Estimate, SalesReceipt, CreditMemo), Region (Customer, Vendor, Employee), PO Number (Invoice, Estimate, SalesReceipt, CreditMemo, PurchaseOrder), Buyer (PurchaseOrder) and Bin Location (Item). Send CustomField: [{"Name": "Region", "StringValue": "West"}] on a create or update; a field that is not defined, or not assigned to that record type, is a 400 CUSTOM_FIELD_UNKNOWN. Bills take no custom fields, exactly as in QuickBooks Desktop (see Custom fields). You cannot define new fields in the sandbox.
Reset
Resetting deletes everything in the sandbox and reloads a template:
sample: the ExampleCo company above.empty: a blank company with only the records a new QuickBooks company file starts with (a few accounts, sales tax codes, company info and preferences).
In the portal, open the sandbox and choose Reset sandbox. From code or CI, call the Admin API with an API key:
bash
curl -X POST "https://api.tenkeybridge.com/admin/v1/realms/$REALM_ID/sandbox/reset" \
-H "x-api-key: $TKB_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "template": "sample" }'json
{ "template": "sample", "records": 477, "nextSeq": 865 }records is the number of records loaded; nextSeq is where new record ids continue from. A reset counts as 50 calls toward the daily limit. Only sandbox realms can be reset: a real realm returns 409.
Limits
| Limit | Default | When exceeded |
|---|---|---|
| REST calls per day (UTC) | 2,000 | 429 SANDBOX_DAILY_LIMIT, with Retry-After |
| Records | 10,000 | 400 SANDBOX_RECORD_LIMIT on the create that would pass it |
| Requests per minute | same as any realm | 429 |
In CI, reset once per run rather than per test, and page with MAXRESULTS instead of polling.
A sandbox can't have a Windows agent token or a Web Connector connection (409). To test against real QuickBooks, create a regular realm; see Testing your integration.
Differences from real QuickBooks
The sandbox emulates QuickBooks Desktop's behaviour, and each release is checked against a real QuickBooks company file running the same requests. Every difference that check finds is either fixed or listed here with its reason.
A1: automatic document numbers
A transaction created without a DocNumber gets the next number from QuickBooks' own per-type counter, which depends on the company file's history. The sandbox numbers from its own counter, so the value differs; that one is numbered does not.
A2: group item lines
Group-item lines (GroupLineDetail) are not emulated: the sandbox answers 400 SANDBOX_UNSUPPORTED where QuickBooks expands the group.
The sandbox also doesn't reproduce Desktop's desktop-side behaviour (dialogs, single-user mode, a company file that isn't open), multi-currency, inventory assemblies or payroll. Test those against a real company file.

