Customer Contacts API
7 PracBill API endpoints for customer contacts. Base URL https://billing.pracbill.com.au/api.
Add one or more contacts to a customer (legacy endpoint). Accepted per-contact fields: first_name, middle_name, last_name, gender, dob, email, web_password (write-only; stored as a bcrypt hash) (phone, mobile and people_type are NOT accepted here - use `/customer/{cid}/contacts`). Failure description: `no customer found`. The body is raw JSON read via `explode('=')` + `urldecode`: a literal `=` character anywhere in the body truncates it and the JSON then fails to parse, and the legacy `data=` form does not work (the handler checks a misspelt variable, so the part before the first `=` is always used).
POST /{api_key}/customer/contact/add/{cid}
Request body
| Field | Type | Description |
|---|---|---|
people required | array of object |
Responses
200— Contacts added successfullydefault— Failure envelope. The legacy API answers failures with HTTP 200 and `success: false` plus a `description` (e.g. `invalid key`, `Customer not found`).
Get all contacts for a customer (legacy endpoint; `/customer/{cid}/contacts` is richer). Returns the people rows linked to the customer without the audit columns. Failure descriptions: `no customer found`, `no contacts found`.
GET /{api_key}/customer/contact/get/{cid}
Responses
200— Contacts retrieved successfullydefault— Failure envelope. The legacy API answers failures with HTTP 200 and `success: false` plus a `description` (e.g. `invalid key`, `Customer not found`).
Retrieve a specific contact. When the contact does not exist for this customer the call still returns `success: true` with `contact: null`.
GET /{api_key}/customer/{cid}/contact/{contact_id}
Responses
200— Request received successfullydefault— Failure envelope. The legacy API answers failures with HTTP 200 and `success: false` plus a `description` (e.g. `invalid key`, `Customer not found`).
Update a contact (only supplied fields change; `people_type` updates the relationship row). Returns the stored values. A contact that does not belong to the customer returns `success: false` with the (misleading) description `customer not found`. The body is raw JSON read via `explode('=')` + `urldecode`: a literal `=` character anywhere in the body truncates it and the JSON then fails to parse, and the legacy `data=` form does not work (the handler checks a misspelt variable, so the part before the first `=` is always used).
POST /{api_key}/customer/{cid}/contact/{contact_id}
Request body
| Field | Type | Description |
|---|---|---|
first_name | string | |
middle_name | string | |
last_name | string | |
email | string | |
phone | string | |
mobile | string | |
people_type | object | Optional contact type to store on the customer/contact relationship (people_related.people_type). Known values: technical, accounts, site, authorised. Either a string (several values joined with the legacy '^,^' delimiter, e.g. 'technical^,^accounts') or an array of strings (joined with '^,^' by the API). |
Responses
200— Contact updated successfullydefault— Failure envelope. The legacy API answers failures with HTTP 200 and `success: false` plus a `description` (e.g. `invalid key`, `Customer not found`).
Delete a contact (soft delete of the contact and its customer link). Note this destructive operation is a GET.
GET /{api_key}/customer/{cid}/contact/{contact_id}/delete
Responses
200— Contact deleted successfully, or `success: false` when the contact is not found for this customerdefault— Failure envelope. The legacy API answers failures with HTTP 200 and `success: false` plus a `description` (e.g. `invalid key`, `Customer not found`).
Retrieve all (non-deleted) contacts for a customer. Unknown customers return `success: false` / `customer not found`. Values are returned as stored (strings).
GET /{api_key}/customer/{cid}/contacts
Responses
200— Request received successfullydefault— Failure envelope. The legacy API answers failures with HTTP 200 and `success: false` plus a `description` (e.g. `invalid key`, `Customer not found`).
Create a new contact for a customer and link it to the customer. The body is raw JSON read via `explode('=')` + `urldecode`: a literal `=` character anywhere in the body truncates it and the JSON then fails to parse, and the legacy `data=` form does not work (the handler checks a misspelt variable, so the part before the first `=` is always used).
POST /{api_key}/customer/{cid}/contacts
Request body
| Field | Type | Description |
|---|---|---|
first_name | string | |
middle_name | string | |
last_name | string | |
email | string | |
phone | string | |
mobile | string | |
people_type | object | Optional contact type to store on the customer/contact relationship (people_related.people_type). Known values: technical, accounts, site, authorised. Either a string (several values joined with the legacy '^,^' delimiter, e.g. 'technical^,^accounts') or an array of strings (joined with '^,^' by the API). |
Responses
200— Contact created successfullydefault— Failure envelope. The legacy API answers failures with HTTP 200 and `success: false` plus a `description` (e.g. `invalid key`, `Customer not found`).