TITLE: How to read the staff member allocated to a job (booking/schedule) via API — jobactivity.json returns 403 insufficient_scope with a Full Access key
Hi all,
I’m building a Make.com integration that routes jobs to the correct staff member/contractor based on who a job is allocated to in ServiceM8. I’ve hit a wall getting the assignment data and would appreciate guidance.
WORKFLOW
Our admin creates jobs with Job Status = Quote and allocates them to a staff member via a booking. In the job’s UI this shows under “Upcoming Bookings” as e.g. “Allocated to [Staff Name] on [date]”. We do NOT use Queues for assignment — allocation is done as a staff booking/schedule.
WHAT I’VE CONFIRMED VIA THE API
GET /api_1.0/job/{uuid}.json returns the full job record successfully (200), including customer, description, status, address, etc.
However, the job record does NOT contain the allocated staff member. The relevant fields are all empty:
queue_uuid: (empty)
queue_assigned_staff_uuid: (empty)
The only staff UUID present is created_by_staff_uuid (the admin who created the job), not the person the job is allocated to.
So the “Allocated to [Staff]” booking clearly lives outside the job record.
GET /api_1.0/jobactivity.json returns: 403 insufficient_scope
This happens even though the connection uses a Full Access API key.
QUESTIONS
Which API endpoint exposes the staff member allocated to a job via a booking/schedule (the “Upcoming Bookings / Allocated to [Staff]” data)? Is jobactivity the correct resource, or is it schedule/booking/roster or something else?
Why would /api_1.0/jobactivity.json return 403 insufficient_scope for a Full Access API key? Is there an additional scope/permission that must be enabled for job activity or scheduling data, and where is that configured?
Is there a recommended way to reliably determine “which staff/contractor is this job allocated to” when allocation is done as a booking (not a queue)?
Ideally I’d like to: detect when a job is allocated to a staff member, read that staff member’s UUID (and email), and route the job accordingly.
Any pointers on the correct endpoint and the scope/permission needed to read it would be a huge help.
If you are using the native make.com servicem8 module, it does not have the required permissions, this would be something you have to ask make.com. to change, so far they have not changed it, alternative is use the http module and use servicem8 api key authentication which has access to all scopes. And correct “jobactivity” is the endpoint to retreive schedules
I checked the request corresponding to your test. It was authenticated using Make’s native ServiceM8 OAuth connection, rather than an account API key. That connection does not currently have the scheduling or staff permissions required, which is why job requests succeed while the scheduling request returns insufficient_scope.
For the booking in your example, use:
GET /api_1.0/joballocation.json?$filter=job_uuid eq '<JOB_UUID>' and active eq 1
The returned record contains staff_uuid. You can then retrieve the staff member with:
GET /api_1.0/staff/<STAFF_UUID>.json
Fixed-time calendar bookings are available from jobactivity.json; flexible or date-based allocations are available from joballocation.json. An integration supporting both should check both resources.
In Make, the current workaround is to use its HTTP module and send a ServiceM8 API key in the X-API-Key header. A Read Only key is sufficient for these requests. The native Make connector would need Make to add the read_schedule and read_staff permissions.
For scheduled bookings, you’ll want to read the schedule records rather than the job record. The schedule endpoint is GET /api_1.0/jobactivity.json, and JobActivity records include job_uuid, staff_uuid, start_date, end_date, and activity_was_scheduled fields, so that’s the right place to look for a staff member assigned to a scheduled activity.
If your workflow is using Job Allocations or booking windows instead, the companion endpoint is GET /api_1.0/joballocation.json, and JobAllocation records include job_uuid, staff_uuid, allocation_date, and allocation_window_uuid.
A practical pattern is to filter by the job UUID and active records, for example GET /api_1.0/jobactivity.json?$filter=job_uuid eq 'JOB_UUID' and active eq 1, then use the returned staff_uuid.
To get the staff member’s email after that, call GET /api_1.0/staff/{uuid}.json or GET /api_1.0/staff.json, as the Staff schema includes both uuid and email.
On the 403, jobactivity and joballocation require the read_schedule OAuth scope for read access, or manage_schedule for full schedule access. If you’re using a private API key, the key needs to be sent in the X-API-Key header.
So if Make is using OAuth, reconnecting with read_schedule or manage_schedule should sort the insufficient scope error. If it’s definitely sending a ServiceM8 API key in the X-API-Key header and still getting 403, email support@servicem8.com with the endpoint and timestamp so we can check the connection privately.
Michael’s on the right track: for a normal scheduled booking, use the Job Activity endpoint and read the staff_uuid on the activity record. Job Activity records also include the related job_uuid, start_date, end_date, and activity_was_scheduled fields.
For Job Allocations specifically, use the Job Allocation endpoint instead, as that record also includes the related job_uuid and the allocated staff_uuid.
Both /jobactivity.json and /joballocation.json support filtering, so you can query by the job UUID rather than reading every record, for example using the API filter syntax with job_uuid eq '...'.
For the 403, the docs list read_schedule as the OAuth scope required for reading Job Activity and Job Allocation records, and manage_schedule as the full-access scope for those endpoints.
If you’re using a direct API key rather than OAuth, the API key needs to be sent in the X-API-Key header, and the endpoint docs list API key authentication as supported for Job Activity and Job Allocation requests.
To get the staff member’s email after you have the staff_uuid, retrieve that staff member via /staff/{uuid}.json, which returns fields including first, last, email, and uuid.
So the usual flow is: filter jobactivity.json by job_uuid, use the returned staff_uuid, then retrieve /staff/{staff_uuid}.json if you need the staff email.