Services API

52 PracBill API endpoints for services. Base URL https://billing.pracbill.com.au/api.

Legacy route form with the token as the last segment. List the unbilled CDR calls (cdr_billing.invoice = 0) for a service, found by `enid` and/or `service_num`. Note the envelope is {result, message, data} (not `success`); only the `invalid key` failure uses {success:false, description}.

POST /service/unbilled_calls/{api_key}

Request body

FieldTypeDescription
enidintegerEngineering (service) ID
service_numstringService number

Responses

  • 200 — Result envelope (or {success:false,description:'invalid key'})

List a customer's non-deleted service sites (the engineering_sites records shown in the UI as "Service Sites"), ordered by name. Constrained to the token's department via the customer. An unknown/foreign customer returns {success:false, description:'invalid customer'}.

GET /{api_key}/customer/{cid}/service-sites

Responses

  • 200 — Service sites for the customer

Paginated service list

GET /{api_key}/eengineering/get

Legacy alias (typo'd/deprecated URI) of `/{api_key}/services/get`. Lists non-deleted services, newest start date first, 20 per page (department-scoped). Row keys are id, cid, service_num, start_date, servicetype, monthlyfee, date_ended, billing_cycle, contractterm, billing_name, call_rates_id, bundle_id, cost, quantity, parent_id, nbn_avc, service_status. Response is {results, page_number, total_pages} with no success key.

Responses

  • 200 — Page of services. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Paginated service list

GET /{api_key}/eengineering/get/page

Legacy alias (typo'd/deprecated URI) of `/{api_key}/services/get/page`. Lists non-deleted services, newest start date first, 20 per page (department-scoped). Row keys are id, cid, service_num, start_date, servicetype, monthlyfee, date_ended, billing_cycle, contractterm, billing_name, call_rates_id, bundle_id, cost, quantity, parent_id, nbn_avc, service_status. Response is {results, page_number, total_pages} with no success key.

Responses

  • 200 — Page of services. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Paginated service list

GET /{api_key}/eengineering/get/page/{pageNumber}

Legacy alias (typo'd/deprecated URI) of `/{api_key}/services/get/page/{pageNumber}`. Lists non-deleted services, newest start date first, 20 per page (department-scoped). Row keys are id, cid, service_num, start_date, servicetype, monthlyfee, date_ended, billing_cycle, contractterm, billing_name, call_rates_id, bundle_id, cost, quantity, parent_id, nbn_avc, service_status. Response is {results, page_number, total_pages} with no success key.

Responses

  • 200 — Page of services. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Check whether service numbers are active

GET /{api_key}/engineering/activeCheck

Declared as GET but reads a JSON array of service numbers from the request body (plain JSON, not the data= form). Scoped to the token's department. The handler reads a JSON request body even though this is a GET (shape: `ServiceCoreActiveCheckRequest`); OpenAPI 3.0 cannot express a GET body, so it is described here.

Responses

  • 200 — Request received successfully. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Create a service

POST /{api_key}/engineering/add

Create a new service record. service_status, when sent, is validated (see ServiceCreateItem); when omitted the database default 'active' applies.

Request body

FieldTypeDescription
idintegerMaps to engineering.enid. Normally omit. On update this would overwrite the primary key - do not send.
cid requiredintegerCustomer ID. On add, required in practice (used for the price book lookup when monthlyfee is omitted).
service_numstringService number/identifier
start_datestringService start date (written to port_dateacc). Accepted alias of port_dateacc; NOT run through date conversion, so send YYYY-MM-DD. Ignored if port_dateacc is also sent.
port_dateaccstringService start date (database column name, accepted directly). Converted with AppDate::toDBDate() and takes precedence over start_date.
servicetype requiredintegerService type ID (esid). On add, required in practice (used for the price lookup when monthlyfee is omitted).
monthlyfeenumberMonthly fee. On add, when omitted it is taken from the price book, else the service type's list_price. On update, omitting leaves it unchanged; sending the JSON value false triggers the same price book/list price recalculation.
date_endedstringService end date, converted with AppDate::toDBDate()
billing_cyclestringBilling cycle
contracttermintegerContract term in months
billing_namestringBilling name
call_rates_idintegerCall rates group ID (stored in ctgid)
bundle_idintegerService bundle ID (stored in engineering_bundle_id)
costnumberCost price
quantitynumberQuantity (DB default 1)
nbn_avcstringNBN AVC identifier
service_information_dataobjectAdditional service information. Re-encoded to a JSON string for storage.
service_statusstring (active | pending | suspended | pending_disconnection | disconnected | churned)Service lifecycle status. Validated case-sensitively and strictly (type and value) against active, pending, suspended, pending_disconnection, disconnected, churned. Any other value is rejected before anything is written with {"success": false, "description": "invalid service_status"} (HTTP 200). When omitted on add the database default 'active' applies. A 'pending' service is excluded from billing. (Read responses return this as a plain string, not an enum.)
site_idintegerService site to link to (engineering.engineering_site_id). Must be a live site of the service's customer in the token's department, else {"success": false, "description": "invalid site_id"}. Values <= 0 or omitted leave it unchanged.
full_addressstringThe service's primary address as a full-address string, geocoded and stored via saveAddress(). Omit/empty to leave unchanged.
parent_enidintegerParent service ID (note: add accepts parent_enid, not parent_id)

Responses

  • 200 — Service created. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Calculate ETF for several services

POST /{api_key}/engineering/calculateMultipleETF

Body is a JSON array of enids (raw JSON; the 'data=' form does not work). Response is a bare array of calculateETF() results each with an enid.

Request body

Array of:

Responses

  • 200 — ETFs calculated. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Calculate ETF for several services

POST /{api_key}/engineering/calculateMultipleETF/{date}

Body is a JSON array of enids (raw JSON; the 'data=' form does not work). Response is a bare array of calculateETF() results each with an enid.

Request body

Array of:

Responses

  • 200 — ETFs calculated. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Execute ETF for several services

POST /{api_key}/engineering/dMultipleoETF

Legacy alias (typo'd/deprecated URI) of `/{api_key}/engineering/doMultipleETF/{date}`. Body is a JSON array of enids (raw JSON; the 'data=' form does not work). Runs doETF() for each. Response is a bare array of {success, enid}. Code bug: the handler signature is post($token, $enid, $date) so on the dated URIs the :date segment binds to $enid and the date is effectively ignored (today is used).

Request body

Array of:

Responses

  • 200 — ETFs processed. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Delete a service

POST /{api_key}/engineering/delete/{enid}

Soft-deletes the service (EP_Database Delete). Returns success true even if the enid does not exist.

Responses

  • 200 — Service deleted. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Execute ETF for several services

POST /{api_key}/engineering/doMultipleETF/{date}

Body is a JSON array of enids (raw JSON; the 'data=' form does not work). Runs doETF() for each. Response is a bare array of {success, enid}. Code bug: the handler signature is post($token, $enid, $date) so on the dated URIs the :date segment binds to $enid and the date is effectively ignored (today is used).

Request body

Array of:

Responses

  • 200 — ETFs processed. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Get a service

GET /{api_key}/engineering/get/{enid}

Get a specific service record by ID. Does not return an error for an unknown enid: success is true and every field is null.

Responses

  • 200 — Request received successfully. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Get related (child/sibling) services

GET /{api_key}/engineering/getRelatedEngineering/{enid}

Legacy alias (typo'd/deprecated URI) of `/{api_key}/engineering/getRelatedServices/{enid}`. Services whose parent_enid is :enid, plus (when the service itself has a parent) siblings under the same parent. Records contain no nbn_avc/primaryAddress. Note: the sibling query contains a SQL typo (`enid ` without an operator), so on a service that has a parent the sibling lookup may fail (observed in code, not fixed).

Responses

  • 200 — Request received successfully. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Get related (child/sibling) services

GET /{api_key}/engineering/getRelatedServices/{enid}

Services whose parent_enid is :enid, plus (when the service itself has a parent) siblings under the same parent. Records contain no nbn_avc/primaryAddress. Note: the sibling query contains a SQL typo (`enid ` without an operator), so on a service that has a parent the sibling lookup may fail (observed in code, not fixed).

Responses

  • 200 — Request received successfully. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Add a one-time charge item to a service

POST /{api_key}/engineering/item/add

Add a one-time charge item to a service (for additional fees, equipment, installation charges, etc.)

Request body

FieldTypeDescription
pid requiredintegerProduct ID (required) - references inventory table
enidintegerService ID to associate the item with
charge_datestringDate the charge should be applied (YYYY-MM-DD, converted with AppDate::toDBDate())
inc_tax_amountnumberAmount including tax (defaults to the product's)
taxratenumberTax rate percentage (read but overwritten with the rate that applies)
descriptionstringCharge description (defaults to the product's)

Responses

  • 200 — Service item created. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Update a one-time charge item

POST /{api_key}/engineering/item/update/{id}

Update a one-time charge item on a service. Errors: 'no data provided', 'service item id is required', 'no service item found'.

Request body

FieldTypeDescription
pidintegerProduct ID - if supplied, tax and ex-tax amount are recalculated
charge_datestringDate the charge should be applied (YYYY-MM-DD)
inc_tax_amountnumberAmount including tax
taxratenumberTax rate percentage
descriptionstringCharge description

Responses

  • 200 — Service item updated. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Search services

POST /{api_key}/engineering/search

Search for services with flexible criteria. The request body is a JSON **array** of criterion objects. Each criterion has a `field`, a `value`, and an optional `operator` (defaults to `like`). Multiple criteria are combined with AND. Results are automatically scoped to the API token's department. Request body is plain JSON. If no criterion is usable the response is ServiceCoreSearchErrorResponse.

Request body

Array of:

FieldTypeDescription
field requiredstring (id | cid | service_num | servicetype | start_date | monthlyfee | date_ended | billing_name)The field to filter on. API names (id, start_date, call_rates_id, parent_id, locid, site_id, username, service_status ...) are translated to the database column; the raw column names enid, port_dateacc, parent_enid, nbn_loc_id, engineering.cid, engineering.ctgid, engineering.ext_field2 and engineering.engineering_site_id are also accepted. billing_cycle, contractterm, cost and bundle_id are NOT searchable (silently ignored). `active_services` is a special flag that takes no value/operator and limits results to services that have not ended (date_ended null, 0000-00-00, 1970-01-01 or >= today). Unrecognised fields are silently ignored.
valueobjectThe value to compare against. Required for every field except `active_services`. May be a string or number depending on the field.
operatorstring (= | like | < | > | <= | >= | !=)Comparison operator. Defaults to `like` (substring match — the value is wrapped in % wildcards) when omitted. Ignored for `active_services`.

Responses

  • 200 — Search completed. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Update a service

POST /{api_key}/engineering/update/{enid}

Update an existing service record. Only supplied keys are written. service_status, when sent, is validated (see ServiceCoreUpdateItem). Changing servicetype without sending monthlyfee recalculates monthlyfee from the customer's price book for the new type, falling back to its list_price; an explicit monthlyfee is never replaced. Errors: 'no record found to update', 'no data provided', 'invalid service_status', 'invalid site_id'.

Request body

FieldTypeDescription
idintegerMaps to engineering.enid. Normally omit. On update this would overwrite the primary key - do not send.
cidintegerCustomer ID. When sent alongside a service type change that recalculates monthlyfee, this customer's price book is used; otherwise the service's stored customer is used.
service_numstringService number/identifier
start_datestringService start date (written to port_dateacc). Accepted alias of port_dateacc; NOT run through date conversion, so send YYYY-MM-DD. Ignored if port_dateacc is also sent.
port_dateaccstringService start date (database column name, accepted directly). Converted with AppDate::toDBDate() and takes precedence over start_date.
servicetypeintegerService type ID (esid). Changing it without sending monthlyfee recalculates monthlyfee (see monthlyfee).
monthlyfeenumberOptional monthly fee. When supplied (including 0) it is written as-is. When omitted and servicetype is sent with a value different from the stored service type, the fee is recalculated for the target service type from the customer's applicable price book (final_total), falling back to the service type's list_price if no price-book entry applies. When omitted and the service type is unchanged, the stored fee is left unchanged. Sending the JSON value false forces the same recalculation for the target (or stored) service type.
date_endedstringService end date, converted with AppDate::toDBDate()
billing_cyclestringBilling cycle
contracttermintegerContract term in months
billing_namestringBilling name
call_rates_idintegerCall rates group ID (stored in ctgid)
bundle_idintegerService bundle ID (stored in engineering_bundle_id)
costnumberCost price
quantitynumberQuantity (DB default 1)
nbn_avcstringNBN AVC identifier
service_information_dataobjectAdditional service information. Re-encoded to a JSON string for storage.
service_statusstring (active | pending | suspended | pending_disconnection | disconnected | churned)Service lifecycle status. Validated case-sensitively and strictly (type and value) against active, pending, suspended, pending_disconnection, disconnected, churned. Any other value is rejected before anything is written with {"success": false, "description": "invalid service_status"} (HTTP 200). When omitted on update the stored status is unchanged. A 'pending' service is excluded from billing. (Read responses return this as a plain string, not an enum.)
site_idintegerService site to link to (engineering.engineering_site_id). Must be a live site of the service's customer in the token's department, else {"success": false, "description": "invalid site_id"}. Values <= 0 or omitted leave it unchanged.
full_addressstringThe service's primary address as a full-address string, geocoded and stored via saveAddress(). Omit/empty to leave unchanged.
locidstringNBN Location ID, stored in nbn_loc_id (same name returned by get). Non-empty only; omit/empty leaves it unchanged.
primaryAddressstringPreferred name for the primary address (as returned by get); takes precedence over full_address. Omit/empty leaves unchanged.

Responses

  • 200 — Service updated. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Calculate Early Termination Fee

GET /{api_key}/engineering/{enid}/calculateETF

Calculate Early Termination Fee (ETF) for a service as at :date (default today). Response is the bare calculateETF() result (no success key).

Responses

  • 200 — ETF calculated. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Calculate Early Termination Fee

GET /{api_key}/engineering/{enid}/calculateETF/{date}

Calculate Early Termination Fee (ETF) for a service as at :date (default today). Response is the bare calculateETF() result (no success key).

Responses

  • 200 — ETF calculated. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Execute Early Termination Fee

POST /{api_key}/engineering/{enid}/doETF

Execute ETF: if the ETF amount is > 0 an engineering_iitems charge is created (description from the department's etf_pid product, else 'Early Termination Fee'), and the service's date_ended is set to the ETF date. Always returns {success: true}.

Responses

  • 200 — ETF processed. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Execute Early Termination Fee

POST /{api_key}/engineering/{enid}/doETF/{date}

Execute ETF: if the ETF amount is > 0 an engineering_iitems charge is created (description from the department's etf_pid product, else 'Early Termination Fee'), and the service's date_ended is set to the ETF date. Always returns {success: true}.

Responses

  • 200 — ETF processed. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Create a service site. cid must be a customer in the token's department (`invalid cid`); name must not be blank (`name is required`); an empty body gives `no data provided`.

POST /{api_key}/service-sites/add

Request body

FieldTypeDescription
cid requiredintegerCustomer ID (must be a customer in the token's department)
name requiredstringSite name (trimmed; must not be blank)
sidstringSite reference (DB field sitesid); defaults to empty
domain_namestringSite domain (DB field domainname); defaults to empty

Responses

  • 200 — Service site created ({success:true,id}) or an error ({success:false,description})

Soft-delete a service site (deleted = 1; never a hard delete). Fails (`site not found`) for a nonexistent/deleted/cross-department site. Success returns only {success:true}.

POST /{api_key}/service-sites/delete/{id}

Responses

  • 200 — Service site deleted

Fetch a single service site. Fails ({success:false, description:'site not found'}) when the site does not exist, is deleted, or belongs to a customer outside the token's department.

GET /{api_key}/service-sites/get/{id}

Responses

  • 200 — The service site

Update a service site (name/sid/domain_name, and optionally cid to another customer in the same department). Fails for a nonexistent/deleted/cross-department site (`site not found`), a blank name (`name cannot be blank`) or an invalid cid (`invalid cid`). Success returns description `service site updated`.

POST /{api_key}/service-sites/update/{id}

Request body

FieldTypeDescription
cidintegerReassign to another customer in the same department
namestringSite name (trimmed; blank is rejected with `name cannot be blank`)
sidstringSite reference (DB field sitesid)
domain_namestringSite domain (DB field domainname)

Responses

  • 200 — Service site updated

List the unbilled CDR calls (cdr_billing.invoice = 0) for a service, found by `enid` and/or `service_num`. Note the envelope is {result, message, data} (not `success`); only the `invalid key` failure uses {success:false, description}.

POST /{api_key}/service/unbilled_calls

Request body

FieldTypeDescription
enidintegerEngineering (service) ID
service_numstringService number

Responses

  • 200 — Result envelope (or {success:false,description:'invalid key'})

Check whether service numbers are active

GET /{api_key}/services/activeCheck

Declared as GET but reads a JSON array of service numbers from the request body (plain JSON, not the data= form). Scoped to the token's department. The handler reads a JSON request body even though this is a GET (shape: `ServiceCoreActiveCheckRequest`); OpenAPI 3.0 cannot express a GET body, so it is described here.

Responses

  • 200 — Request received successfully. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Create a service

POST /{api_key}/services/add

Create a new service record. service_status, when sent, is validated (see ServiceCreateItem); when omitted the database default 'active' applies.

Request body

FieldTypeDescription
idintegerMaps to engineering.enid. Normally omit. On update this would overwrite the primary key - do not send.
cid requiredintegerCustomer ID. On add, required in practice (used for the price book lookup when monthlyfee is omitted).
service_numstringService number/identifier
start_datestringService start date (written to port_dateacc). Accepted alias of port_dateacc; NOT run through date conversion, so send YYYY-MM-DD. Ignored if port_dateacc is also sent.
port_dateaccstringService start date (database column name, accepted directly). Converted with AppDate::toDBDate() and takes precedence over start_date.
servicetype requiredintegerService type ID (esid). On add, required in practice (used for the price lookup when monthlyfee is omitted).
monthlyfeenumberMonthly fee. On add, when omitted it is taken from the price book, else the service type's list_price. On update, omitting leaves it unchanged; sending the JSON value false triggers the same price book/list price recalculation.
date_endedstringService end date, converted with AppDate::toDBDate()
billing_cyclestringBilling cycle
contracttermintegerContract term in months
billing_namestringBilling name
call_rates_idintegerCall rates group ID (stored in ctgid)
bundle_idintegerService bundle ID (stored in engineering_bundle_id)
costnumberCost price
quantitynumberQuantity (DB default 1)
nbn_avcstringNBN AVC identifier
service_information_dataobjectAdditional service information. Re-encoded to a JSON string for storage.
service_statusstring (active | pending | suspended | pending_disconnection | disconnected | churned)Service lifecycle status. Validated case-sensitively and strictly (type and value) against active, pending, suspended, pending_disconnection, disconnected, churned. Any other value is rejected before anything is written with {"success": false, "description": "invalid service_status"} (HTTP 200). When omitted on add the database default 'active' applies. A 'pending' service is excluded from billing. (Read responses return this as a plain string, not an enum.)
site_idintegerService site to link to (engineering.engineering_site_id). Must be a live site of the service's customer in the token's department, else {"success": false, "description": "invalid site_id"}. Values <= 0 or omitted leave it unchanged.
full_addressstringThe service's primary address as a full-address string, geocoded and stored via saveAddress(). Omit/empty to leave unchanged.
parent_enidintegerParent service ID (note: add accepts parent_enid, not parent_id)

Responses

  • 200 — Service created. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Calculate ETF for several services

POST /{api_key}/services/calculateMultipleETF

Body is a JSON array of enids (raw JSON; the 'data=' form does not work). Response is a bare array of calculateETF() results each with an enid.

Request body

Array of:

Responses

  • 200 — ETFs calculated. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Calculate ETF for several services

POST /{api_key}/services/calculateMultipleETF/{date}

Body is a JSON array of enids (raw JSON; the 'data=' form does not work). Response is a bare array of calculateETF() results each with an enid.

Request body

Array of:

Responses

  • 200 — ETFs calculated. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Execute ETF for several services

POST /{api_key}/services/dMultipleoETF

Legacy alias (typo'd/deprecated URI) of `/{api_key}/engineering/doMultipleETF/{date}`. Body is a JSON array of enids (raw JSON; the 'data=' form does not work). Runs doETF() for each. Response is a bare array of {success, enid}. Code bug: the handler signature is post($token, $enid, $date) so on the dated URIs the :date segment binds to $enid and the date is effectively ignored (today is used).

Request body

Array of:

Responses

  • 200 — ETFs processed. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Execute ETF for several services

POST /{api_key}/services/dMultipleoETF/{date}

Legacy alias (typo'd/deprecated URI) of `/{api_key}/engineering/doMultipleETF/{date}`. Body is a JSON array of enids (raw JSON; the 'data=' form does not work). Runs doETF() for each. Response is a bare array of {success, enid}. Code bug: the handler signature is post($token, $enid, $date) so on the dated URIs the :date segment binds to $enid and the date is effectively ignored (today is used).

Request body

Array of:

Responses

  • 200 — ETFs processed. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Delete a service

POST /{api_key}/services/delete/{enid}

Soft-deletes the service (EP_Database Delete). Returns success true even if the enid does not exist.

Responses

  • 200 — Service deleted. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Paginated service list

GET /{api_key}/services/get

Lists non-deleted services, newest start date first, 20 per page (department-scoped). Row keys are id, cid, service_num, start_date, servicetype, monthlyfee, date_ended, billing_cycle, contractterm, billing_name, call_rates_id, bundle_id, cost, quantity, parent_id, nbn_avc, service_status. Response is {results, page_number, total_pages} with no success key.

Responses

  • 200 — Page of services. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Calculate the daily cost for an active service (monthlyfee divided by days in the current month, times quantity). Failures: `{n} not found`.

GET /{api_key}/services/get/monthlyCostByServiceNumber/daily/{service_num}

Responses

  • 200 — Daily cost calculated successfully

Calculate the pro-rata monthly cost for a service that started on the given date (calculated from monthlyfee to the end of that month). Failures: `{n} not found as starting on {date}`.

GET /{api_key}/services/get/monthlyCostByServiceNumber/proRata/{date}/{service_num}

Responses

  • 200 — Pro-rata monthly cost calculated successfully

Get the actual monthly cost charged for a service in the month of the given date (from non-void invoice data for that customer dated between the date and the end of its month). Failures are HTTP 200 with {success:false, description}: `{n} not found`, `Unable to Find invoice for customer: ...`, `{n} was not billed on {date}`.

GET /{api_key}/services/get/monthlyCostByServiceNumber/{date}/{service_num}

Responses

  • 200 — Monthly cost retrieved successfully

Paginated service list

GET /{api_key}/services/get/page

Lists non-deleted services, newest start date first, 20 per page (department-scoped). Row keys are id, cid, service_num, start_date, servicetype, monthlyfee, date_ended, billing_cycle, contractterm, billing_name, call_rates_id, bundle_id, cost, quantity, parent_id, nbn_avc, service_status. Response is {results, page_number, total_pages} with no success key.

Responses

  • 200 — Page of services. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Paginated service list

GET /{api_key}/services/get/page/{pageNumber}

Lists non-deleted services, newest start date first, 20 per page (department-scoped). Row keys are id, cid, service_num, start_date, servicetype, monthlyfee, date_ended, billing_cycle, contractterm, billing_name, call_rates_id, bundle_id, cost, quantity, parent_id, nbn_avc, service_status. Response is {results, page_number, total_pages} with no success key.

Responses

  • 200 — Page of services. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Get a service

GET /{api_key}/services/get/{enid}

Get a specific service record by ID. Does not return an error for an unknown enid: success is true and every field is null.

Responses

  • 200 — Request received successfully. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Get related (child/sibling) services

GET /{api_key}/services/getRelatedServices/{enid}

Services whose parent_enid is :enid, plus (when the service itself has a parent) siblings under the same parent. Records contain no nbn_avc/primaryAddress. Note: the sibling query contains a SQL typo (`enid ` without an operator), so on a service that has a parent the sibling lookup may fail (observed in code, not fixed).

Responses

  • 200 — Request received successfully. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

AVC Transfer Qualification Check

POST /{api_key}/services/qualify/avc-check

Verify that an AVC ID matches a given location before submitting a transfer order. Parameters may be sent in the query string or as a form-encoded body. Validation and carrier failures are {success:false, description} (`missing location_id`, `invalid location_id format`, `missing avcid`, `invalid avcid format`, `invalid service_type`, or the carrier error message).

Responses

  • 200 — AVC check result

Search services

POST /{api_key}/services/search

Search for services with flexible criteria. The request body is a JSON **array** of criterion objects. Each criterion has a `field`, a `value`, and an optional `operator` (defaults to `like`). Multiple criteria are combined with AND. Results are automatically scoped to the API token's department. Request body is plain JSON. If no criterion is usable the response is ServiceCoreSearchErrorResponse.

Request body

Array of:

FieldTypeDescription
field requiredstring (id | cid | service_num | servicetype | start_date | monthlyfee | date_ended | billing_name)The field to filter on. API names (id, start_date, call_rates_id, parent_id, locid, site_id, username, service_status ...) are translated to the database column; the raw column names enid, port_dateacc, parent_enid, nbn_loc_id, engineering.cid, engineering.ctgid, engineering.ext_field2 and engineering.engineering_site_id are also accepted. billing_cycle, contractterm, cost and bundle_id are NOT searchable (silently ignored). `active_services` is a special flag that takes no value/operator and limits results to services that have not ended (date_ended null, 0000-00-00, 1970-01-01 or >= today). Unrecognised fields are silently ignored.
valueobjectThe value to compare against. Required for every field except `active_services`. May be a string or number depending on the field.
operatorstring (= | like | < | > | <= | >= | !=)Comparison operator. Defaults to `like` (substring match — the value is wrapped in % wildcards) when omitted. Ignored for `active_services`.

Responses

  • 200 — Search completed. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Alias of /{api_key}/customer/{cid}/service-sites. List a customer's non-deleted service sites (the engineering_sites records shown in the UI as "Service Sites"), ordered by name. Constrained to the token's department via the customer. An unknown/foreign customer returns {success:false, description:'invalid customer'}.

GET /{api_key}/services/sites/customer/{cid}

Responses

  • 200 — Service sites for the customer

Update a service

POST /{api_key}/services/update/{enid}

Update an existing service record. Only supplied keys are written. service_status, when sent, is validated (see ServiceCoreUpdateItem). Changing servicetype without sending monthlyfee recalculates monthlyfee from the customer's price book for the new type, falling back to its list_price; an explicit monthlyfee is never replaced. Errors: 'no record found to update', 'no data provided', 'invalid service_status', 'invalid site_id'.

Request body

FieldTypeDescription
idintegerMaps to engineering.enid. Normally omit. On update this would overwrite the primary key - do not send.
cidintegerCustomer ID. When sent alongside a service type change that recalculates monthlyfee, this customer's price book is used; otherwise the service's stored customer is used.
service_numstringService number/identifier
start_datestringService start date (written to port_dateacc). Accepted alias of port_dateacc; NOT run through date conversion, so send YYYY-MM-DD. Ignored if port_dateacc is also sent.
port_dateaccstringService start date (database column name, accepted directly). Converted with AppDate::toDBDate() and takes precedence over start_date.
servicetypeintegerService type ID (esid). Changing it without sending monthlyfee recalculates monthlyfee (see monthlyfee).
monthlyfeenumberOptional monthly fee. When supplied (including 0) it is written as-is. When omitted and servicetype is sent with a value different from the stored service type, the fee is recalculated for the target service type from the customer's applicable price book (final_total), falling back to the service type's list_price if no price-book entry applies. When omitted and the service type is unchanged, the stored fee is left unchanged. Sending the JSON value false forces the same recalculation for the target (or stored) service type.
date_endedstringService end date, converted with AppDate::toDBDate()
billing_cyclestringBilling cycle
contracttermintegerContract term in months
billing_namestringBilling name
call_rates_idintegerCall rates group ID (stored in ctgid)
bundle_idintegerService bundle ID (stored in engineering_bundle_id)
costnumberCost price
quantitynumberQuantity (DB default 1)
nbn_avcstringNBN AVC identifier
service_information_dataobjectAdditional service information. Re-encoded to a JSON string for storage.
service_statusstring (active | pending | suspended | pending_disconnection | disconnected | churned)Service lifecycle status. Validated case-sensitively and strictly (type and value) against active, pending, suspended, pending_disconnection, disconnected, churned. Any other value is rejected before anything is written with {"success": false, "description": "invalid service_status"} (HTTP 200). When omitted on update the stored status is unchanged. A 'pending' service is excluded from billing. (Read responses return this as a plain string, not an enum.)
site_idintegerService site to link to (engineering.engineering_site_id). Must be a live site of the service's customer in the token's department, else {"success": false, "description": "invalid site_id"}. Values <= 0 or omitted leave it unchanged.
full_addressstringThe service's primary address as a full-address string, geocoded and stored via saveAddress(). Omit/empty to leave unchanged.
locidstringNBN Location ID, stored in nbn_loc_id (same name returned by get). Non-empty only; omit/empty leaves it unchanged.
primaryAddressstringPreferred name for the primary address (as returned by get); takes precedence over full_address. Omit/empty leaves unchanged.

Responses

  • 200 — Service updated. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Calculate Early Termination Fee

GET /{api_key}/services/{enid}/calculateETF

Calculate Early Termination Fee (ETF) for a service as at :date (default today). Response is the bare calculateETF() result (no success key).

Responses

  • 200 — ETF calculated. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Calculate Early Termination Fee

GET /{api_key}/services/{enid}/calculateETF/{date}

Calculate Early Termination Fee (ETF) for a service as at :date (default today). Response is the bare calculateETF() result (no success key).

Responses

  • 200 — ETF calculated. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Execute Early Termination Fee

POST /{api_key}/services/{enid}/doETF

Execute ETF: if the ETF amount is > 0 an engineering_iitems charge is created (description from the department's etf_pid product, else 'Early Termination Fee'), and the service's date_ended is set to the ETF date. Always returns {success: true}.

Responses

  • 200 — ETF processed. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

Execute Early Termination Fee

POST /{api_key}/services/{enid}/doETF/{date}

Execute ETF: if the ETF amount is > 0 an engineering_iitems charge is created (description from the department's etf_pid product, else 'Early Termination Fee'), and the service's date_ended is set to the ETF date. Always returns {success: true}.

Responses

  • 200 — ETF processed. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

End a service by number

POST /{api_key}/services/{number}/endService

Sets date_ended on the active service(s) (no end date, 0000-00-00 or future end date) whose service_num equals {number}. All matching rows are updated. Error 'number not found' if none match; 'no data provided' for an empty body.

Request body

FieldTypeDescription
datestringEnd date. Used only when strictly after today; otherwise (or when omitted) the service is ended today.

Responses

  • 200 — Service ended. Errors are returned with HTTP 200 as {"success": false, "description": ...} (ErrorResponse), e.g. 'invalid key'.

← All API groups