Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
All errors
Integration

API_DISABLED_FOR_ORG: API is not enabled for this Organization or Partner

The org's edition or the user's profile doesn't include API access. Most often this is a Professional Edition org without the API add-on, or a profile (typically Standard User) where "API Enabled" was unchecked.

Also seen asAPI_DISABLED_FOR_ORG·API is not enabled for this Organization·API_DISABLED_FOR_ORG: API is not enabled

Your data warehouse pulls Opportunity records from a Salesforce sandbox every fifteen minutes. The pipeline has been green for months. This morning every call returns API_DISABLED_FOR_ORG: API is not enabled for this Organization or Partner. Nothing changed on your side. The pipeline is dead until you understand what shifted on the Salesforce side.

What the platform is actually saying

The error tells you the org or the user account does not have API access. The API call reached Salesforce, the credentials authenticated, and then the permission check rejected the request before it touched any object data. The fault is at the access-control layer, not the data layer.

Two distinct settings can trigger this. The org as a whole may lack API access (this happens on Developer Edition orgs without the API feature enabled, on Essentials Edition, and on Trial orgs that aged out). The user account may lack API access (this happens when the profile or permission set doesn't include "API Enabled").

The error message doesn't distinguish between the two. You have to check both.

The broken example

A Node integration that worked yesterday:

const jsforce = require('jsforce');

const conn = new jsforce.Connection({
  loginUrl: 'https://acme.my.salesforce.com',
});

await conn.login(process.env.SF_USER, process.env.SF_PASSWORD + process.env.SF_TOKEN);

const result = await conn.query(
  'SELECT Id, Name, StageName, Amount FROM Opportunity WHERE LastModifiedDate = TODAY'
);

The login succeeds; the query throws API_DISABLED_FOR_ORG. The connection object is fine. The credentials are valid. The query syntax is valid. The user simply isn't permitted to use the API.

Three paths to a fix

The user's profile is missing the "API Enabled" permission. This is the most common cause. Even an admin user can lose API access if their profile is edited or they're cloned from a profile that didn't have it. Go to Setup, then Users, then click the integration user, then Edit Profile (or check their assigned permission sets). Confirm "API Enabled" is checked. If you cloned the profile from "Standard User" you may inherit a profile that has API access turned off. Assign a permission set called "Salesforce API Integration" (Salesforce ships one) or build a custom permission set with only "API Enabled" set true and assign it to integration users.

The org doesn't include API access in its edition. Essentials Edition does not include API access by default; Developer Edition does, but only in limited amounts; Professional Edition requires an add-on; Enterprise, Unlimited, and Performance include it as standard. If your org is Essentials, you can purchase the API add-on or upgrade the edition. Check Setup, then Company Information, and look at the "Organization Edition" field.

The user is locked out or the license is wrong. Some user licenses (Chatter Free, Identity Only) don't include API access regardless of the profile setting. Confirm the user has a Salesforce user license (full license) or a Salesforce Integration license (introduced specifically for integration users). The Salesforce Integration license is the cheapest way to license a dedicated integration user.

The fixed example

The fix isn't in the code; it's in the org configuration. Once "API Enabled" is true on the user's profile and the user has an appropriate license, the original code works without changes:

const jsforce = require('jsforce');

const conn = new jsforce.Connection({
  loginUrl: 'https://acme.my.salesforce.com',
});

await conn.login(process.env.SF_USER, process.env.SF_PASSWORD + process.env.SF_TOKEN);

const result = await conn.query(
  'SELECT Id, Name, StageName, Amount FROM Opportunity WHERE LastModifiedDate = TODAY'
);
console.log(`Fetched ${result.totalSize} opportunities.`);

Sometimes you also need to bump the API version in your client to ensure compatibility with the org's current API surface. For jsforce, set conn.version = '60.0' or pass version in the constructor.

When the permission was always missing but worked before

A confusing variant: the integration worked for months, then suddenly broke. The user didn't lose access; the profile didn't change. What can shift?

Profile clone. If your admin recently cloned the integration user's profile to create a similar profile for a new use case, the original profile may have been renamed or modified in ways that affect inheritance. Check the user's currently assigned profile.

Permission set removal. If "API Enabled" was granted via a permission set (not the base profile) and the permission set was deactivated or unassigned, the user loses API access. Check Setup, then Permission Sets, and verify the user still has every permission set that grants API access.

License change. If the integration user's license was downgraded (an admin tried to save costs by moving the user to a Chatter Free license, for example), API access goes with it.

Org type change. Rare, but a Salesforce account renegotiation can shift edition. If your AE moved you from Enterprise to a different edition, API access may have changed.

Diagnosing in production

When the alert fires, four checks resolve 95% of cases.

Confirm the user can log in via the UI. Open a browser, log in as the integration user, and confirm the login succeeds. If login fails with a different error, that's a separate problem.

Confirm "API Enabled" is true on the user's profile. Setup, Profiles, click the profile, scroll to "System Permissions" and find "API Enabled". The checkbox should be ticked.

Confirm the user has no permission set issues. Setup, Users, click the user, scroll to "Permission Set Assignments". Make sure none have been deactivated or revoked.

Confirm the org has API access in general. Setup, Company Information, look at the edition. Confirm it's Enterprise, Unlimited, Performance, or Developer with the API feature. If it's Essentials or Professional without an add-on, the integration needs an API add-on.

The Salesforce Integration License pattern

For new integrations, the Salesforce Integration license is the recommended user type. It's priced for headless integrations, supports API access, and lacks UI features your bot doesn't need. The license has constraints: the user can't log in to the UI in any meaningful way, can only access objects through the API, and has a restricted profile shape.

To use it:

  1. Purchase the license (your Salesforce account team handles this).
  2. Create a new user assigned to the new license type.
  3. Assign the "Salesforce API Integration" permission set (or your custom equivalent) to the user.
  4. Use this user's credentials in the integration.

The integration license doesn't count against your sales-cloud or service-cloud user count, which makes it the cheap option for high-volume integrations that don't need a human user behind them.

Recovering from a profile mistake

If an admin accidentally removed API access from your integration user's profile and you can't get the change reverted quickly, the temporary recovery path is a permission set.

Create a permission set called "Emergency API Access". Edit it, go to "System Permissions", check "API Enabled", save. Assign it to the affected user. The user has API access immediately. You can resolve the profile question on a longer timeline.

This pattern is useful in general: permission sets layer access on top of profiles. Granting API access through a permission set instead of editing the profile keeps the base profile clean and lets you grant the permission to specific users without affecting everyone on the profile.

When the integration uses OAuth Connected Apps

Modern integrations use OAuth through a Connected App rather than the username and password login. The Connected App has its own access controls.

If the Connected App's "Permitted Users" setting is "Admin approved users are pre-authorized", you must explicitly grant access to the integration user via a profile or permission set assignment on the Connected App configuration page. An unauthorized user gets API_DISABLED_FOR_ORG even though their profile has "API Enabled" set true, because the app itself denies them.

Setup, App Manager, find your Connected App, click View, check "Permitted Users" and "Profiles" / "Permission Sets". Make sure the integration user's profile or assigned permission set is listed.

When the API version is wrong

A subtle case: the API endpoint URL embeds a version. An old version that's been retired by Salesforce returns errors that can look like access errors.

GET /services/data/v25.0/sobjects/Opportunity HTTP/1.1

Versions older than the lowest supported version (currently v21.0, scheduled to deprecate) can return UNSUPPORTED_API_VERSION or API_DISABLED_FOR_ORG depending on which check runs first. The fix is to bump the version to a current one (v60.0 or later as of recent releases).

Test patterns for integration auth

Two tests catch most regressions.

A smoke test that authenticates and runs a trivial query against an object every integration touches. Run on every deploy. If the smoke test fails with API_DISABLED_FOR_ORG, the deploy stops and an alert pages the on-call.

A user-permission audit that compares the integration user's currently-effective permissions to a snapshot taken at the last known-good state. Any drift is investigated before it causes an incident. The Salesforce Permission Set Group introspection API makes this kind of audit feasible.

Related errors to recognize

API_DISABLED_FOR_ORG lives in a small family:

  • INVALID_LOGIN: API security token required, please add it to the end of your password (login succeeded but with no token where one was required)
  • INSUFFICIENT_ACCESS_OR_READONLY: You do not have permission to access this record (auth works, object-level or record-level access is missing)
  • INVALID_SESSION_ID: Session expired or invalid (token aged out; refresh and retry)
  • REQUEST_LIMIT_EXCEEDED: TotalRequests Limit exceeded (org hit its 24-hour API quota)
  • UNABLE_TO_LOCK_ROW: unable to obtain exclusive access to this record (data contention, not access)

Knowing which is which lets you triage in seconds rather than minutes.

The 24-hour API request limit, as a neighbor

API_DISABLED_FOR_ORG is access-level. REQUEST_LIMIT_EXCEEDED is quota-level. The two get confused because the latter also blocks API calls.

Every org has a 24-hour rolling API request budget tied to edition and user count. Enterprise Edition orgs get a base of 15,000 requests plus 1,000 per Salesforce user license, with various adders. If you blow the budget, every API call returns REQUEST_LIMIT_EXCEEDED until the rolling window reduces.

You can monitor usage with the API Limits page (Setup, then API Usage Last 7 Days) or the Limits REST resource (GET /services/data/v60.0/limits/). If the failure is "API works for some calls, then breaks", you're at the quota wall, not the access wall.

A team workflow for managing integration permissions

For shops with multiple integrations, manage permissions explicitly:

  1. One permission set per integration ("Stripe Integration Access", "Snowflake Reader Access").
  2. Each permission set grants API Enabled plus the minimum object access the integration needs.
  3. Integration users are members of exactly the sets they need.
  4. Document every integration user, every assigned permission set, and the owning team in a shared runbook.

When something breaks, the runbook tells you which permission set to check first.

Further reading from Salesforce

Related dictionary terms

Share this fix

Share on LinkedInShare on X

Related Integration errors