We integrate with ServiceM8 via OAuth (manage_customer_contacts scope) to auto-create site companies (Use Sites / parent_company_uuid) and add a Property Owner contact from work-order data when a new site is created.
This has recently changed
Expected behaviour
When we POST to companycontact.json with:
{
"company_uuid": "<new-site-uuid>",
"first": "Owner Test",
"type": "Property Owner",
"is_primary_contact": "0"
}
…we expect the stored contact to have type: "Property Owner" and is_primary_contact: "0".
Actual behaviour
On a newly created site with no existing company contacts, ServiceM8 stores the contact as:
{
"type": "BILLING",
"is_primary_contact": "1",
"first": "Owner Test",
"last": ""
}
This happens even when we explicitly send type: "Property Owner" and is_primary_contact: "0". The API returns 200 / { "errorCode": 0, "message": "OK" }, but the created record is coerced to primary BILLING.
Reproduction (confirmed 18 Jun 2026)
- Create a new site company:
POST /api_1.0/company.json
{
"active": 1,
"name": "Test Site Address",
"address": "123 Test St",
"parent_company_uuid": "<parent-company-uuid>"
}
POST Property Owner as the first contact on that site:
POST /api_1.0/companycontact.json
{
"company_uuid": "<company-uuid>",
"first": "Owner Test 2",
"type": "Property Owner",
"is_primary_contact": "0"
}
- GET contacts:
GET /api_1.0/companycontact.json?$filter=company_uuid eq ‘<company-uuid’ and active eq 1
Result: type: "BILLING", is_primary_contact: "1" — not Property Owner.
Earlier test (without is_primary_contact)
Same outcome on another fresh site (<company-uuid>): sent type: "Property Owner" only → stored as BILLING + is_primary_contact: "1".
When it does work
If the site already has other contacts, a Property Owner POST with is_primary_contact: "0" is stored correctly as type: "Property Owner".
What we ruled out on our side
- We are not sending
type: "BILLING"for the owner — only"Property Owner". - Our template does not map owner name into job billing contact fields (
billingContactFirstNameis empty). - Job contacts (
jobcontact.json) are separate; on our test job only JOB + Property Manager were created — the owner does not appear onjobcontact.json. - The incorrect
BILLINGrow appears oncompanycontact.jsonfor the sitecompany_uuid, timestamped at site-creation time (before job contacts).
Impact
Client look for Property Owner on site contacts in the ServiceM8 UI. The owner name appears under BILLING instead, so it looks like the Property Owner was never created. c the When the Client billing attention is set to “Property Owner, C/- Company Name” it causes it t So not have the company name
Questions for ServiceM8
- Is it by design that the first
companycontacton a new site is always forced totype: "BILLING"andis_primary_contact: "1", regardless of thetypeandis_primary_contactvalues in the POST body?
And did logic change recently - What is the supported API pattern to create a Property Owner contact as the first (or only) contact on a newly created site company?
- Should we use a different
typevalue, a two-step create-then-update (PUT), or always seed another contact first? - Is this behaviour documented anywhere in the API reference for
companycontact.json?
Environment
- API:
https://api.servicem8.com/api_1.0/ - Auth: OAuth 2.0 (integration app) with customer contact permissions
- Use case: Sites add-on enabled, site companies under a parent agency/head-office company
Happy to provide additional request/response logs (with credentials redacted) if helpful.
Thanks.