Stream a ServiceM8 account
Land a ServiceM8 account's jobs, quotes, invoice lines, payments, bookings, clients, staff time and forms in your warehouse, read with an API key, with nothing to approve.
A ServiceM8 stream lands a ServiceM8 account's jobs and quotes, the lines and payments behind each invoice, the schedule, clients, staff time, forms and assets in your warehouse, as often as every 15 minutes. After the first run, each run reads only what changed in ServiceM8 since the last.
ServiceM8 is a published source, like Postgres and Bite: sanda wrote the code that reads it and runs it as its own, so there is no connector for sam to write or for anyone to approve. You type an API key the account's Business Owner makes in ServiceM8, choose what to read, and set a schedule.
Before you start
- The Business Owner makes the key. In ServiceM8, only the Business Owner can make an API key. It is under Settings · API Keys (the button may read API Access). Make an API key there, not a Plugin API key (one that starts
smk-): those are ServiceM8's older kind, and its API doesn't accept them. sanda only reads, so Read Only access is enough. Give the key a name such assanda, so you can tell it apart from other keys later. - One account at a time. Each key reads one ServiceM8 account. A business with two accounts connects each one and makes a stream for each.
- Only owners and admins connect a key and make a stream on it in sanda, because sanda reads the account on the whole workspace's behalf.
Connect an account
- Open Pull. Go to Data · Streams, open the Pull tab and press the ServiceM8 card under Choose a source. The new pull's editor opens on Connect a ServiceM8 account when none is connected yet. Once an account is connected, Connect an account beside ServiceM8 under Connected adds another.
- Paste the API key into API key. Name is optional: leave it empty and sanda names the account after the business.
- Press Check and connect. sanda asks ServiceM8 which account the key belongs to before it keeps the key. The account is listed under ServiceM8 in Connected, named after the business (such as
ServiceM8 · Acme Plumbing), with the last characters of the key. If you connected it from a new pull's editor, the account is chosen there.
sanda keeps the key encrypted, only ever sends it to ServiceM8, and never shows it again, in the console or to sam. Type it again replaces the key (after you make a new one in ServiceM8, say), and every stream on the account carries on. A key for a different ServiceM8 account is refused there, because a stream keeps the account it reads. Disconnect forgets the key in sanda. To stop it working in ServiceM8 as well, revoke it under Settings · API Keys.
Make a stream
- Start it. Press the ServiceM8 card under Choose a source, or New pull and then ServiceM8.
- Choose when it runs. When it runs comes first. A ServiceM8 stream runs at most every 15 minutes, so the faster choices are greyed out. Within your trading hours is a good start. See when a stream runs.
- Name it. Its tables are named after it: a stream called
sm8lands jobs inraw.sm8__jobs. - Choose the account, and, if your workspace has more than one warehouse, the warehouse it lands in. Both are chosen once.
- Choose what it reads. Everything is ticked. Untick what you don't need: each one you leave out saves requests from the account's daily allowance.
- Press Save pull. Saving reads nothing yet: press Run now, or wait for its schedule.
What it reads
| Tick | Lands in | Each run reads |
|---|---|---|
| Jobs | raw.<stream>__jobs |
The jobs that changed since the last run |
| Job materials | raw.<stream>__job_materials |
The job materials that changed since the last run |
| Job material bundles | raw.<stream>__job_material_bundles |
The job material bundles that changed since the last run |
| Job activities | raw.<stream>__job_activities |
The job activities that changed since the last run |
| Job payments | raw.<stream>__job_payments |
The job payments that changed since the last run |
| Job allocations | raw.<stream>__job_allocations |
The job allocations that changed since the last run |
| Job contacts | raw.<stream>__job_contacts |
The job contacts that changed since the last run |
| Job queues | raw.<stream>__job_queues |
The job queues that changed since the last run |
| Clients | raw.<stream>__clients |
The clients that changed since the last run |
| Client contacts | raw.<stream>__client_contacts |
The client contacts that changed since the last run |
| Staff | raw.<stream>__staff |
The staff that changed since the last run |
| Staff clock events | raw.<stream>__staff_time_events |
The staff clock events that changed since the last run |
| Materials and labour rates | raw.<stream>__materials |
The materials and labour rates that changed since the last run |
| Job categories | raw.<stream>__categories |
The job categories that changed since the last run |
| Badges | raw.<stream>__badges |
The badges that changed since the last run |
| Forms | raw.<stream>__forms |
The forms that changed since the last run |
| Form questions | raw.<stream>__form_fields |
The form questions that changed since the last run |
| Form responses | raw.<stream>__form_responses |
The form responses that changed since the last run |
| Assets | raw.<stream>__assets |
The assets that changed since the last run |
| Customer feedback | raw.<stream>__feedback |
The customer feedback that changed since the last run |
| Job admin time | raw.<stream>__job_admin_activities |
The last 60 days again, once a day, so late changes land |
| Tax rates | raw.<stream>__tax_rates |
The whole list, every run |
| Account | raw.<stream>__account |
The whole list, every run |
Jobs, job contacts, clients, client contacts and staff hold people's names, phone numbers, email addresses or home addresses, and the editor says so under each. Untick them if your warehouse shouldn't hold them.
What changed since the last run
The first run reads each list whole. After that, a run asks ServiceM8 for every record changed after a date: the date of the newest change the last run saw, less one day. So each run reads a day or two of changes again. A record read twice is still one row, and one that hasn't changed costs nothing in your warehouse. Reading a little again means a change is never missed, whatever ServiceM8's clock did, including the hour that repeats when daylight saving ends.
Jobs, quotes and invoices
A quote is a job whose status is Quote, and a work order one whose status is Work Order: ServiceM8 keeps them in one list, so they land in one table. ServiceM8 has no separate invoice record either: a job's invoice is its invoice_date, invoice_sent and total_invoice_amount, with its lines (labour included) in job materials and the money received in job payments. Each line and payment names its job in job_uuid.
The schedule and staff time
Job activities are both the bookings on the schedule and the time staff recorded on a job, told apart by activity_was_scheduled and activity_was_recorded. Job allocations are jobs given to someone without a booked time. Staff clock events are each clock on, clock off and lunch break.
Job admin time
ServiceM8 records no time of change for office time logged against a job, so a run can't ask for what changed. Instead, the first run reads all of it, and after that, once a day, the stream reads the last 60 days again. An entry corrected inside those days lands corrected, and one removed is marked _deleted_at. An entry older than that keeps what it last said.
Tax rates and the account
Both are a handful of rows, read whole every run. The account is the ServiceM8 account itself: its timezone_name is the time zone ServiceM8's times are in (with one exception: a form response's timestamp is UTC), and its currency the currency of every amount.
Left out
ServiceM8 also offers these, which a ServiceM8 stream doesn't read yet: job notes, tasks, checklists and job templates, attachments (such as the quote and invoice PDFs), suppliers, locations, allocation windows and security roles.
A member of staff's last known position (lat, lng and geo_timestamp) and the job they are travelling to (navigating_to_job_uuid and its times) never land.
What lands in your warehouse
Every field becomes a column, and the whole record is kept in _record, as for every pull. A few things are worth knowing when you model them:
- Times are the account's own time, with no time zone. ServiceM8 writes its times as the wall-clock time where the account is, so these columns are timestamps without a zone. The
accounttable'stimezone_namesays which zone: in a view,edit_date at time zone 'Australia/Sydney'gives the instant. A time ServiceM8 never set, which it sends as0000-00-00 00:00:00, is empty in its column and kept in_record. - A form response's
timestampis UTC. When a form was completed is the one time ServiceM8 writes in UTC, so that column is a timestamp with a time zone: it already holds the instant. In a view,"timestamp" at time zone 'Australia/Sydney'gives the time on the account's clock, to set beside its other times. A form response'sedit_dateis the account's own time, like every other table's. - Amounts are numbers. ServiceM8 sends money and quantities as text. They land as numbers in
total_invoice_amounton jobs, inquantity,price,cost,displayed_amountanddisplayed_coston job materials, inpriceandcoston materials, inamounton job payments and inamount(a percentage) on tax rates. A job material'spriceandcostare without tax, and itsdisplayed_amount_is_tax_inclusivesays whetherdisplayed_amountincludes it. - Deleted records stay, with
active0. Deleting something in ServiceM8 marks it inactive rather than removing it, and ServiceM8 still lists it, so its row keeps coming in withactive0. Leave those out in a view where you count jobs or revenue. - Ids are ServiceM8's uuids. Every table is keyed by
uuid, and a column ending in_uuidnames a row of another table:company_uuida client,staff_uuida member of staff,category_uuida job category. - Badges are uuids. A job's or client's
badgesholds the uuids of its badges, each a row of badges.
Change a stream
Edit, on the stream's page, changes everything but the account and the warehouse. Something you take off keeps its table, with what it landed. Load everything again on the stream's page reads every list whole on the next run. A large account's first read, or a load from the start, can take several runs, each carrying on from the last.
Remove ServiceM8 data
ServiceM8's terms ask that its data be deleted when you stop using it, or when someone asks. To remove an account's data from sanda:
- Delete each pull on the account: Delete pull, at the foot of the stream's page. Its tables stay in your warehouse until you remove them.
- Disconnect the account under ServiceM8 in Connected, and revoke the key in ServiceM8 under Settings · API Keys.
- Drop what you built from it. Remove the views and modelled tables in Modelling that read the stream's tables.
- Ask sanda support to drop the stream's tables (
raw.<stream>__jobsand the rest), naming the stream. Landing tables can't be dropped from the console.
When something goes wrong
| What you see | What to do |
|---|---|
ServiceM8 refused that API key (401). Check it and type it again. |
The key was mistyped, was revoked in ServiceM8, or is a Plugin API key (one that starts smk-), which ServiceM8's API doesn't accept. Copy it again from Settings · API Keys, or make a new API key there |
| ServiceM8 didn't say which account that API key is for, so nothing was saved. | ServiceM8's answer named no account. Try again later |
| That account is already connected as ServiceM8 · … | The account is in Connected already. Press Type it again on that row to replace its key |
| That API key is for …, not … | A stream keeps the account it reads. Connect the other account as its own, and make a stream on it |
| ServiceM8 stopped accepting the API key for … | The key was revoked or changed in ServiceM8. The stream waits, rather than failing again and again. Make a new key and press Type it again beside the account under Connected |
| ServiceM8's daily allowance for this account is spent, so the run stopped. The next run after ServiceM8 resets it carries on. | Nothing to do: the run kept what it landed. sanda asks ServiceM8 again 60 minutes later, with one request, and the first run after ServiceM8 resets the allowance carries on. If it happens often, run the stream less often or read less |
| … sanda waits until … (UTC) before asking ServiceM8 again, so nothing was read. | A run that started while the allowance rests. Nothing to do: it asked ServiceM8 nothing, and isn't a failure |
| ServiceM8 says this account isn't in good standing and has invoices to pay, so it answers nothing until they are paid. | The Business Owner settles the account's ServiceM8 invoices. The next run after that carries on |
| ServiceM8 didn't let the API key read …, so this run left it out. | Take that list off the stream with Edit, or ask the Business Owner for a key that can read it. The rest of the run carried on |
| A ServiceM8 stream runs at most every 15 minutes … | Choose a slower schedule |
| ServiceM8 asked sanda to slow down, or didn't answer | Nothing to do: the run waits as ServiceM8 asks, then carries on from the last page that landed |
A failed run counts toward the stream pausing itself, as any stream's does. A run that stopped for the daily allowance, or was skipped while it rests, doesn't. See runs.
Limits
- ServiceM8 allows each account 180 requests a minute and 20,000 a day. A run makes at most 2 requests a second, which keeps it inside the minute's allowance, and a stream runs at most every 15 minutes, which keeps its everyday runs well inside the day's. A large account's first read, or Load everything again, can spend more of the day.
- Each request returns up to 1,000 records: ServiceM8 sets the page size.
- One run lands at most 20,000,000 records, so a large account's first read is several runs.
A ServiceM8 stream is billed like any pull: a charge for each run that does its work, and the rows it lands past what your edition includes. See what streams cost.
Something unclear or out of date? Tell us, and we will fix the page.