← Back to Integration & Data
INTG-005 Integration & Data 18 min read For: Salesforce Architects & Tech Leaders

API Rate Limits: The Integration Tax Nobody Budgets For

Salesforce API limits are one of the most misunderstood aspects of enterprise Salesforce architecture. They are not a bug to route around — they are a shared infrastructure constraint that every integration must budget for. When they are not budgeted, production failures follow.

VS

Vishal Sharma

Salesforce Architecture Specialist · Updated May 2026

What you will learn...
  • How Salesforce's 24-hour API limit is calculated and what counts against it
  • The difference between REST API limits, Bulk API limits, Streaming API limits, and Apex callout limits
  • How to audit current API consumption and identify which integrations are consuming the most
  • Design patterns that reduce API consumption: composite API, sObject Collections, and event-driven alternatives
  • What happens when limits are exceeded and how to design for graceful degradation
  • The licensing math: how additional API calls are purchased and when it makes sense

How Salesforce API Limits Work

Salesforce's primary API limit is the 24-hour rolling limit on REST and SOAP API calls. The allocation is calculated as: 1,000 API calls per Salesforce license per 24 hours, with a minimum of 15,000 calls for Professional Edition and 1,000,000 calls for Unlimited and Performance Edition orgs. For an Enterprise Edition org with 200 users, the daily allocation is approximately 200,000 API calls. This sounds generous until you model what each integration actually consumes.

The limit resets on a rolling 24-hour basis, not at midnight. This means a spike of API calls at 11pm does not immediately free up limit at midnight — the calls count against the window until 11pm the following day. Integration designs that front-load API consumption (large batch jobs running overnight) may encounter limits during business hours when the window hasn't fully reset.

Critically, not all API types count the same way against limits. REST and SOAP API calls count against the 24-hour limit one call per HTTP request. Bulk API jobs do not count individual records against the REST API limit — they consume from the Bulk API allocation. Streaming API (CometD subscriptions) has its own hourly event delivery limit. Understanding which API each integration uses is the foundation of API budget planning.

⚠️
ISV packages consume your API limit: Every managed package installed in your org that makes API calls — AppExchange data enrichment tools, analytics connectors, email tracking tools — consumes from your shared API allocation. Many organisations discover their API limit is being exhausted by third-party packages that are polling Salesforce every few minutes. Audit all installed packages before investigating custom integrations.

Auditing API Consumption

Salesforce provides API usage data through System Overview (Setup > System Overview) and through the API Usage platform event. The System Overview shows current API requests in the last 24 hours with a gauge. For detailed attribution — which connected app, which user, which integration is consuming how many calls — you need Event Monitoring (a Shield add-on) or the API Usage Notifications feature.

The REST endpoint for checking current API usage is simple and should be polled by every integration monitoring system. The response includes the remaining API calls and the total limit, giving a real-time view of consumption:

// Check current API usage
GET /services/data/v60.0/limits
// Response excerpt:
{
  "DailyApiRequests": {
    "Max": 1000000,
    "Remaining": 847293
  },
  "DailyBulkApiBatches": {
    "Max": 15000,
    "Remaining": 14823
  },
  "DailyStreamingApiEvents": {
    "Max": 50000,
    "Remaining": 49100
  },
  "HourlyPublishedPlatformEvents": {
    "Max": 50000,
    "Remaining": 48750
  }
}

For deep attribution, Event Monitoring's API event logs include the Connected App name, the client IP address, the user ID, and the API endpoint for every API call. Running an aggregation over a day's API event log reveals which connected apps are making the most calls, which users are driving the most programmatic access, and which endpoints are being called most frequently. This is the starting point for any API limit optimisation effort.

High-Consumption Patterns to Eliminate

The most wasteful API consumption pattern is individual REST API calls in a loop. A common anti-pattern is an integration that fetches a list of record IDs (1 API call), then makes individual GET requests for each record to retrieve its fields (N API calls for N records). For 10,000 records, this is 10,001 API calls. The correct pattern uses SOQL queries with all required fields returned in a single API call, reducing 10,000 calls to 1 (or a handful for pagination).

The Composite API and sObject Collections API exist specifically to reduce API call count for multi-record operations. sObject Collections allows up to 200 record creates, updates, or deletes in a single API call. Composite allows up to 25 subrequests in a single HTTP round trip, including queries and DML operations with results from one subrequest referenced by subsequent ones. These are significant API call multipliers when used correctly.

Polling patterns — where an external system repeatedly calls the Salesforce REST API every minute to check if records have changed — are extremely wasteful and unnecessary. Salesforce provides Platform Events, Change Data Capture, and the Streaming API specifically to replace polling. A system subscribing to Account CDC events receives notifications only when Accounts actually change, consuming zero API calls for quiet periods versus hundreds of polling calls that return no new data.

Composite API and Batch Optimisation

The Composite API is one of the most underused API efficiency tools in the Salesforce ecosystem. It allows a single HTTP request to contain up to 25 subrequests, with conditional logic and reference IDs that allow the output of one subrequest to be the input to another. The practical impact: an integration that creates a parent Account, creates a Contact with the new Account ID, and creates an Opportunity linked to both can do all three in a single HTTP request with three subrequests, rather than three sequential API calls.

// Composite API — create Account + Contact + Opportunity in 1 call
POST /services/data/v60.0/composite
{
  "allOrNone": false,
  "compositeRequest": [
    {
      "method": "POST",
      "url": "/services/data/v60.0/sobjects/Account",
      "referenceId": "newAccount",
      "body": { "Name": "Acme Corp", "Industry": "Technology" }
    },
    {
      "method": "POST",
      "url": "/services/data/v60.0/sobjects/Contact",
      "referenceId": "newContact",
      "body": {
        "LastName": "Smith",
        "AccountId": "@{newAccount.id}"
      }
    },
    {
      "method": "POST",
      "url": "/services/data/v60.0/sobjects/Opportunity",
      "referenceId": "newOpp",
      "body": {
        "Name": "Acme - Initial Deal",
        "AccountId": "@{newAccount.id}",
        "CloseDate": "2026-09-30",
        "StageName": "Prospecting",
        "Amount": 50000
      }
    }
  ]
}
// 3 records created, 1 API call consumed

Graceful Degradation When Limits Are Hit

When an API limit is exceeded, Salesforce returns HTTP 403 with error code REQUEST_LIMIT_EXCEEDED. Integrations that are not designed for this response will typically throw an unhandled exception, crash, or enter an error loop that consumes even more calls trying to recover. Well-designed integrations handle the 403 explicitly — logging the event, pausing the integration, alerting the operations team, and queuing failed operations for retry when the limit window resets.

Priority-based API budget allocation is the architectural pattern for production resiliency. Not all integrations are equal — real-time customer-facing processes should consume API budget before background batch synchronisation jobs. Implement this through time-of-day scheduling (batch jobs run overnight when user-facing API consumption is low), API call monitoring with automatic batch job throttling when remaining limits drop below a threshold, and separate connected app credentials per integration so consumption can be attributed and managed individually.

The Connected App OAuth settings allow per-connected-app IP restrictions and can be revoked independently. Creating separate connected apps for each integration system (rather than all integrations sharing one credential) enables granular monitoring, independent credential rotation, and the ability to kill one misbehaving integration without affecting others. This is an operational hygiene requirement in any multi-integration Salesforce org.

💡
Monitor the Remaining value, not the Max: Set alert thresholds on the DailyApiRequests Remaining value, not on the consumed count. Alert at 20% remaining (200,000 calls left on a 1M limit) and again at 5% remaining. This gives operations time to throttle batch jobs before limit exhaustion affects interactive users.

Key Takeaways

  • The daily API limit is 1,000 calls per license with a minimum allocation per edition. For a 200-user Enterprise org, expect ~200,000 daily API calls — this is consumed faster than most teams expect when multiple integrations and packages are present.
  • REST and SOAP API calls count against the 24-hour rolling limit; Bulk API and Streaming API have separate limits. Understanding which API each integration uses is prerequisite to accurate capacity planning.
  • Audit API consumption using Event Monitoring logs to attribute calls to specific connected apps and users. Installed managed packages are frequently the largest unbudgeted API consumers.
  • Eliminate polling patterns — replace them with Platform Events, Change Data Capture, or Streaming API subscriptions that notify on change rather than burning API calls on silent periods.
  • Use the Composite API (25 subrequests per call) and sObject Collections API (200 records per DML call) to reduce API call count by an order of magnitude compared to record-by-record operations.
  • Handle HTTP 403 REQUEST_LIMIT_EXCEEDED explicitly with queuing, alerting, and graceful degradation — never let API limit exhaustion crash an integration silently.

Test Your Understanding

1. An integration synchronises 5,000 records from an external system to Salesforce every hour by making individual REST API PATCH calls for each record. The org has a 500,000/day API limit. How many API calls does this integration consume per day, and what is the most impactful optimisation?

5,000 calls per day — one call per sync cycle. The REST API batches the records automatically.
120,000 calls per day (5,000 records × 24 hours). Switch to Bulk API 2.0 upsert jobs, which do not consume REST API call quota for individual records and can process 5,000 records as a single job.
5,000 calls per hour = 120,000/day, but the fix is to use the Composite API to batch 25 calls per request, reducing to 4,800/day

2. An organisation unexpectedly hits its daily API limit despite having what appeared to be adequate headroom based on their integration inventory. What is the most likely overlooked source of consumption?

Interactive user activity in the Salesforce Lightning UI, which makes background API calls for every page viewed
Installed managed packages from AppExchange that poll Salesforce on recurring schedules — these consume from the same shared API allocation and are frequently not included in integration capacity plans
Platform Events published by internal Flows, which consume from the REST API allocation

3. A Salesforce integration team receives an HTTP 403 with error code REQUEST_LIMIT_EXCEEDED during a peak processing period. The integration retries the failed calls immediately in a loop. What is the likely outcome?

The retries will succeed once Salesforce processes the backlog — retry loops are the correct recovery pattern for 403 errors
The retry loop itself makes additional API calls, consuming the remaining limit faster and blocking other integrations from making any calls — exponential backoff with a maximum retry limit and alerting is the correct pattern
Salesforce will automatically increase the limit temporarily to accommodate the retry burst

Discussion & Feedback