Skip to main content
This guide shows you how to grant an application, script, or vendor programmatic access to your organization’s DualEntry data by issuing it an API key. You need the Admin role. The Developer access tab is disabled for every other role, including Controller, and the underlying endpoints reject non-admins. If you do not have it, send this page to someone who does, along with the list of operations your integration performs.

Decide the roles first

The key carries roles of its own, and it can do exactly what those roles permit. The key is not tied to the person who created it and does not inherit anyone’s permissions. Match the roles to what the integration actually does, before you open the dialog: Two of these are narrower than their names suggest, and both catch people out. Accountant creates journal entries and bank transfers but is read-only on bills and invoices. Controller can edit every record type and creates none. An integration that posts bills needs Accounts Payable, not Accountant, and an integration that creates anything at all needs a role that grants create on that record type. A key can hold several roles, so an integration spanning AP and AR takes both. If no combination fits, adjust the closest role’s permissions, keeping in mind the change applies to everyone who holds it, including users and other API keys. You cannot create a new role for a single integration. Reach for Admin only when nothing narrower works. A key holding Admin bypasses permission checks entirely rather than being granted a permission set, so it is exempt from every restriction above. For the full matrix, see User roles and permissions. Keys start with least-privilege access. The picker is optional and selects nothing by default. A key with no roles can call only the API Health Check endpoint. Every other endpoint refuses it with 403. The key gets nothing more until an admin assigns a role. You must choose Admin access explicitly. Always choose at least one role. Issue one key per integration. Sharing a key between two systems means you cannot revoke one without breaking the other.

Issue the key

A key belongs to the organization you are signed in to when you create it, and nothing else decides where it works. The create dialog has no sandbox or production setting. To issue a key for a sandbox organization, switch to that organization first, then create the key there.
1

Switch to the organization the key is for

Select your organization’s name at the top of the sidebar, then choose the production or sandbox organization the integration should read and write. When you are in a sandbox organization, the top bar shows a Sandbox badge. You need the Admin role in that organization as well, because roles are held per organization.
2

Open the API Keys tab

Go to Settings → Organization → Developer access → API Keys.
3

Open the create dialog

Choose the + button in the header row of the key table.
4

Name it after the integration

Enter an API Key Name such as netsuite-migration or billing-service-prod. The name is the only label you will have when you come back to revoke it, so avoid test. Names must be unique within the organization; reusing one returns Label already exists.
5

Choose the roles you decided on

Open the Roles dropdown and choose the roles. The field takes more than one.
6

Create and copy

Choose Create API Key, then copy the full key from the dialog before closing it. It is displayed once and cannot be retrieved afterward. If you lose it here, revoke the key and issue another.

Hand it over

Send the key through your password manager’s sharing feature or another channel that expires. Do not paste it into Slack, email, or a ticket. A key in a chat history is a key in your organization’s search index, readable by anyone who joins the channel later. Tell the recipient which organization the key is for. A key authenticates only against the organization it was issued from, and production and sandbox organizations are separate organizations on the same host, https://api.dualentry.com. A sandbox key reads only sandbox data, and a production key reads only production data. If they need both, issue one key from each organization and name them so they can’t be confused, for example billing-service-prod and billing-service-sandbox. Don’t rely on the key’s prefix to tell them apart. Every key issued in DualEntry starts with org_production_, including keys issued from a sandbox organization. The prefix names the DualEntry server environment, which is production for every customer organization, sandboxes included. To check which organization a key belongs to, see Key format and statuses. Tell them the roles you assigned, too. A developer who knows the key is scoped to View-Only will recognize a 403 on a write as expected behavior rather than a broken credential, and will come back for the right scope instead of debugging their HTTP client. Once the key is delivered, record which integration holds it somewhere your team will look during an incident. The key table shows the name you chose and nothing about who received it.

Confirm it is working, then keep an eye on it

Ask the recipient to make one call. The Last Used column on the key row fills in once a request authenticates successfully. It shows a date rather than a timestamp, and the underlying value is written asynchronously and only refreshed once a minute, so do not expect it to move the instant a call lands. Review the table periodically and revoke any key whose Last Used date has gone stale, or whose integration has been retired. To revoke, choose the ⋮ menu on the key’s row and choose Revoke API Key. There is no confirmation prompt: the key stops working immediately, and a revoked key cannot be reactivated. If an integration’s needs change, you do not have to reissue. The same ⋮ menu has an Edit action that changes the key’s name and roles in place, leaving the secret intact.

If something goes wrong

Each entry starts with a symptom you might see while issuing or testing a key, followed by what to do about it. The create dialog rejects the name. Label already exists means another key in the organization already uses it, including a revoked one. Revoked keys keep their names, so add a date or a version to distinguish the new one. A key created in a sandbox organization has a production prefix. That is expected. Every key starts with org_production_, and the prefix doesn’t mean the key belongs to production. The key works against the organization whose API Keys table lists it. The key returns production data, or sandbox data, when you expected the other. The key was created while you were signed in to the other organization. Switch to the right organization, issue a new key there, and revoke the one you don’t need. You closed the dialog without copying the secret. It cannot be retrieved. Revoke the key and create another; nothing else in the product will show you that value again. The Developer access tab is grayed out. You do not hold the Admin role. No other role can open it, and there is no read-only view of the key table for Controller or anyone else. Every call the recipient makes is refused. If each one returns 403, check the Roles column on the key’s row. An empty Roles cell means someone created the key without roles. That key authenticates, but every endpoint except the health check refuses it. Use Edit on the row to add them; the secret keeps working. Last Used stays empty after a successful call. The value is written asynchronously and debounced by a minute, and the column shows a date rather than a time. Reload after a minute before concluding the key is unused.

Next steps

Last modified on October 29, 2026