Salesforce doesn't issue a single "API key" - instead you create a Connected App in Setup, enable OAuth settings, and get a Consumer Key (client ID) and Consumer Secret (client secret). You exchange those for an OAuth 2.0 access token - using the Client Credentials flow for server-to-server integrations, or the Web Server (Authorization Code) flow for per-user access - and send that token as Authorization: Bearer <token> on REST API calls.
The rest of this page covers the setup steps, where the credential goes, a working code sample, and the errors you'll hit if something's misconfigured.
Prerequisites
- A Salesforce org where you can create Connected Apps — this requires the "Customize Application" and "Manage Connected Apps" permissions, typically held by System Administrators.
- A My Domain configured for your org. Salesforce requires My Domain to be enabled before OAuth flows work (Salesforce Help, Enable OAuth Settings for API Integration).
- A decision on which OAuth flow fits: Client Credentials for a server-to-server integration with no end user, or Web Server (Authorization Code) if the integration needs to act as a specific Salesforce user.
Step-by-step: creating a Salesforce Connected App and getting your Consumer Key
- In Setup, enter "App Manager" in the Quick Find box, then click New Connected App.
- Fill in the Connected App Name, API Name (auto-filled), and a contact Email.
- Under API (Enable OAuth Settings), check Enable OAuth Settings. Enter a Callback URL - Salesforce requires one even for server-to-server flows; a placeholder URL works if you won't use a redirect-based flow.
- Add OAuth Scopes. At minimum, add "Manage user data via APIs (
api)". If your integration needs long-lived access without re-prompting a user, also add "Perform requests at any time (refresh_token,offline_access)" (Salesforce Help, Enable OAuth Settings for API Integration). - For server-to-server integrations, also enable Client Credentials Flow under the connected app's policies and assign a "Run As" user — this user's permissions determine what the integration can access (Salesforce Help, Configure a Connected App for the OAuth 2.0 Client Credentials Flow).
- Click Save. Salesforce can take up to 10 minutes to propagate a new Connected App - if your first token request fails, wait and retry.
- Open the app and click Manage Consumer Details. Salesforce emails a verification code to confirm your identity; enter it, then copy the Consumer Key and Consumer Secret.
Where the credential goes
The Consumer Key and Consumer Secret aren't sent directly on API calls - they're exchanged for an OAuth access token at your org's token endpoint:
POST https://login.salesforce.com/services/oauth2/tokenFor the Client Credentials flow, send grant_type=client_credentials with your client_id (Consumer Key) and client_secret (Consumer Secret). The response includes an access_token and an instance_url. Use the token on subsequent calls:
Authorization: Bearer <access_token>against <instance_url>/services/data/v66.0/... (Salesforce Developers, Authorization Through Connected Apps and OAuth 2.0).
Connector-specific gotcha: the instance_url returned in the token response is specific to your org (e.g., https://yourcompany.my.salesforce.com) and can change — for example, after a sandbox refresh or org migration. Always use the instance_url from the most recent token response for your API calls rather than hardcoding a domain; a cached or assumed domain is a common source of IP_RESTRICTED or connection errors after a sandbox refresh.
A few other things to know:
- Lifetime: access tokens are session-based and expire according to your org's session timeout policy (2 hours by default, but configurable in Setup). Client Credentials flow tokens are not paired with a refresh token — request a new one when the current one expires or returns
INVALID_SESSION_ID. - Refresh: if you used the Web Server (Authorization Code) flow with the
refresh_tokenandoffline_accessscopes, exchange the refresh token at the same/services/oauth2/tokenendpoint withgrant_type=refresh_tokento get a new access token without re-prompting the user. - Scopes:
apicovers REST, SOAP, Bulk, and Metadata API access for the Run As user's permission set — grant the Run As user only the object and field permissions the integration needs, since the scope itself doesn't restrict data access beyond that user's profile. - Revocation: revoke a Connected App's access from Setup → Apps → Connected Apps OAuth Usage, or from the integration user's own Connected Apps list under personal settings.
If you need per-user access instead (Authorization Code flow)
If your integration needs to act on behalf of different Salesforce users (not a single Run As user), use the Web Server (Authorization Code) flow: direct the user to https://login.salesforce.com/services/oauth2/authorize?response_type=code&client_id=...&redirect_uri=..., then exchange the returned code at /services/oauth2/token with grant_type=authorization_code for an access token and refresh token (Salesforce Developers, Authorization Through Connected Apps and OAuth 2.0).
Minimal working example
This uses the Client Credentials flow to get a token, then calls the REST API's limits endpoint — a good smoke test that doesn't depend on any specific object data.
curl:
# 1. Get an access token
curl -X POST https://login.salesforce.com/services/oauth2/token \
-d "grant_type=client_credentials" \
-d "client_id=$SF_CONSUMER_KEY" \
-d "client_secret=$SF_CONSUMER_SECRET"
# Response includes "access_token" and "instance_url" — use both below
# 2. Call the REST API
curl "$SF_INSTANCE_URL/services/data/v66.0/limits" \
-H "Authorization: Bearer $SF_ACCESS_TOKEN"Node.js:
const tokenRes = await fetch("https://login.salesforce.com/services/oauth2/token", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
grant_type: "client_credentials",
client_id: process.env.SF_CONSUMER_KEY,
client_secret: process.env.SF_CONSUMER_SECRET,
}),
});
const { access_token, instance_url } = await tokenRes.json();
const res = await fetch(`${instance_url}/services/data/v66.0/limits`, {
headers: { Authorization: `Bearer ${access_token}` },
});
console.log(await res.json());Store SF_CONSUMER_KEY and SF_CONSUMER_SECRET as environment variables, and treat the resulting access token as a short-lived secret too.
Common errors and fixes
Why am I getting invalid_client_id or invalid_client?
Either the Consumer Key/Secret is wrong, or the Connected App hasn't finished propagating yet - Salesforce can take up to 10 minutes after creation or after enabling Client Credentials Flow. Double-check you copied the Consumer Key and Secret from Manage Consumer Details, and retry after a few minutes (Salesforce Help, Configure a Connected App for the OAuth 2.0 Client Credentials Flow).
Why am I getting a 401 with INVALID_SESSION_ID?
Your access token expired or was revoked - session-based tokens expire per your org's session timeout policy (2 hours by default). Request a new access token via the same OAuth flow; if you're using the Authorization Code flow with offline_access, use the refresh token instead of restarting the full flow (Salesforce Developers, Authorization Through Connected Apps and OAuth 2.0).
Why am I getting a 403 with REQUEST_LIMIT_EXCEEDED?
Your org has exceeded its Daily API Request Limit (100,000 requests per rolling 24 hours for Enterprise Edition, plus 1,000 per additional user license, scaling with org size). This is a soft limit that allows temporary bursts, but a hard cap blocks further calls until usage drops back under the limit. Check current usage via the Sforce-Limit-Info response header or the /services/data/vXX.0/limits endpoint (Salesforce Developers Blog, API Limits and Monitoring Your API Usage).
The faster way
Setting up a Connected App, choosing the right OAuth flow, and tracking the instance_url and daily limits works fine for one Salesforce org. It gets harder once you're connecting Salesforce alongside other CRMs — each with different auth flows, object models, and rate-limit shapes. Knit's unified CRM API handles Salesforce's OAuth and instance_url routing, normalizes object data across connectors, and manages rate-limit backoff for you. See the Salesforce API overview for what's available, or book a demo to see it against your own org. You can also sign up free and connect a sandbox Salesforce org in a few minutes.
FAQ
Where do I find my Salesforce Consumer Key and Consumer Secret?
After creating a Connected App in Setup → App Manager, open it and click "Manage Consumer Details." Salesforce sends a verification code to your registered email to confirm your identity before showing the Consumer Key (client ID) and Consumer Secret (client secret). You can return to this page later to view them again.
Does Salesforce have a simple API key like some other platforms?
No — Salesforce doesn't issue a static "API key" you paste into a header. Access is always through OAuth 2.0: a Connected App's Consumer Key and Secret are exchanged for a short-lived access token, which is what you actually send with API requests. This adds setup steps but means credentials can be rotated and scoped without changing a hardcoded key.
What's the difference between the Client Credentials flow and the Authorization Code flow?
The Client Credentials flow is server-to-server: your app exchanges its Consumer Key and Secret directly for a token tied to a configured "Run As" user, with no end-user login. The Authorization Code (Web Server) flow involves a Salesforce user logging in and granting consent, after which your app gets an access token and refresh token tied to that specific user. Use Client Credentials for backend integrations and Authorization Code when the integration needs to act as different individual users.
How long does a Salesforce access token last?
It depends on your org's session timeout setting in Setup, which defaults to 2 hours but can be configured higher or lower. There's no fixed "token expiry" separate from session timeout. If you're using the Authorization Code flow with the refresh_token and offline_access scopes, your app can silently get a new access token via the refresh token instead of expiring the user's session.
What are Salesforce's API rate limits?
Most paid editions (e.g., Enterprise Edition) get a Daily API Request Limit starting at 100,000 calls per rolling 24-hour period, increasing with the number of user licenses your org has. It's a soft limit - short bursts above it are allowed - but a hard system-protection limit eventually returns 403 REQUEST_LIMIT_EXCEEDED until usage drops back down. Knit manages this backoff automatically across the Salesforce connections it handles.

