Service order time

Hours logged against a service order (an order with ordertype service). Hours are not order lines: they become lines only when billed, at which point status becomes billed and the record is frozen.

The object#

FieldTypeDescription
idread-onlyintegerNolaPro id.
employeeidintegerEmployeeid. Id only - premployee is read-only or has no code key.
vendoridintegerReference to vendors, by id. Write either this or vendor.
vendorstring(30)Code for the referenced vendor, instead of the id.
orderedinteger1 marks pre-ordered hours - time sold in advance rather than actual worked time.
technamestring(50)Name of the technician who worked the time, as entered.
hoursqtystring(2dp)Quantity, 2 decimal places, as a string. Stored as decimal(2dp).
startdatetimestringWhen the work started.
enddatetimestringWhen the work ended.
ratemoneystring(4dp)Stored as decimal(10,4).
totalpricemoneystring(4dp)Stored as decimal(10,4).
totalcostmoneystring(4dp)Stored as decimal(10,4).
worktypeidintegerReference to worktypes, by id. Write either this or worktype.
worktypestring(100)Code for the referenced worktype, instead of the id.
worksubtypeidintegerWorksubtypeid. Id only.
notestextNotes. Stored as text, no practical length limit.
entrydatestringWhen the record was created.
cancelbooleanCancelled. Always a boolean on the wire, whatever integer width the column uses (D23).
lastchangedateread-onlystringLast modification. Drives modifiedsince.
internal_commenttextInternal_comment. Stored as text, no practical length limit.
costratemoneystring(4dp)Stored as decimal(10,4).
statusread-onlyinteger0 = zero-hour placeholder (never bills), 1 = ready to bill (set automatically the moment hours are non-zero - there is no approval step), 2 = billed (an order line exists for it; the entry refuses PATCH and DELETE). Derived, never accepted as input.
orderidintegerOrderid. Id only.
currencystring(10)Currency the billable rate is stated in.
assetidintegerAssetid. Id only.
assetidlastchangedatestringWhen the assigned asset last changed on the time entry.
baseratemoneystring(4dp)Stored as decimal(10,4).
prpaytypeidintegerPrpaytypeid. Id only.
prpaytypemultipliernumberstring(2dp)Numeric string, 2 decimal places. Not money - do not apply currency rounding.
taxclassidintegerTaxclassid. Id only.
taxclassstring(100)The name of the referenced taxclasses, instead of the id. Send this or taxclassid, not both unless they agree.
sortorderintegerDisplay order. Lower sorts first.
externalidstring(100)Your own key. Scoped to your company.

Endpoints#

POST/serviceordertimes/batch 207

Create many.

Requires scope orders:write.

Parameters
NameInTypeNotes
Body array
FieldTypeDescription
orderidrequiredintegerThe service order the hours belong to. Must be a service order (422 hours_require_service_order) that has not reached billed (409 order_already_billed).
employeeidintegerThe employee who did the work. Must be active with a work class - the time screen only offers those. Send this or a vendor, never both.
vendoridintegerThe vendor/subcontractor who did the work. Must carry a work class and not be a child location.
vendorstring(30)The vendor by code instead of id. Same validation either way.
worktypeidrequiredintegerThe kind of work. GET /serviceworktypes lists them.
worksubtypeidintegerOptional sub-classification. Must belong to worktypeid.
hoursqtystring(2dp)Hours worked, 2 decimal places, as a string. Negative is a correction. Zero is allowed only with a note - the entry stays a placeholder (status 0) and never bills.
entrydatestringThe date the work was done. Defaults to today.
ratemoneystring(4dp)The billing rate per hour, in the ORDER currency. When omitted it derives from the work class rate for the worker, converted at the order date, times the pay type multiplier. When sent it is stored as sent - the multiplier is not applied on top.
costratemoneystring(4dp)Cost per hour to the company, in the company BASE currency. When omitted it derives from the worker: fringe-loaded pay for an employee, default cost per hour for a vendor.
notestextCustomer-visible notes. Concatenated onto the invoice line when hours convert.
internal_commenttextInternal notes. Never shown to the customer.
technamestring(50)Technician name override. Defaults from the worker.
taxclassidintegerTax class, when labor is taxable.
assetidintegerThe customer asset being serviced.
prpaytypeidintegerAR pay type (straight time, overtime...). Only pay types flagged for AR are accepted - the screen offers no others.
prpaytypemultipliernumberstring(2dp)Rate multiplier. Defaults to the pay type's own multiplier, else 1.00. Applied only when rate is derived.
startdatetimestringTimer start, for entries imported from a timer.
enddatetimestringTimer stop.
externalidstring(100)Your own key. Scoped to your company.
curl -X POST \
  'https://acme.nolapro.com/!/api/v2/serviceordertimes/batch' \
  -H 'Authorization: Bearer $NP_TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: your-unique-key' \
  -d '[
    {
        "orderid": 104,
        "worktypeid": 104
    }
]'
GET/serviceordertimes 200403

List service order time.

Requires scope orders:read.

Parameters
NameInTypeNotes
statusquerystringRestrict to one status.
vendoridquerystringRestrict to one vendorid.
employeeidquerystringRestrict to one employeeid.
orderidquerystringRestrict to one orderid.
cancelquerystringDefaults to false. Pass true or any.
modifiedsincequerystringRFC 3339 UTC timestamp. Returns only records changed since then, including cancelled ones - so cancel defaults to any rather than false when this is used. The response carries _meta.synced_through; store it and send it back next time.
externalidquerystringExact match on your own key.
includequerystringComma-separated extras to embed. Only custom_fields is available: the extra fields this install has defined on the record. Off by default, and an unrecognised value is refused rather than ignored. See Conventions.
When it fails
StatusCodeMeaning
403insufficient_scopeToken lacks read scope.
curl \
  'https://acme.nolapro.com/!/api/v2/serviceordertimes' \
  -H 'Authorization: Bearer $NP_TOKEN'
POST/serviceordertimes 201400409422

Create.

Requires scope orders:write.

Parameters
NameInTypeNotes
Body
FieldTypeDescription
orderidrequiredintegerThe service order the hours belong to. Must be a service order (422 hours_require_service_order) that has not reached billed (409 order_already_billed).
employeeidintegerThe employee who did the work. Must be active with a work class - the time screen only offers those. Send this or a vendor, never both.
vendoridintegerThe vendor/subcontractor who did the work. Must carry a work class and not be a child location.
vendorstring(30)The vendor by code instead of id. Same validation either way.
worktypeidrequiredintegerThe kind of work. GET /serviceworktypes lists them.
worksubtypeidintegerOptional sub-classification. Must belong to worktypeid.
hoursqtystring(2dp)Hours worked, 2 decimal places, as a string. Negative is a correction. Zero is allowed only with a note - the entry stays a placeholder (status 0) and never bills.
entrydatestringThe date the work was done. Defaults to today.
ratemoneystring(4dp)The billing rate per hour, in the ORDER currency. When omitted it derives from the work class rate for the worker, converted at the order date, times the pay type multiplier. When sent it is stored as sent - the multiplier is not applied on top.
costratemoneystring(4dp)Cost per hour to the company, in the company BASE currency. When omitted it derives from the worker: fringe-loaded pay for an employee, default cost per hour for a vendor.
notestextCustomer-visible notes. Concatenated onto the invoice line when hours convert.
internal_commenttextInternal notes. Never shown to the customer.
technamestring(50)Technician name override. Defaults from the worker.
taxclassidintegerTax class, when labor is taxable.
assetidintegerThe customer asset being serviced.
prpaytypeidintegerAR pay type (straight time, overtime...). Only pay types flagged for AR are accepted - the screen offers no others.
prpaytypemultipliernumberstring(2dp)Rate multiplier. Defaults to the pay type's own multiplier, else 1.00. Applied only when rate is derived.
startdatetimestringTimer start, for entries imported from a timer.
enddatetimestringTimer stop.
externalidstring(100)Your own key. Scoped to your company.
When it fails
StatusCodeMeaning
400invalid_requestA required field was missing, or hours were zero with no note.
400invalid_typeA decimal arrived as a JSON number, or an id was not an integer.
400invalid_precisionMore decimal places than the field holds.
400unknown_parameterA field outside the accepted set, including the derived ones (totalprice, totalcost, baserate, status, currency).
409order_already_billedThe order has reached billed. The service order screen refuses hours there too.
422hours_require_service_orderThe order is not a service order.
422unknown_valueThe worker, work type, tax class, asset or pay type did not resolve in this company.
422rule_violationNolaPro refused the write. message carries its reason.
curl -X POST \
  'https://acme.nolapro.com/!/api/v2/serviceordertimes' \
  -H 'Authorization: Bearer $NP_TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: your-unique-key' \
  -d '{
    "orderid": 104,
    "worktypeid": 104
}'
Response 201
{
    "employeeid": 104,
    "vendorid": 104,
    "vendor": "Example vendor",
    "ordered": 1,
    "techname": "Example techname",
    "hours": "1.000000"
}
GET/serviceordertimes/{id} 200404

Retrieve one record.

Requires scope orders:read.

Parameters
NameInTypeNotes
idrequiredpathintegerThe record id.
includequerystringComma-separated extras to embed. Only custom_fields is available: the extra fields this install has defined on the record. Off by default, and an unrecognised value is refused rather than ignored. See Conventions.
When it fails
StatusCodeMeaning
404not_foundNo record with that id.
curl \
  'https://acme.nolapro.com/!/api/v2/serviceordertimes/104' \
  -H 'Authorization: Bearer $NP_TOKEN'
Response 200
{
    "employeeid": 104,
    "vendorid": 104,
    "vendor": "Example vendor",
    "ordered": 1,
    "techname": "Example techname",
    "hours": "1.000000"
}
PATCH/serviceordertimes/{id} 200400404409422

Update.

Requires scope orders:write.

Parameters
NameInTypeNotes
idrequiredpathintegerThe record id.
Body
FieldTypeDescription
worksubtypeidintegerOptional sub-classification. Must belong to worktypeid.
hoursqtystring(2dp)Hours worked, 2 decimal places, as a string. Negative is a correction. Zero is allowed only with a note - the entry stays a placeholder (status 0) and never bills.
entrydatestringThe date the work was done. Defaults to today.
ratemoneystring(4dp)The billing rate per hour, in the ORDER currency. When omitted it derives from the work class rate for the worker, converted at the order date, times the pay type multiplier. When sent it is stored as sent - the multiplier is not applied on top.
costratemoneystring(4dp)Cost per hour to the company, in the company BASE currency. When omitted it derives from the worker: fringe-loaded pay for an employee, default cost per hour for a vendor.
notestextCustomer-visible notes. Concatenated onto the invoice line when hours convert.
internal_commenttextInternal notes. Never shown to the customer.
technamestring(50)Technician name override. Defaults from the worker.
taxclassidintegerTax class, when labor is taxable.
assetidintegerThe customer asset being serviced.
prpaytypeidintegerAR pay type (straight time, overtime...). Only pay types flagged for AR are accepted - the screen offers no others.
prpaytypemultipliernumberstring(2dp)Rate multiplier. Defaults to the pay type's own multiplier, else 1.00. Applied only when rate is derived.
startdatetimestringTimer start, for entries imported from a timer.
enddatetimestringTimer stop.
externalidstring(100)Your own key. Scoped to your company.
When it fails
StatusCodeMeaning
400invalid_requestNothing to change, or a malformed value.
400unknown_parameterA field outside the amendable set - including the worker and work type, which are the entry's identity.
404not_foundNo such record, or it belongs to another company.
409hours_already_billedBilling already converted this entry into an order line.
409stale_recordIf-Match did not match; someone else changed it first.
422unknown_valueA reference did not resolve in this company.
422rule_violationThe entry is cancelled, or NolaPro refused the change.
curl -X PATCH \
  'https://acme.nolapro.com/!/api/v2/serviceordertimes/104' \
  -H 'Authorization: Bearer $NP_TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: your-unique-key' \
  -d '{
    "worksubtypeid": 104,
    "hours": "1.000000",
    "rate": "125.0000",
    "costrate": "125.0000",
    "notes": "Example notes",
    "internal_comment": "Example internal comment"
}'
Response 200
{
    "employeeid": 104,
    "vendorid": 104,
    "vendor": "Example vendor",
    "ordered": 1,
    "techname": "Example techname",
    "hours": "1.000000"
}
DELETE/serviceordertimes/{id} 200404409

Cancel.

Requires scope orders:cancel.

Parameters
NameInTypeNotes
idrequiredpathintegerThe record id.
When it fails
StatusCodeMeaning
404not_foundNo such record, or it belongs to another company.
409hours_already_billedBilling already converted this entry into an order line. Credit the invoice and cancel the line first.
curl -X DELETE \
  'https://acme.nolapro.com/!/api/v2/serviceordertimes/104' \
  -H 'Authorization: Bearer $NP_TOKEN'