Custom Fields API: `DELETE /custom_fields_1.0` returns `"Invalid UUID"` for valid UUIDs (OAuth 2.0)

Hi ServiceM8 team — hoping someone from your end can pick this up. There are two existing community threads reporting exactly this issue, both with zero replies from ServiceM8:

I’m hitting the same wall in 2026 while building a public OAuth 2.0 add-on. List and Create work. Delete is fully broken — the API rejects every request shape with errorCode: 100, "Invalid UUID", even though the UUID is the one the API itself just returned from GET.

Reproduction

A single OAuth 2.0 access token used for all requests below. Scope: manage_jobs manage_customers.

1. Create a Job custom field

curl -X POST "https://api.servicem8.com/custom_fields_1.0" \
  -H "Authorization: Bearer <ACCESS_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"object_name":"Job","field_name":"test","display_name":"TEST","field_type":"Text","max_length":50}'

Response: {"errorCode":0,"message":"OK","UUID":"5671be47-9ebb-49d3-bb9b-242077a141fb"} — works.

2. List custom fields

curl "https://api.servicem8.com/custom_fields_1.0" \
  -H "Authorization: Bearer <ACCESS_TOKEN>" \
  -H "Accept: application/json"

Response (HTTP 200):

[{
  "uuid": "5671be47-9ebb-49d3-bb9b-242077a141fb",
  "object": "job",
  "display_name": "TEST",
  "field_name": "test",
  "field_type": "Text",
  "is_unique": 0,
  "sort_priority": 0,
  "max_length": 50
}]

So the API confirms the field exists with that exact UUID.

3. Try to delete that exact UUID — every shape fails

I tried every reasonable interpretation of the docs (https://developer.servicem8.com/reference/delete_custom_field) and standard ServiceM8 REST conventions:

# Request shape Result
1 DELETE /custom_fields_1.0 body UUID=<uuid> (form-urlencoded — exactly what your docs / API Explorer show) 400 {"errorCode":100,"message":"Invalid UUID"}
2 Same as 1, but uuid=<uuid> (lowercase key) 400 Invalid UUID
3 DELETE /custom_fields_1.0 JSON body {"UUID":"<uuid>"} 400 Invalid UUID
4 DELETE /custom_fields_1.0?UUID=<uuid> (query string) 400 Invalid UUID
5 DELETE /custom_fields_1.0/<uuid> (path style, like /api_1.0/job/<uuid>.json) 400 Invalid UUID
6 POST /custom_fields_1.0 with header X-HTTP-Method-Override: DELETE 400 {"errorCode":110,"message":"expected valid JSON in request body"} (proves POST is reachable on the same path)
7 DELETE with --data-urlencode "UUID=<uuid>" (matches your API Explorer’s curl exactly) 400 Invalid UUID

The exact request from your own API Explorer page also fails:

curl --request DELETE \
     --url https://api.servicem8.com/custom_fields_1.0 \
     --header 'Authorization: Bearer <ACCESS_TOKEN>' \
     --header 'accept: application/json' \
     --header 'content-type: application/x-www-form-urlencoded' \
     --data UUID=5671be47-9ebb-49d3-bb9b-242077a141fb

HTTP 400 {"errorCode":100,"message":"Invalid UUID"}.

Response headers indicate the 400 is generated by ServiceM8 (not CloudFront / not a CORS preflight artefact):

HTTP/1.1 400 Bad Request
Content-Type: application/json
Server: nginx
X-Cache: Error from cloudfront

What I’d like to know

  1. Is DELETE /custom_fields_1.0 actually wired up for OAuth 2.0 public applications? Given the 2018 and 2023 reports above, it looks like this endpoint has been broken for at least 8 years.
  2. If it does work, what’s the correct request shape? None of the seven variants above match. The published docs say body-style with UUID key, which is what I send and what fails.
  3. Is there a hidden scope or capability flag (something analogous to manage_custom_fields) that public apps need to include in their OAuth scope to be allowed to delete? Your published scope table doesn’t list a custom-fields scope; we’re using manage_jobs manage_customers because the fields are on Job/Company.
  4. If there’s no fix coming, please update the Custom Fields API docs to clearly state that DELETE is not supported via OAuth 2.0, so developers stop spending hours debugging a working request against a non-functional endpoint.

Documentation, scope tables, OpenAPI spec, and the in-product API Explorer all imply this should work. It doesn’t, and it hasn’t for a very long time. Could we please get a real answer this time?

Thanks.

Hi David,

We’ve investigated this and there’s currently a mismatch between the docs and the live endpoint: the docs show the form field name as UUID (uppercase), but the API is presently only accepting uuid (lowercase).

If you switch your DELETE to send uuid (lowercase) in an application/x-www-form-urlencoded body, it should go through, for example:

curl --request DELETE \
  --url https://api.servicem8.com/custom_fields_1.0 \
  --header 'Authorization: Bearer <ACCESS_TOKEN>' \
  --header 'accept: application/json' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data uuid=5671be47-9ebb-49d3-bb9b-242077a141fb

We’re going to update the docs and resolve this inconsistency.

Thanks,
Cody

1 Like

Thanks Cody, I tested this and it works :+1: