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.1Host: api.desktopaccountingapi.comAuthorization: Bearer sk_test_...Daapi-End-User-Id: eu_01j9x4m6v4c8k2t7q0r5s3w1zbKey types
Section titled “Key types”| 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.
Secret keys
Section titled “Secret keys”- 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
GEToperation and send passthrough requests that contain only queries (...QueryRq). Every other call returns403 API_KEY_READ_ONLYbefore 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
Section titled “The publishable key”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.
Selecting the end user
Section titled “Selecting the end user”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 callawait client.qbd.customers.list({ limit: 5 }, { endUserId: "eu_01j9..." });
// Or a client scoped to one end userconst acme = client.forEndUser("eu_01j9...");await acme.qbd.customers.list({ limit: 5 });import osfrom desktopaccountingapi import DesktopAccountingApi
client = DesktopAccountingApi(api_key=os.environ["DAAPI_SECRET_KEY"])
# Per callclient.qbd.customers.list(limit=5, end_user_id="eu_01j9...")
# Or a client scoped to one end useracme = client.for_end_user("eu_01j9...")acme.qbd.customers.list(limit=5)var client = new DesktopAccountingApiClient(new ClientOptions { ApiKey = Environment.GetEnvironmentVariable("DAAPI_SECRET_KEY") });
// Per callawait foreach (var c in client.Qbd.Customers.ListAsync(new CustomerListParams { Limit = 5 }, new RequestOptions { EndUserId = "eu_01j9..." })) { }
// Or a client scoped to one end uservar acme = client.ForEndUser("eu_01j9...");DesktopAccountingApiClient client = new DesktopAccountingApiClient( ClientOptions.builder().apiKey(System.getenv("DAAPI_SECRET_KEY")).build());
// A client scoped to one end userDesktopAccountingApiClient acme = client.forEndUser("eu_01j9...");acme.qbd().customers().list(new CustomerListParams().limit(5));curl "https://api.desktopaccountingapi.com/v1/quickbooks-desktop/customers?limit=5" \ -H "Authorization: Bearer $DAAPI_SECRET_KEY" \ -H "Daapi-End-User-Id: eu_01j9..."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 and production projects
Section titled “Test and production projects”| 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.
Rotating a key
Section titled “Rotating a key”- Create a new secret key in the dashboard.
- Deploy it to every service that uses the old key.
- 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.
Authentication errors
Section titled “Authentication errors”| 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.