Jobber is where a lot of home services businesses already keep the thing that matters: a quote, a scheduled visit, a job status and an invoice. That makes it the right trigger source for messaging, because it already knows the facts you would otherwise be re-typing.
The three routes, and which to pick
| Route | What it needs | Best when |
|---|---|---|
| Jobber's own API and webhooks | Developer access, and somewhere to run code | You want full control and have someone to build it |
| Zapier (or Make / n8n) | A paid Zapier plan on both sides | You want it working this week without a developer |
| A provider with a native integration | Just the two accounts | One exists for your provider — check first, it is the least work |
Jobber publishes a GraphQL API with webhooks, and the webhook requests carry a calculated signature you are expected to verify — HMAC-SHA256, using the secret Jobber gives you. If you are building this yourself, that verification is not optional. How to do it correctly.
Check your Zapier connection version
Jobber's Zapier integration has been through versions, and older connections do not expose newer triggers. If a trigger you expect is missing, an outdated connection is the usual reason — reconnect rather than concluding it cannot be done.
Which Jobber events deserve a message
| Jobber event | Message | Why it earns its place |
|---|---|---|
| Quote sent | Short note pointing at the emailed quote | The quote sits unopened otherwise |
| Quote approved | Thanks plus the scheduling question | Momentum, while they are still decided |
| Visit scheduled | Date, window, technician name | Sets the expectation you will be held to |
| Day before visit | Confirm, one-tap reschedule | Catches the change while you can still fill the slot |
| Technician en route | Name, ETA | Removes the stranger-at-the-door problem |
| Job complete | What was done, photo | Turns work into something they can show a partner |
| Invoice sent | Note that it is in their email | Gets paid faster than email alone |
| 90 minutes after close | Review request | The goodwill window is short |
That is eight possible messages and you should not send all eight. Pick the two with the clearest business case — usually the day-before confirmation and the review request — get them working, then add. Why one excellent play beats six mediocre ones.
The webhook payload, and the field that matters
import crypto from "node:crypto";
app.post("/webhooks/jobber", express.raw({ type: "application/json" }), async (req, res) => {
const expected = crypto
.createHmac("sha256", process.env.JOBBER_WEBHOOK_SECRET!)
.update(req.body)
.digest("base64");
const signature = req.get("X-Jobber-Hmac-SHA256") ?? "";
const a = Buffer.from(expected);
const b = Buffer.from(signature);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
return res.status(401).end();
}
res.status(200).end(); // Acknowledge first, work second.
const event = JSON.parse(req.body.toString("utf8"));
await enqueueMessage({
// E.164 on the way in. Storing numbers three ways is how the same
// customer gets two messages from two contact records.
to: toE164(event.data.client.phone, "US"),
template: "visit_confirmation",
// Natural key, so a webhook retry cannot double-send.
idempotencyKey: `${event.data.visit.id}:visit_confirmation`,
});
});The shape of a Jobber-triggered send. Verify the signature over raw bytes before parsing, and normalise the number on the way through.
The consent field Jobber does not have
Jobber stores a phone number. It does not store whether that customer agreed to receive marketing messages, or when. You need that somewhere — a custom field in Jobber, or your own table keyed on the client ID — and it must be checked at send time, not when the list was built. What consent has to look like, and the compliance rules.
Where replies should land
This is the decision that determines whether the integration succeeds. If replies arrive only at your provider, someone has to watch a second inbox, and that is how replies go unanswered. The realistic options are a shared inbox on the provider side, or writing inbound messages back to the Jobber client as a note.
Writing back is more work and much better: whoever opens the job next sees the conversation. Who answers the replies is the question most of these projects get wrong.
Before you turn it on
- Webhook signature verification tested with a deliberately bad signature.
- Phone numbers normalised to E.164 on write.
- Consent state recorded, and checked at send time.
- STOP on the iMessage side suppresses future Jobber-triggered sends.
- Quiet hours enforced in the recipient's timezone, in your code.
- Idempotency keyed on the Jobber record ID, so a retry cannot double-send.
- Someone named is responsible for replies within the hour.