Flow HTTP Callout: calling a REST API from Salesforce without Apex or middleware
There's a whole class of integration — check a credit score, validate an address, pull a shipping quote — that used to mean an Apex callout class or a MuleSoft flow. HTTP Callout in Flow does it declaratively: you paste a sample response, Salesforce generates the types, and an admin ships the integration. Here's how it actually works, the transaction rule that trips everyone up, and the exact line where you still reach for Apex.
There’s a specific integration that shows up in almost every org and almost always gets over-engineered: a single, synchronous call to an external REST endpoint. Validate an address before save. Pull a live currency rate. Ask a scoring service whether this lead is worth a rep’s time. None of these need a message queue, a middleware tenant, or a developer sprint — they need one HTTP request and its response. And for years the only supported way to make that request was an Apex callout class, which meant the “small” integration became a code change, a test class, and a deployment.
HTTP Callout in Flow removes that tax. You describe the endpoint, paste a sample of what it returns, and Salesforce generates the request and response types for you — no Apex, no external iPaaS. An admin can build and ship a REST integration in an afternoon. That’s genuinely new leverage, and it’s also a fast way to build something fragile if you don’t understand what’s happening underneath. This post is the underneath: how the feature assembles a callout, the authentication model it stands on, the transaction rule that breaks half of first attempts, and the honest boundary where Apex or MuleSoft is still the right tool.
What HTTP Callout actually is
HTTP Callout is a Flow action that connects to an external service without a connector and without code. It started GET-only when it went generally available in 2023, and by the Winter ‘24 release it covered the full set of verbs you’d expect — GET, POST, PUT, PATCH, and DELETE — which is the point at which it stopped being a read-only novelty and became a real integration primitive.
The mechanism is worth understanding because it explains both the power and the limits. When you configure a callout, you paste a sample JSON response. Flow parses it and, behind the scenes, generates an External Service registration and the Apex classes that model the request and response structures. The result is an invocable action that becomes reusable across Flow Builder and the rest of your org. In other words, the feature doesn’t avoid the External Services / Apex machinery — it writes it for you from an example. You’re still getting typed request and response objects; you just never opened a .cls file to get them.
That framing matters for how you reason about it. This is the same decision philosophy we lay out in when to use Flow, Apex, or an agent action: the declarative surface is a generator sitting on top of the imperative one. Knowing that tells you exactly when the generated version will be enough and when you’ve outgrown it.
The build sequence, step by step
The order matters, because getting the authentication objects wrong produces the most common first-callout failure.
1. Create an External Credential. In Setup, the External Credential defines how you authenticate — the protocol (OAuth 2.0, API key passed as a custom header, JWT, and so on) and the principal Salesforce uses when it authenticates. This is the object that actually holds the trust relationship.
2. Create a Named Credential that points at it. The Named Credential defines where — the callout endpoint URL and the HTTP options — and references the External Credential for the how. Splitting the two is deliberate: one endpoint definition can be reused across many callouts, and the secret material lives in the credential store, never in your flow. This is the same discipline we flag in the security health check: endpoints and secrets belong in Named and External Credentials, not hardcoded anywhere a human or an LLM can read them back.
3. Grant the principal access. A permission set (or profile) has to be granted access to the External Credential’s principal, or the callout authenticates as nobody and fails. This is easy to forget in a sandbox where you’re a System Administrator and everything seems to work — then it breaks for the running user in production.
4. Add the HTTP Callout action in Flow. In an action element, choose Create HTTP Callout. Name the external service, select the Named Credential, pick the method, and set the URL path — which must start with a slash and is appended to the Named Credential’s base URL.
5. Describe the request and response with samples. For POST, PUT, and PATCH you provide a sample request body; Flow generates a request structure you populate with flow variables. For every method you paste a sample response, click Review, and Flow infers the data types and builds the response structure. The generated Apex types follow a predictable naming convention (ExternalServiceName__CalloutLabel_IN_body for the inbound body, and matching names for the response), which is how you’ll recognize them later in the debug logs.
6. Use the response downstream. The parsed response lands in flow variables you can reference in any subsequent element — a Decision that branches on a returned status, an Assignment that maps a returned field onto a record, a screen that shows the caller the result.
The whole thing is declarative, but notice what you actually did: you defined an auth model, a typed contract, and a data mapping. Those are the same things a good Apex integration defines. The feature didn’t make the integration trivial; it made the typing and plumbing trivial and left the design to you.
The transaction rule that breaks the first attempt
Here is the single gotcha that trips up almost everyone, and it isn’t a Flow bug — it’s a platform invariant. Salesforce does not allow a callout after a DML operation in the same transaction. You cannot save a record and then, in the same synchronous transaction, call an external service. The platform blocks it to avoid holding a database lock open while it waits on a network round trip it can’t control.
Where this bites is record-triggered flows. Your instinct is to put the callout right there in the fast, same-transaction path — a record is created, call the scoring API, stamp the score back. That path will fail, because the trigger is part of the save transaction. The supported pattern is the asynchronous path: the callout runs in the background after the triggering record’s save has committed. It’s a first-class feature of record-triggered flows for exactly this reason, and it also sidesteps the mixed-DML error class along the way.
Screen flows and autolaunched flows invoked outside a save transaction can call synchronously and use the response immediately — that’s the right shape for “validate this address and show the result before the user continues.” The rule to internalize: if a DML has already happened in this transaction, your callout belongs on an async path. Design for it up front rather than discovering it when the flow silently does nothing in production.
The limits are Apex’s limits
Because HTTP Callout compiles down to the same callout machinery as Apex, it inherits the same governor limits — and admins building these often don’t know those limits exist.
- 100 callouts per transaction. A callout inside a loop over a collection hits this ceiling fast. If you’re iterating over 200 records and calling out per record, you’re not building a Flow HTTP Callout integration; you’re building a batch problem that wants a different pattern.
- A cumulative callout timeout of 120 seconds per transaction, with each individual callout capped well below that. A slow endpoint doesn’t just delay your flow — it burns the shared budget for the whole transaction.
- Response size and heap limits. A callout that returns a multi-megabyte payload can blow the heap. HTTP Callout is for a result, not for bulk data extraction; if you’re pulling large datasets, that’s an ingestion or integration-pattern decision, not a Flow action.
These are the same governor limits that decide whether any automation survives production, and they’re worth reading alongside the broader governor-limits and API-limits picture. The declarative surface hides the code; it does not hide the limits.
When Flow HTTP Callout is the right tool — and when it isn’t
The decision is cleaner than the marketing makes it sound. Reach for HTTP Callout when the integration is:
- A single request-and-reply the user or process genuinely needs an answer from — address validation, a credit or risk score, a real-time inventory check, a shipping quote.
- Authenticated by something External Credentials supports — OAuth 2.0, API key headers, JWT. If the auth model fits the credential store, you’re in the happy path.
- Owned by an admin or low-code builder who shouldn’t have to wait on a developer to ship a two-field lookup.
Stay in Apex — or move to MuleSoft — when you hit any of these:
- Callouts in bulk or in a loop. Trigger-driven, per-record callouts across large volumes need bulkification and careful limit management that Apex gives you and a Flow loop does not.
- Chained or conditional call sequences with heavy transformation between steps, retry-and-backoff logic, or partial-failure handling. That’s orchestration, and it’s what an integration layer exists for.
- Auth or protocol the credential store can’t express, non-JSON payloads, streaming, or responses that exceed the heap. When the contract gets weird, typed Apex is more honest than a generated approximation.
- A reusable, versioned integration many systems depend on. At that point you want the governance of a real integration tier, which is the MuleSoft-as-action story, not a per-flow callout.
There’s also an Agentforce angle worth naming: because the generated callout is an invocable action, it can back an agent action built from a Flow. An agent that needs to check a live external fact — a policy status, an account balance from a system of record — can call one through a Flow HTTP Callout without anyone writing an Apex @InvocableMethod. The same grounding discipline applies: the agent should act on what the API actually returned, never on a value it inferred.
The takeaway
HTTP Callout in Flow is one of the highest-leverage declarative features Salesforce has shipped for integration, because it collapses the most common integration — a single authenticated REST call — from a developer task into an admin task. Paste a sample, get typed request and response objects, ship the flow. But it earns that leverage by generating the same External Services and Apex plumbing you’d otherwise write, which means the same rules apply: authenticate through Named and External Credentials, keep callouts off the same transaction as a DML by using the asynchronous path, respect the 100-callout and 120-second ceilings, and hand the genuinely hard integrations — bulk, orchestrated, oddly authenticated — back to Apex or MuleSoft. Get that boundary right and you’ll ship more integrations faster without building the fragile ones that fail quietly at 2 a.m.
Understanding the basics
What is HTTP Callout in Salesforce Flow?
It’s a Flow action that calls an external REST API declaratively, without Apex or middleware. You define an External Credential and a Named Credential in Setup, then in Flow you choose the method (GET, POST, PUT, PATCH, or DELETE), set the URL path, and paste a sample JSON response. Salesforce parses the sample, generates an External Service registration and the Apex request/response types behind the scenes, and produces an invocable action whose response you can use in later flow elements.
Do I still need Named Credentials for a Flow HTTP Callout?
Yes. The Named Credential defines the endpoint URL and references an External Credential that defines the authentication protocol and principal. This split keeps secrets in the credential store instead of in the flow, and it lets one endpoint definition be reused across many callouts. You also have to grant a permission set or profile access to the External Credential’s principal, or the callout fails to authenticate — a common first-time mistake that works for a System Administrator in a sandbox and breaks for the running user in production.
Why does my HTTP Callout fail in a record-triggered flow?
Almost always because Salesforce doesn’t allow a callout after a DML operation in the same transaction, and a record-triggered flow runs inside the record’s save transaction. The fix is to run the callout on the flow’s asynchronous path, which executes after the triggering record’s save commits and outside the transaction boundary. Screen flows and autolaunched flows that aren’t part of a save transaction can call out synchronously and use the response right away.
When should I use Apex instead of Flow HTTP Callout?
When you need callouts in bulk or inside a loop over many records, chained or conditional call sequences with retry and partial-failure handling, an authentication or payload shape the credential store can’t express, streaming, responses that exceed the heap, or a reusable versioned integration that many systems depend on. Those are orchestration and scale problems that typed Apex or a MuleSoft integration tier handle properly; Flow HTTP Callout is for the single, authenticated request-and-reply that used to be over-engineered.
Trying to decide whether an integration belongs in a Flow, in Apex, or behind a real integration tier — and how it holds up under load and governor limits? Talk to us about integration. Choosing the right seam for each call is exactly the work that keeps an org from becoming a pile of brittle callouts.