Skip to content
Desktop Accounting API

Authentication and API keys

Every API call authenticates with a project secret key in the Authorization header. Calls that touch QuickBooks also name the end user whose company file they use.

GET /v1/quickbooks-desktop/customers HTTP/1.1
Host: api.desktopaccountingapi.com
Authorization: Bearer sk_test_...
Daapi-End-User-Id: eu_01j9x4m6v4c8k2t7q0r5s3w1zb
Key Looks like How many Use it for
Secret key sk_test_ or sk_live_ followed by 40 letters and digits As many as you need per project, each with a name Every API call, from your server only
Publishable key pk_test_ or pk_live_ followed by 24 letters and digits Exactly one per project The publishableKey field when you create a setup link

test and live follow the project’s environment: test projects issue sk_test_ and pk_test_ keys, production projects issue sk_live_ and pk_live_ keys.

The last six characters of a secret key are a checksum. The SDKs use it to reject a mistyped key before making a network call, and secret scanners use the prefix to find leaked keys in code.

  • Create them in the dashboard under API keys. Give each key a name that says where it runs, such as billing-worker production.
  • The full key is shown once, when you create it. Afterwards the dashboard shows only its last four characters, its creator and when it was last used.
  • A full-access secret key can do everything in its project: create end users, read and write every connected company file, and manage setup links. Treat it like a database password.
  • A read-only secret key can call every GET operation and send passthrough requests that contain only queries (...QueryRq). Every other call returns 403 API_KEY_READ_ONLY before anything is queued or sent to QuickBooks. Choose Read-only when you create the key. Use read-only keys for reporting jobs, AI agents and MCP clients that should never change data.
  • Use it only from your server. The API accepts browser requests from one origin only, the Try it panel of the API reference, and never with cookies or other credentials. Any other site, including your own app’s frontend, cannot call the API from a browser, and that is deliberate. In Try it, prefer a test key (sk_test_); the page keeps it in memory only.

The publishable key identifies a project but grants no access by itself. You send it in POST /v1/auth-sessions together with your secret key, and it must belong to the same project (otherwise 403 PUBLISHABLE_KEY_PROJECT_MISMATCH). You can rotate it in the dashboard; it cannot be deleted.

QuickBooks Desktop operations, everything under /v1/quickbooks-desktop/, need to know which company file to use. Send the end user’s ID in the Daapi-End-User-Id header.

import { DesktopAccountingApi } from "@desktopaccountingapi/quickbooks-desktop";
const client = new DesktopAccountingApi({ apiKey: process.env.DAAPI_SECRET_KEY });
// Per call
await client.qbd.customers.list({ limit: 5 }, { endUserId: "eu_01j9..." });
// Or a client scoped to one end user
const acme = client.forEndUser("eu_01j9...");
await acme.qbd.customers.list({ limit: 5 });

Platform operations (/v1/end-users, /v1/auth-sessions, /v1/requests) ignore the header. Passthrough takes the end user from its path instead: /v1/end-users/{id}/passthrough/quickbooks_desktop.

If the header is missing on a QuickBooks Desktop operation, the API returns 400 END_USER_ID_MISSING. If the ID is unknown, or belongs to another project, it returns 404 RESOURCE_MISSING. The API never reveals whether an end user exists in someone else’s project.

Test project Production project
Keys sk_test_, pk_test_ sk_live_, pk_live_
Price Free Billed per active company file
Meant for Sample company files, QuickBooks trial installations, your own test data Your customers’ real books
Setup link redirect https URLs and http://localhost https URLs only

A new organization gets a test project called Development. When you are ready for real customers, create a production project in the dashboard under Projects, create a sk_live_ key there and deploy it. Your code does not change; the key decides which project, and therefore which end users, a call reaches.

  1. Create a new secret key in the dashboard.
  2. Deploy it to every service that uses the old key.
  3. Check Last used on the old key. When it stops changing, click Revoke.

Revocation takes effect within 30 seconds. Calls with a revoked key return 401 API_KEY_INVALID.

If a key leaks, revoke it first and rotate afterwards. Revoking does not affect your end users’ connections; their Web Connector credentials are separate.

Code HTTP Meaning
API_KEY_MISSING 401 No Authorization: Bearer header
API_KEY_INVALID 401 Unknown, malformed or revoked key. The message shows only the key’s last four characters
PUBLISHABLE_KEY_INVALID 401 Unknown publishable key in an auth session request
PUBLISHABLE_KEY_PROJECT_MISMATCH 403 The publishable key belongs to a different project than the secret key
END_USER_ID_MISSING 400 A QuickBooks Desktop operation without Daapi-End-User-Id

Your end users never see these details: an authentication problem reaches them as a neutral “contact the application provider” message in userFacingMessage.