Calling your own system from a WhatsApp flow
One block turns a scripted flow into one that knows things — provided you build the path for when your server is asleep.
The Call External API block lets a flow read from or write to your own software in the middle of a conversation. It is the difference between a bot that recites what you typed into it and one that can answer "where is my order".
It is also the block with the most ways to go wrong, because it depends on something outside this platform being awake and returning what you expect.
Two directions, two methods
| Reading (GET) | Writing (POST) | |
|---|---|---|
| What it does | Looks something up | Sends something to you |
| You configure | Where the answer lives in the response | The fields to send |
| Result | Saved into contact fields | A record created in your system |
| Example | Order status by order number | A support ticket, a lead |
A flow can do both, in sequence — read the order, then post the customer's chosen action back. That is a common shape for anything where the customer is making a decision about existing data.
Reading: saving what comes back
A GET call needs to know two things beyond the address: what to send, and where in the answer the useful values are.
The block maps a path in the response to a contact field, so a status buried in a nested response becomes a field you can use in the very next message. Multiple mappings are normal — status, carrier and tracking number from one call.
Once mapped, those values behave like any other contact field. You can put them into message text, branch on them, or save them for later.
Writing: what to send
A POST call carries fields you define, and their values can be anything the flow holds — the customer's phone number, an answer they gave, something calculated a moment earlier.
The most common use is not exotic: creating a record of an enquiry in whatever system your business actually runs on, so the conversation is not the only place it exists.
The two ports, and why the failure one matters most
The block branches on success and failure, and the failure port is not optional in any flow you intend to leave running.
Things that legitimately fail: your server is down, the customer typed an order number that does not exist, an authentication token expired, the response took too long. All of those are ordinary Tuesday events, and none of them should leave the customer staring at a chat that went silent.
Both paths built
A failure path that hands to a human is almost always right. A failure path that apologises and stops is acceptable. A failure path that does not exist is a customer who thinks you ignored them.
Authentication and secrets
The block supports a token and custom headers, which covers most ordinary APIs. Two habits worth keeping:
- Use a token scoped to exactly what the flow needs. A read-only credential for a lookup; nothing broader.
- Rotate it on a schedule, the same way you would any other integration credential, and remember to update the block when you do.
If your endpoint is not public, this is also the point at which somebody needs to decide how it will be reached. That is a conversation to have before building the flow rather than during it.
Speed is a design constraint
The customer is sitting in a chat waiting. A call that takes several seconds is noticeable; one that takes longer feels broken.
Two mitigations. Send a short line before the call — "let me check that for you" — so the pause has an explanation. And keep the endpoint the flow calls as simple as possible: a purpose-built lookup that returns three fields beats a general endpoint that returns everything about an order.
The other direction
This block is your flow reaching out. The reverse — your system starting a flow — is a different mechanism entirely, and if what you want is "when X happens in our software, message the customer", that is the one you need. It is covered in starting a flow from your own system.
Plenty of setups use both: an event starts the flow, and a lookup inside the flow fetches the detail the event did not carry.
When a spreadsheet is the better answer
Before commissioning an endpoint, check whether the data could live in a Google Sheet. The Sheets block can look up a row, add one, or update one, needs no developer, and is set up by signing in and picking the file.
For a price list, a stock list, a set of dealer codes, or a booking log, that is frequently the whole solution — see WhatsApp automation with Google Sheets. Keep the API for data that genuinely lives in software.
What the API call does not change
Nothing about Meta's rules. Whatever your system returns, sending it to a customer outside the 24-hour window still requires an approved template, per Meta's sending messages documentation, and inside the window a free-form reply remains free under Meta's pricing documentation.
So a lookup flow triggered by the customer's own message is the easy case, and one triggered by your system is the case that needs a template ready.
Frequently asked
Can it call more than one endpoint?
Yes — chain the blocks. A GET to read, then a POST to write, each with its own failure path.
What if the response shape changes?
The mapping stops finding the value and the field arrives empty. Guard any message that uses it, so an empty value stops the flow rather than sending a gap.
Do I need a developer?
To build or expose the endpoint, yes. To configure the block, no — it is a form.
Is it safe to put a token in the block?
Treat it like any credential: scope it narrowly, rotate it, and do not reuse an admin token where a read-only one works.
A worked example: order status
The single most requested lookup, and a good template for the rest:
- Ask for the order number and save it to a contact field.
- Send a holding line — one sentence, so the pause is explained.
- Call your endpoint with that order number, mapping status, carrier and tracking number into 3 contact fields.
- On success, send the status using those fields.
- On failure, assign the chat and tell the customer a person is looking.
Five steps, one of which most people forget. The version of this that uses Shopify data rather than your own endpoint is in answering "where is my order" automatically.
What to check before you build
| Question | Why it matters |
|---|---|
| Is the endpoint reachable from outside your office? | An internal-only address will never work |
| How fast does it respond? | Anything past a few seconds feels broken in a chat |
| What does it return when nothing is found? | Decides whether "no such order" is a success or a failure |
| Does it rate limit? | A busy flow can call it hundreds of times a day |
| Who rotates the token? | An expired credential fails silently on the customer's side |
Fifteen minutes with whoever maintains the system, and it saves a week of debugging a flow that was never going to work.
Keeping the flow honest when data is missing
The single most common production problem is not a failed call but a successful one that returned a blank. An order with no tracking number yet is a perfectly valid response, and a message built around it reads badly.
Guard every message that uses a looked-up value. The block that stops a run when a value is missing exists for exactly this, and the same discipline is covered from the data side in tagging and segmenting customers automatically.
The numbers worth knowing before you commit
Some rough planning figures, all of which are about your system rather than ours:
| Consideration | Rule of thumb |
|---|---|
| Acceptable response time | Under 2 seconds feels instant; past 5 it feels broken |
| Fields to map back | 3 to 5. More than that and the message is too long anyway |
| Calls per conversation | 1 or 2. Chaining four lookups is a sign the endpoint should do more |
| Token lifetime | Whatever your policy says — put the rotation in a calendar, not in someone's memory |
None of these are enforced limits. They are the shape of an integration that keeps working, and the difference between a flow you trust and one you check on every week.
Building it in the right order
- Prove the endpoint outside the flow first, with whatever tool your developer uses. If it does not work there, it will not work here.
- Build the flow with the failure path first, so the incomplete version is still safe to publish.
- Add the success path, and test it with a value you know exists.
- Test with a value you know does not exist, which is the case customers will produce on day one.
- Then publish.
Step four is the one that catches the design mistake: deciding whether "not found" should be treated as success or failure is a decision, and making it deliberately is better than discovering what your endpoint happens to return.