Jobber Integration
Overview
Section titled “Overview”The Jobber integration connects your Jobber account to Adva via OAuth and the Jobber GraphQL API. Once connected, Adva syncs your Jobber data automatically and maps it to the Adva data model.
What Gets Synced
Section titled “What Gets Synced”| Jobber Entity | Adva Entity | Direction |
|---|---|---|
| Clients | Customers | Jobber → Adva |
| Properties | Locations | Jobber → Adva |
| Quotes | Proposals + Line Items | Jobber → Adva |
| Jobs | Jobs | Jobber → Adva |
| Invoices | Invoices | Jobber → Adva |
| Team Members | Team Members | Jobber → Adva |
| Line Items | Products (derived) | Jobber → Adva |
Sync is currently one-way: Jobber to Adva. Changes made in Adva are not pushed back to Jobber.
Prerequisites
Section titled “Prerequisites”- A Jobber account with admin access
- Your Adva business must be on a plan that supports integrations
Step 1: Start the Connection
Section titled “Step 1: Start the Connection”Navigate to Settings > Integrations in the Adva web app. Click Connect next to Jobber. This redirects you to Jobber’s authorization page.
Step 2: Authorize in Jobber
Section titled “Step 2: Authorize in Jobber”Sign in to your Jobber account if prompted, then click Allow to grant Adva read access to your data. Jobber redirects you back to Adva automatically.
Step 3: Initial Sync
Section titled “Step 3: Initial Sync”After authorization, Adva runs an initial full sync of all your Jobber data. This typically takes a few minutes depending on the size of your account. You can monitor progress on the Integrations settings page.
How the Sync Works
Section titled “How the Sync Works”Full Sync
Section titled “Full Sync”A full sync pulls all records from Jobber using cursor-based pagination. It runs:
- Automatically after the initial connection
- When you click Sync Now on the Integrations page
- On a configurable schedule (default: daily)
Incremental Sync
Section titled “Incremental Sync”After the initial full sync, Adva listens for Jobber webhooks to pick up changes in real time. When Jobber notifies Adva of a change, only the affected record is re-fetched and updated.
Conflict Resolution
Section titled “Conflict Resolution”If the same record is modified in both Jobber and Adva between syncs, the Jobber version takes precedence during the next sync (last-write-wins from Jobber’s perspective).
Data Mapping Details
Section titled “Data Mapping Details”Clients → Customers
Section titled “Clients → Customers”| Jobber Field | Adva Field | Notes |
|---|---|---|
firstName | first_name | |
lastName | last_name | |
companyName | company_name | |
isCompany | customer_type | true → commercial, false → residential |
emails[0] | email | Primary email |
phones[0] | phone | Primary phone |
billingAddress | Address fields | Mapped to street_line_1, city, state, postal_code, country |
Properties → Locations
Section titled “Properties → Locations”| Jobber Field | Adva Field | Notes |
|---|---|---|
address | Address fields | Full address breakdown |
client.id | customer_external_id | Links location to the customer |
Quotes → Proposals + Line Items
Section titled “Quotes → Proposals + Line Items”| Jobber Field | Adva Field | Notes |
|---|---|---|
quoteNumber | proposal_number | |
title | project_type | |
quoteStatus | status | See status mapping below |
client.id | customer_external_id | |
amounts.total | final_price | |
lineItems[] | Proposal Items | Each line item becomes a proposal_item |
Quote Status Mapping:
| Jobber Status | Adva Status |
|---|---|
DRAFT | draft |
AWAITING_RESPONSE | sent |
APPROVED | approved |
CONVERTED | approved |
REJECTED | rejected |
ARCHIVED | expired |
Jobs → Jobs
Section titled “Jobs → Jobs”| Jobber Field | Adva Field | Notes |
|---|---|---|
jobNumber | job_number | |
title | name | |
jobStatus | status | See status mapping below |
client.id | customer_external_id | |
quote.id | proposal_external_id | Links job to original quote |
startAt | scheduled_date + scheduled_start_time | Split into date and time |
endAt | scheduled_end_time |
Job Status Mapping:
| Jobber Status | Adva Status |
|---|---|
IN_PROGRESS | in_progress |
ACTIVE | in_progress |
LATE | in_progress |
REQUIRES_INVOICING | completed |
ON_HOLD | pending |
UNSCHEDULED | pending |
ARCHIVED | cancelled |
Invoices → Invoices
Section titled “Invoices → Invoices”| Jobber Field | Adva Field | Notes |
|---|---|---|
invoiceNumber | invoice_number | |
subject | notes | |
client.id | customer_external_id | |
amounts.subtotal | subtotal | |
amounts.total | total_amount | |
amounts.depositAmount | discount | Mapped as deposit credit |
Team Members → Team Members
Section titled “Team Members → Team Members”| Jobber Field | Adva Field | Notes |
|---|---|---|
name.first | first_name | |
name.last | last_name | |
email | email | |
phone | phone | |
role | role | See role mapping below |
Role Mapping:
| Jobber Role | Adva Role |
|---|---|
ADMIN | admin |
MANAGER | manager |
WORKER | production |
VIEWER | sales_rep |
CONTRACTOR | production |
Product Derivation
Section titled “Product Derivation”Adva derives products from Jobber quote line items. Unique product names across all quotes are extracted and created as products in Adva with the most recent pricing.
API Reference
Section titled “API Reference”Connection Management
Section titled “Connection Management”# List all integration connectionsGET /api/v1/integrations
# Create a new connection (returns OAuth redirect URL)POST /api/v1/integrations{ "provider": "jobber"}
# Get connection statusGET /api/v1/integrations/:id
# Trigger a full syncPOST /api/v1/integrations/:id/sync
# DisconnectDELETE /api/v1/integrations/:idOAuth Callback
Section titled “OAuth Callback”The OAuth callback endpoint is called by Jobber after the user authorizes the connection:
GET /api/v1/integrations/oauth/jobber/callback?code=AUTH_CODE&state=ENCODED_STATEThis endpoint is unauthenticated — it validates the state parameter to prevent CSRF.
Webhooks
Section titled “Webhooks”Jobber sends webhooks to notify Adva of data changes:
POST /api/v1/webhooks/jobberThis endpoint is unauthenticated — it validates the webhook signature using HMAC-SHA256.
Configuration
Section titled “Configuration”The following environment variables are required for the Jobber integration:
| Variable | Description |
|---|---|
JOBBER_CLIENT_ID | OAuth client ID from Jobber Developer Center |
JOBBER_CLIENT_SECRET | OAuth client secret |
JOBBER_REDIRECT_URI | OAuth callback URL (e.g., https://api.getadva.ai/api/v1/integrations/oauth/jobber/callback) |
JOBBER_WEBHOOK_SECRET | Webhook signing secret for HMAC verification |
INTEGRATION_ENCRYPTION_KEY | 32-byte hex key for encrypting stored OAuth tokens |
Setting Up a Jobber App
Section titled “Setting Up a Jobber App”- Go to Jobber Developer Center
- Create a new app
- Set the redirect URI to your Adva instance’s OAuth callback URL
- Copy the Client ID and Client Secret to your environment
- Configure webhooks to point to your Adva webhooks endpoint
Troubleshooting
Section titled “Troubleshooting””Connection failed” after OAuth
Section titled “”Connection failed” after OAuth”- Verify
JOBBER_CLIENT_IDandJOBBER_CLIENT_SECRETare correct - Ensure the redirect URI in Jobber Developer Center exactly matches
JOBBER_REDIRECT_URI - Check that the Jobber user has admin access
Sync completes but data is missing
Section titled “Sync completes but data is missing”- Only entity types with data in Jobber will appear in Adva
- Properties require a linked client — orphaned properties are skipped
- Quotes without a client are skipped
Stale data after changes in Jobber
Section titled “Stale data after changes in Jobber”- Webhook delivery can be delayed — try clicking Sync Now for immediate results
- Verify the webhook endpoint is accessible from Jobber’s servers
- Check the sync log on the Integrations settings page for errors