Skip to content

When Someone Calls You Back

Module 6 of 7 in the chapter Salesforce as an API Provider, chapter 8 of the Integration Architect course. Each module stands on its own. Previous: Your Own Door: Custom Apex REST · Next: Who’s at the Door

The question this module answers: When another system wants to tell Salesforce that something happened, by calling a webhook, where does that call land, and what has to be checked before you trust it?

In chapter 2, a delivery’s status changed and Salesforce called Redrock’s webhook. Salesforce was the client; Redrock’s webhook was the server, waiting to be told. That’s the easy direction. Salesforce makes outbound calls all day.

Now turn it around. Say Steve Trucking’s SMS provider texts a recipient that their delivery is on the way, and calls back a few seconds later to say whether the text arrived. The provider is the client now. It wants to call you, at an address you gave it, whenever something happens. That’s a webhook coming in.

A webhook is just an HTTP POST to an address, usually with a JSON body. The sender doesn’t wait for a long answer; it wants a quick yes, and it will try again later if it doesn’t get one.

Salesforce has no built-in place to receive one. There’s no setting where you paste in “accept webhooks from the SMS provider.” Every door from module 1 that a program uses expects a token from the token server, and most webhook senders don’t sign in with OAuth. They send a secret-signed message to an address, and that’s all.

So you build the receiving end, and there are three places to build it.

1. The integration layer receives it, then calls in. The webhook lands on your middleware, which is built to receive calls from the internet. It checks the message, and then calls Salesforce through a normal door with a normal token: a REST upsert, or your own Apex REST door from module 5. Salesforce never faces the sender. This is the first choice whenever you have an integration layer, and it’s how Steve Trucking handles the SMS provider.

2. The integration layer publishes a platform event. The same as the first, except the middleware doesn’t write the records itself. It publishes an event into Salesforce, through the REST API or the Pub/Sub API, and a flow or trigger inside Salesforce takes it from there (chapter 4 built one in Flow; chapter 11 goes deep). Good when several things inside Salesforce care about the same news, or when you want the work done after the webhook has already been answered.

3. Your own door, open to the internet. No middleware: an Apex REST service on a Salesforce Site, reachable without signing in, as the site’s guest user. It works, and for a small org without an integration layer it can be the only option. But look at what it is. It’s a public door, like the web forms in module 1, except this one runs your code. Everything that keeps it safe is now in that code, and the guest user must be able to do almost nothing. Chapter 13 covers guest users and why one should have almost no access. If you choose this, choose it on purpose and write down why.

Three ways to take a webhook in Three ways to take a webhook in. On the left, the sender, Steve Trucking's SMS provider, calls back to say whether a text arrived. Row 1: the integration layer receives the webhook, checks it, then calls Salesforce through a normal door with a token, a REST upsert or your own Apex REST door. Row 2: the integration layer receives it, checks it, and publishes a platform event; a flow or trigger inside Salesforce does the work. Row 3, in amber: your own Apex REST door on a Salesforce Site, open to the internet as the guest user, with no sign-in; all the checks are in your code. Underneath: whichever way in, the receiver checks the signature, the time and duplicates, and answers fast. {"author": "Steve Simpson", "blueprint": "1.0.0", "builder": "standard 1.57.1", "built": "2026-10-31", "id": "DGM-INT-SP-05", "rights": "\u00a9 2026 Twinshark LLC. All rights reserved.", "template": "cells 0.5.0", "theme": "stevetecharc 1.4.0"} THE SENDER WHERE IT LANDS INSIDE STEVE TRUCKING'S ORG The SMS provider calls back: did the text arrive? The integration layer checks it, then calls in with a token 1 A REST upsert or your own door a normal door, a normal token The SMS provider the same call back The integration layer checks it, then publishes an event 2 A platform event a flow or trigger does the work The SMS provider the same call back Your own door on a Site open to the internet, as the guest user; every check is in your code 3: no sign-in Your Apex does the work the guest user can do almost nothing else posts calls in posts publishes posts runs Whichever way in: check the signature, the time and duplicates, then answer fast. HOW TO READ IT nobody signs in: the checks are all yours © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Three ways in. Only one of them has Salesforce facing the internet.

Whichever way in, the receiver does four things. Many webhook senders follow a common shape for them, written down as the Standard Webhooks specification, a community spec rather than an IETF standard (Standard Webhooks (opens in a new tab), checked 2026-10-31). Your sender may name its headers differently; the four checks are the same.

1. Is it really from them? Check the signature. You and the sender share a secret. The sender signs each message, and you sign it again on your side and compare. In the Standard Webhooks shape, the signature covers the message’s ID, its time and its body together, joined with dots: msg_id.timestamp.payload. Anyone can find your address. Only the sender has the secret. A message whose signature doesn’t match is thrown away, whatever it says. (In Apex, Crypto.generateMac does the signing; chapter 13 covers keeping the secret.)

2. Is it fresh? Check the time. A signed message can be copied and sent again, word for word, and its signature still matches. So the time is signed too, and the receiver rejects anything outside a short window. The spec’s words: verify the timestamp is “within some allowable tolerance of the current timestamp to prevent replay attacks.” Pick the window, a few minutes, and write it down.

3. Have I seen it before? Check the ID. Senders retry. If your answer was slow, or lost on the way back, the same webhook comes again, and the ID “remains the same no matter how many times a webhook that has failed is retried” (same spec). Keep the IDs you’ve processed, and when one comes back, answer yes and do nothing. Otherwise one text that arrived becomes two delivery notes. It’s the same idea as module 2’s upsert by key: doing it twice must leave the same result as doing it once.

4. Answer fast, then do the work. The sender counts any 2xx as delivered and anything else as a failure, and it will retry, the spec’s example schedule running for about three days. So check the message, store it or publish it, answer 200, and do the real work afterwards. A receiver that does all its processing before answering will time out under load, get the same message again, and make the load worse. Two answers from module 5 matter here too: 429 with Retry-After asks the sender to slow down, and under the spec, 410 Gone tells it to stop sending to this address.

  • Where webhooks land. The integration layer, by default. Your own door on a Site only on purpose, with the reason written down.
  • The four checks, and who owns each. Signature, time window, duplicate IDs, a fast answer. In the middleware or in your code, but somewhere named.
  • Where the secret lives, and how it changes. The spec allows more than one signature at a time so a secret can be replaced without stopping delivery.
  • What happens after the yes. The work that runs after the 200, and where a failure there is logged and retried (chapter 14).