Connect Jobber to n8n (Google Sheets + alerts)
There's no Jobber node in n8n and no Jobber template in the n8n gallery (a search for "jobber" returns 0). The forum question "Connecting Jobber to n8n" asks for exactly this: update a Google Sheet when jobs change in Jobber. The poster wanted that "when we add or update clients & job statuses n8n will automatically update certain cells within google sheets", and asked where to find a tutorial or workflow. The thread has 687 views and no solution. The usual blocker is OAuth: "everything breaks in 1 hour when the access_token expires". This guide walks through a setup that keeps working, and the free template does the rest.
n8n workflow JSON: verified Jobber webhooks + 15-minute poll fallback, Sheets upsert, one email per new job or quote. No credentials inside. Needs n8n 2.29.0+.
Want it set up faster? The Jobber Pro Kit ($19) adds a step-by-step setup guide, the Sheet header CSV and an offline test kit (Jobber API mock + signed-webhook tester), so you can check it works before connecting your real account.
What you'll build
- Jobber sends a webhook when a job or quote is created. n8n checks the signature, replies within 1 second, then fetches the full record from Jobber's GraphQL API.
- A 15-minute poll runs as a safety net, so a missed webhook doesn't mean a missing row.
- Each job or quote becomes one row in Google Sheets: number, title, status, client, email, phone, address, total, dates and a link back to Jobber. Repeats update the same row.
- You get one email per new job or quote, and one "sync problem" email a day if the connection breaks.
Before you start
- n8n 2.29.0 or newer. Older versions have the token-refresh bug described below. Check the version under Settings → About n8n.
- A Jobber account where you're an admin, and a free Jobber Developer Center account.
- An n8n instance Jobber can reach over HTTPS (n8n Cloud or self-hosted with a public URL) if you want webhooks. The poll works without a public URL.
Step 1: Create a Jobber app
In the Jobber Developer Center, create a new app. A private app for your own business is a custom integration: it can stay in Draft as long as it's connected to 5 or fewer paying Jobber accounts, so there's no Marketplace review.
- Scopes: read access to jobs, quotes and clients. Webhooks only arrive for objects your app has the read scope for (Jobber webhook docs).
- OAuth Callback URL: paste the OAuth Redirect URL from the n8n credential in step 2. It looks like
https://your-n8n.example.com/rest/oauth2-credential/callback. - Copy the app's Client ID and Client Secret.
Step 2: The OAuth2 credential (the part that usually breaks)
In n8n, create an OAuth2 API credential with these values from Jobber's app authorization docs:
| Field | Value |
|---|---|
| Grant Type | Authorization Code |
| Authorization URL | https://api.getjobber.com/api/oauth/authorize |
| Access Token URL | https://api.getjobber.com/api/oauth/token |
| Client ID / Client Secret | from your Jobber app |
| Scope | leave empty (scopes come from the app) |
| Authentication | Body (the accepted fix when authorization fails with Header) |
Click Connect and approve the app in Jobber.
Why it used to break after an hour: Jobber access tokens last 60 minutes, and refresh token rotation means every refresh returns a new refresh token that replaces the old one. Jobber's token endpoint answers with a text/plain content type. Older n8n versions couldn't parse that and failed with Unsupported content type: text/plain (n8n issue #30345). Two fixes, #33018 (parse non-standard token responses) and #33092 (serialize refreshes so a rotated token isn't lost), shipped in n8n 2.29.0. On 2.29.0+ you don't need a cron job that refreshes the token by hand.
A forum reply warns that refresh "won't work because gql returns an HTTP 20X". That isn't what Jobber does today. We sent a bad token to api.getjobber.com/api/graphql and got HTTP 401 {"message":"Token not recognized"}, which is what triggers n8n's automatic refresh. In our tests, an expired token was refreshed and the request retried without any extra nodes.
Step 3: Call the GraphQL API with the version header
Use an HTTP Request node: POST to https://api.getjobber.com/api/graphql, Authentication Generic Credential Type → OAuth2 API, and a header X-JOBBER-GRAPHQL-VERSION. Jobber's versioning docs say this header "is required for all apps". Versions are dates, and the newest in the changelog is 2026-09-25. Body (JSON):
{{ JSON.stringify({
query: `query JobById($id: EncodedId!) {
job(id: $id) {
id jobNumber title jobStatus total createdAt startAt jobberWebUri
client { id name companyName emails { address primary } phones { number primary } }
property { address { street city province postalCode } }
}
}`,
variables: { id: $json.item_id }
}) }}
Every field above was checked against Jobber's live schema. For quotes, use quote(id:) with quoteNumber quoteStatus amounts { total } sentAt. Jobber also reports some failures as HTTP 200 with an errors array, for example THROTTLED when a query costs more points than you have left (rate limits: a 10,000-point bucket, refilled at 500 points per second). Check for errors before you write anything.
Step 4: Receive and verify Jobber webhooks
A Jobber webhook only says what happened. The body is {"data":{"webHookEvent":{"topic","appId","accountId","itemId","occurredAt"}}}, with no job details, so you fetch the record by itemId (step 3). Three rules from the webhook docs shape the workflow:
- Verify the signature. Each request has an
X-Jobber-Hmac-SHA256header: base64 HMAC-SHA256 of the raw body, keyed with your app's client secret. In n8n, turn on Raw Body in the Webhook node's options, then use a Crypto node (Action Hmac, Binary File on, propertydata, SHA256, Base64) with a Crypto credential that holds the client secret. Compare the result to the header and answer 401 if it doesn't match. - Answer within 1 second. Set the Webhook to respond with a Respond to Webhook node and send the 200 before calling the API.
- Expect duplicates. Delivery is at-least-once. Upsert rows on a key (
job:<id>) and put a Remove Duplicates node (Remove Items Processed in Previous Executions) before the email.
Apps created before Dec 8, 2023 get the field as occuredAt (one "r"); the template accepts both. Once the workflow is published, open your app's webhook settings in the Developer Center and add the Webhook node's production URL for JOB_CREATE, QUOTE_CREATE and APP_DISCONNECT.
Step 5: Google Sheets and the email alert
Create a sheet with a Jobber tab and this header row:
record_key, record_type, jobber_id, number, title, status, client_name, client_email, client_phone, property_address, total, created_at, start_at, jobber_url, source, synced_at
Use Google Sheets Append or Update Row with record_key as the column to match on, so a repeat webhook or a poll overlap updates the row instead of adding one. After it, Remove Duplicates on record_key and a Gmail node send the alert, so you're emailed once per job or quote.
Step 6: Add the poll fallback
A Schedule Trigger every 15 minutes runs jobs(first: 50, filter: { createdAt: { after: $since } }, sort: [{ key: CREATED_AT, direction: DESCENDING }]) and the same for quotes, looking back 30 minutes. The overlap is harmless because rows upsert and alerts are deduplicated. Each poll costs about 1,250 points, far below the bucket. If you can't register webhooks, the poll works on its own.
Download the template
Free download: n8n-jobber-to-sheets.json (import with Workflows → Import from file). It contains steps 2–6 already wired: signature check, topic routing, one GraphQL node with the version header, Sheets upsert, alert once per record and a sync-problem email. No credentials are inside; you attach your own Jobber OAuth2, Crypto, Google Sheets and Gmail credentials. The sticky notes repeat this guide's setup steps.
The JSON is and stays free. If you'd rather not wire the test setup yourself, the Jobber Pro Kit ($19 on Gumroad) bundles the same workflow with a setup guide, the Sheet header CSV and the offline test kit we used (a local Jobber API mock and a signed-webhook tester).
We tested it on n8n 2.44.4 against a local mock of Jobber that behaves like the real API: 401 on expired tokens, text/plain token responses, rotating refresh tokens. The tests covered a new job, a new quote, a duplicate webhook, a bad signature, an expired token, a revoked refresh token, throttling, the poll and an app disconnect, and all checks passed. The GraphQL queries were validated against Jobber's live schema. We have not tested it against a real Jobber account yet.
Troubleshooting
| Symptom | Fix |
|---|---|
| Works for an hour, then 401 | Update n8n to 2.29.0+ and click Reconnect on the credential once. |
Unsupported content type: text/plain | The same bug (#30345). Update to 2.29.0+. |
The provided refresh token is not valid. | The stored refresh token was rotated or revoked, often by GraphiQL testing or a second tool sharing the app. Reconnect the credential. |
| Every webhook gets 401 from your workflow | Raw Body is off, or the Crypto credential doesn't hold the same client secret as the app. |
| Authorization fails when connecting | Set the credential's Authentication to Body and check that the callback URL in the Jobber app matches n8n's exactly. |
| No webhooks arrive | The app needs the read scope for the object, the workflow must be published, and the URL must be the production one, not /webhook-test/. |
n8n workflow JSON: verified Jobber webhooks + 15-minute poll fallback, Sheets upsert, one email per new job or quote. No credentials inside. Needs n8n 2.29.0+.
Want it set up faster? The Jobber Pro Kit ($19) adds a step-by-step setup guide, the Sheet header CSV and an offline test kit (Jobber API mock + signed-webhook tester), so you can check it works before connecting your real account.
FAQ
Is there a Jobber node for n8n?
No. n8n has no built-in Jobber node and the template gallery has no Jobber templates. You connect with an HTTP Request node, a generic OAuth2 API credential and Jobber's GraphQL API at api.getjobber.com/api/graphql.
Why does my Jobber connection in n8n stop working after an hour?
Jobber access tokens expire after 60 minutes and refresh tokens rotate. n8n versions before 2.29.0 could not parse Jobber's text/plain token response (n8n issue #30345). Update to 2.29.0 or newer, set the credential's Authentication to Body, and reconnect once.
Which header does the Jobber API require?
X-JOBBER-GRAPHQL-VERSION, set to a dated API version such as 2026-09-25. Jobber's docs say it is required for all apps.
How do I verify Jobber webhooks in n8n?
Turn on Raw Body in the Webhook node, compute a base64 HMAC-SHA256 of the raw body with your app's client secret using the Crypto node, and compare it with the X-Jobber-Hmac-SHA256 header. Reply 401 if it doesn't match, and reply 200 within 1 second if it does.