Simpro API integration: a practical guide
What you need to know before connecting anything to the Simpro API, from authentication to webhooks. Written from building an integration that raises real jobs every day, including the parts the documentation does not warn you about.
Published · 8 minute read
What the Simpro API is
Simpro exposes a REST API on every build. It reads and writes JSON over HTTPS and covers most of what you see in the Simpro interface: customers, sites, jobs, quotes, cost centres, attachments and more.
Most trade businesses look at it for one reason. Work arrives somewhere other than Simpro, usually a shared mailbox, and someone retypes it into a job. An integration removes the retyping. The two calls that matter most are creating a job, with POST /jobs/, and creating a quote, with POST /quotes/, each against an existing customer and site.
Three ways to authenticate
Which one you use depends on who the integration is for. A script for your own build can use a key. A product used by many businesses should use the sign-in flow.
Permanent API key
Generated by an admin inside your own build. The simplest option for an in-house script: one token, no expiry, sent as a bearer token on every request. It is tied to that one build and has full access, so store it like a password.
OAuth client credentials
A client ID and secret exchanged at your build's /oauth2/token endpoint for a short-lived access token, about an hour by default. Cache the token, refresh it before it expires, and retry once on a 401. This is how Simpro often provisions developer sandboxes.
Authorization code (Marketplace apps)
The flow apps listed on the Simpro Marketplace use. A user signs in with Simpro, approves the app and, on a multi-company build, picks the company. The app receives an access token and a refresh token, so the customer never has to create an API application in their build.
Creating a job
A job needs a type (Service, Project or Prepaid), a customer ID and a site ID that already exist in Simpro. Name, description, notes, due date and the customer's order number are optional but worth sending. A successful call returns 201 with the new job's ID.
The hard part is not the call, it is the mapping. Your system has to know which Simpro customer and site a request belongs to before it can raise anything. Matching by email domain gets you most of the way. The rest needs a person to confirm the first time, then the link is remembered.
Put your own reference in the job name, such as a ticket number. Then anyone can find the job from your system and the request from Simpro, without a lookup table nobody maintains.
Six things that catch people out
01Every build has its own address
There is no single Simpro API host. Each customer's build lives at its own domain, and every call goes to https://<build>/api/v1.0/companies/{companyID}/... An integration that serves more than one business has to store the build address per customer.
02The company ID matters
Single-company builds use company ID 0. Multi-company builds have several, and a job created against the wrong one lands in the wrong set of books. List the companies once at connection time with GET /api/v1.0/companies/ and store the chosen ID.
03Access is all or nothing
A Simpro credential cannot be scoped to read-only, or to jobs only. If you need a connection that can look but not touch, your integration has to enforce that itself. Starting every production connection read-only, then switching on job creation once the mapping is checked, avoids an expensive first day.
04Refresh tokens rotate, and the old one dies
With the authorization code flow, using a refresh token returns a new one and invalidates the old one straight away. In our testing, refreshing twice from the same stored token failed the second time with invalid_grant. On serverless hosting where several processes may refresh at once, only one should be allowed to spend the token, and the new one must be saved before anything else happens. Lose it and the customer has to reconnect by hand.
05Webhooks can arrive before the change is saved
Stage webhooks (job.stage.pending, progress, complete, invoiced, archived) are triggered by the job's Stage field, not its Status. Do not trust the payload: re-read the job through the API for the real stage. We have also seen an event arrive a moment before Simpro saved the change, so the re-read still showed the old stage. A short retry and a scheduled re-check every few minutes catch both that and the occasional event that never comes.
06Jobs do not always pass through Complete
Jobs can jump straight from Pending or Progress to Invoiced. If your integration waits for Complete to tell someone the work is done, it will sometimes wait forever. Treat Invoiced without a previous Complete as finished too, and never treat Archived as finished, because cancelled jobs are archived as well.
Build it or use one that exists
A first version that creates a job from a form takes a developer a few days. Keeping it working takes longer: token rotation, missed webhooks, customer and site matching, multi-company builds and someone to call when it stops.
Build your own when your process is genuinely unusual. If the problem is the common one, requests arriving by email and being retyped into Simpro, an existing integration will usually be cheaper than maintaining your own.
How Dispatch Layer uses the Simpro API
Dispatch Layer turns emails in your Microsoft 365 or Google Workspace shared mailbox into tickets, then raises the Simpro job or quote from the ticket with the customer and site already filled in. Stage changes come back onto the ticket. A job is never created without a person choosing to create it, and every connection starts read-only. It is listed on the Simpro Marketplace, so connecting is a sign-in rather than an API project.
Common questions
- Does Simpro have an API?
- Yes. Simpro has a REST API that every build exposes at its own address, under /api/v1.0/companies/{companyID}/. It covers customers, sites, jobs, quotes and much more, and it can send webhooks when records change.
- How do I get access to the Simpro API?
- There are three routes. A permanent API key generated inside your own build, an OAuth client ID and secret for server-to-server use, or the authorization code flow that apps listed on the Simpro Marketplace use, where a user signs in with Simpro and approves the connection.
- Can I limit what an API connection can do in Simpro?
- Not inside Simpro. API access is all or nothing, with no granular permissions. If you want a connection that can only read, the integration itself has to enforce it, which is why a sensible first connection to a production build is read-only.
- Can Simpro tell my system when a job changes stage?
- Yes, through webhooks. Simpro sends an event such as job.stage.complete when a job's Stage changes. Treat the event as a prompt to re-read the job rather than as the truth, and keep a scheduled re-check for the occasional event that never arrives.
- Do I have to build a Simpro integration myself?
- Not if an existing one does what you need. Apps on the Simpro Marketplace connect through the standard sign-in, so there is no API application to set up in your build. Building your own makes sense when your process is unusual enough that nothing off the shelf fits.