Jobs
Construction jobs. Costs and revenue can be tracked against one.
This resource needs the construction feature active on the install you are calling. Without that every endpoint here answers 403 with feature_not_licensed - that is a licensing answer, not a permissions one, so check the company's features before the token's scopes.
The object#
| Field | Type | Description |
|---|---|---|
| idread-only | integer | NolaPro id. |
| jobcode | string(20) | Short code identifying the job. |
| jobname | string(255) | Name of the job. |
| address1 | string(100) | Street address. |
| address2 | string(100) | Second address line. |
| city | string(255) | City of the job site. |
| state | string(50) | State of the job site. |
| zip | string(20) | Postal code. |
| description | text | Description. Stored as text, no practical length limit. |
| status | string | Status. Labels are Job_model::$statuses; stored as an int and never exposed or accepted as one (D35). One of active, inactive. |
| productionmanager_userid | integer | NolaPro user assigned as the job’s production manager. |
| productionmanager_user | string(50) | The name of the referenced genusers, instead of the id. Send this or productionmanager_userid, not both unless they agree. |
| owner_companyid | integer | Owner companyid. Id only. |
| cancel | boolean | Cancelled. Always a boolean on the wire, whatever integer width the column uses (D23). |
| entrydateread-only | string | When the record was created. |
| site_manager_userid | integer | NolaPro user assigned as the job’s site manager. |
| site_manager_user | string(50) | The name of the referenced genusers, instead of the id. Send this or site_manager_userid, not both unless they agree. |
| isconstructionjob | integer | 1 marks a construction job - construction budget reports and the bank, lien, and prelim fields apply. |
| bankname | string(100) | Bank funding the construction loan. |
| bankcontact_name | string(100) | Contact at the funding bank. |
| bankcontact_email | string(255) | Email of the funding bank contact. |
| bankinspector_name | string(100) | Bank inspector who signs off draws. |
| bankinspector_email | string(255) | Email of the bank inspector. |
| msproject_jobname | string(100) | Job name as it appears in the imported Microsoft Project plan. |
| region | string(100) | Region the job belongs to. |
| isexternalclient | integer | 1 when the job’s owner is an external client rather than one of the install’s own companies. |
| sitecode | string(100) | Short code of the job site. |
| riskinsurance_underwriter | string(255) | Risk Insurance Underwriter for the job. |
| riskinsurance_amountmoney | string(6dp) | Stored as decimal(19,6). |
| riskinsurance_expiration | string | When the job’s risk insurance expires. |
| siteid | integer | Siteid. Id only. |
| projectid | integer | Row id in the project table the job belongs to. That table has no API endpoint (it is used only by tenant-specific customizations), so this reference is id-only. |
| architectvendorid | integer | Reference to vendors, by id. Write either this or architectvendor. |
| architectvendor | string(30) | The vendorcode of the referenced vendors, instead of the id. Send this or architectvendorid, not both unless they agree. |
| clientprojectnumber | string(100) | The client’s own project number for the job. |
| contractdate | string | Date the contract was signed. |
| inactive | integer | 1 hides the job from active job lists. |
| addressverifiedread-only | string(32) | Hash of the address as it stood when it last passed the AvaTax/USPS address check; when it no longer matches the current address the address counts as unverified. Maintained by the verification flow, so it cannot be written through the API. |
| apn | string(32) | APN - Assessor’s Parcel Number of the job site. |
| closed | boolean | The relationship has ended. Not the same as cancelled. |
| closeddate | string | Date the job was closed. |
| closeduserid | integer | Reference to genusers, by id. Write either this or closeduser. |
| closeduser | string(50) | The name of the referenced genusers, instead of the id. Send this or closeduserid, not both unless they agree. |
| contactname | string(100) | Job site contact. |
| contacttitle | string(32) | Title of the job site contact. |
| contractnumber | string(24) | Contract number for the job. |
| country | string(20) | Country of the job site. |
| customerid | integer | Reference to customers, by id. Write either this or customer. |
| customer | string(30) | Code for the referenced customer, instead of the id. |
| defaultshipvia | integer | Default shipping method for materials going to the job. |
| estpurchasemoney | string(6dp) | Stored as decimal(19,6). |
| jobtype | integer | Job type, from the company’s job types list. |
| lastchangedateread-only | string | Last modification. Drives modifiedsince. |
| latitudemoney | string(6dp) | Stored as decimal(19,6). |
| longitudemoney | string(6dp) | Stored as decimal(19,6). |
| numjobyears | integer | How many years the job spans (Num Job Years). |
| permitcontact | string(100) | Contact for building permits. |
| ponum | string(24) | PO# - the customer’s purchase order covering the job. |
| prelimable | boolean | True when the job qualifies for a preliminary lien notice (Job Prelimable). |
| prelimamountmoney | string(6dp) | Stored as decimal(19,6). |
| prelimcounty | string(24) | County where the preliminary notice is recorded. |
| prelimcreditlimitmoney | string(6dp) | Stored as decimal(19,6). |
| prelimdate | string | Date the preliminary notice was filed. |
| prelimestimatemoney | string(6dp) | Stored as decimal(19,6). |
| prelimnotes | text | Prelimnotes. Stored as text, no practical length limit. |
| prelimstatus | string(100) | Status text of the preliminary notice. |
| productionsalesmanid | integer | Reference to salesmen, by id. Write either this or productionsalesman. |
| productionsalesman | string(50) | The name of the referenced salesmen, instead of the id. Send this or productionsalesmanid, not both unless they agree. |
| sitesalesmanid | integer | Reference to salesmen, by id. Write either this or sitesalesman. |
| sitesalesman | string(50) | The name of the referenced salesmen, instead of the id. Send this or sitesalesmanid, not both unless they agree. |
| taskstatusid | integer | Reference to taskstatuses, by id. Write either this or taskstatus. |
| taskstatus | string(100) | The name of the referenced taskstatuses, instead of the id. Send this or taskstatusid, not both unless they agree. |
| zlienid | integer | Zlienid. Id only. |
| zlienready | boolean | True when the job is ready to send to the lien service (Zlien Ready). |
| deferredvoucherid | integer | Deferredvoucherid. Id only. |
| deferredvoucher | string(50) | The voucher of the referenced gltransactions, instead of the id. Send this or deferredvoucherid, not both unless they agree. |
| lieneddate | string | Date a lien was filed on the job. |
| prelimfirstinvoicedate | string | First invoice date used to compute the preliminary notice deadline. |
| taxexemptid | integer | Reference to taxexempts, by id. Write either this or taxexempt. |
| taxexempt | string(32) | The exemptname of the referenced taxexempts, instead of the id. Send this or taxexemptid, not both unless they agree. |
| unincorporated | integer | 1 when the job site is in an unincorporated area, so no city sales tax applies. |
| zlienhirepartyrole | string(32) | Role of the party that hired you, as sent to the lien service (e.g. Subcontractor). |
| externalid | string(100) | Your own key. Scoped to your company. |
Endpoints#
Create many.
Requires scope jobs:write.
| Name | In | Type | Notes |
|---|---|---|---|
| Idempotency-Key | header | string | Makes the write safely retryable. Any unique string per logical operation; a UUID is fine.
The failure this prevents is specific: the request succeeds, the response is lost to a timeout, you retry, and the customer is billed twice. With a key, the retry returns the original response - same status, same body, same id - and creates nothing.
The body is part of the key's identity. Reusing a key with a different body is a bug on your side, not a retry, and answers 409 idempotency_replay rather than silently handing back the old response. Keys are remembered for 24 hours. |
| Field | Type | Description |
|---|---|---|
| idread-only | integer | NolaPro id. |
| jobcode | string(20) | Short code identifying the job. |
| jobname | string(255) | Name of the job. |
| address1 | string(100) | Street address. |
| address2 | string(100) | Second address line. |
| city | string(255) | City of the job site. |
| state | string(50) | State of the job site. |
| zip | string(20) | Postal code. |
| description | text | Description. Stored as text, no practical length limit. |
| status | string | Status. Labels are Job_model::$statuses; stored as an int and never exposed or accepted as one (D35). One of active, inactive. |
| productionmanager_userid | integer | NolaPro user assigned as the job’s production manager. |
| productionmanager_user | string(50) | The name of the referenced genusers, instead of the id. Send this or productionmanager_userid, not both unless they agree. |
| owner_companyid | integer | Owner companyid. Id only. |
| cancel | boolean | Cancelled. Always a boolean on the wire, whatever integer width the column uses (D23). |
| entrydateread-only | string | When the record was created. |
| site_manager_userid | integer | NolaPro user assigned as the job’s site manager. |
| site_manager_user | string(50) | The name of the referenced genusers, instead of the id. Send this or site_manager_userid, not both unless they agree. |
| isconstructionjob | integer | 1 marks a construction job - construction budget reports and the bank, lien, and prelim fields apply. |
| bankname | string(100) | Bank funding the construction loan. |
| bankcontact_name | string(100) | Contact at the funding bank. |
| bankcontact_email | string(255) | Email of the funding bank contact. |
| bankinspector_name | string(100) | Bank inspector who signs off draws. |
| bankinspector_email | string(255) | Email of the bank inspector. |
| msproject_jobname | string(100) | Job name as it appears in the imported Microsoft Project plan. |
| region | string(100) | Region the job belongs to. |
| isexternalclient | integer | 1 when the job’s owner is an external client rather than one of the install’s own companies. |
| sitecode | string(100) | Short code of the job site. |
| riskinsurance_underwriter | string(255) | Risk Insurance Underwriter for the job. |
| riskinsurance_amountmoney | string(6dp) | Stored as decimal(19,6). |
| riskinsurance_expiration | string | When the job’s risk insurance expires. |
| siteid | integer | Siteid. Id only. |
| projectid | integer | Row id in the project table the job belongs to. That table has no API endpoint (it is used only by tenant-specific customizations), so this reference is id-only. |
| architectvendorid | integer | Reference to vendors, by id. Write either this or architectvendor. |
| architectvendor | string(30) | The vendorcode of the referenced vendors, instead of the id. Send this or architectvendorid, not both unless they agree. |
| clientprojectnumber | string(100) | The client’s own project number for the job. |
| contractdate | string | Date the contract was signed. |
| inactive | integer | 1 hides the job from active job lists. |
| addressverifiedread-only | string(32) | Hash of the address as it stood when it last passed the AvaTax/USPS address check; when it no longer matches the current address the address counts as unverified. Maintained by the verification flow, so it cannot be written through the API. |
| apn | string(32) | APN - Assessor’s Parcel Number of the job site. |
| closed | boolean | The relationship has ended. Not the same as cancelled. |
| closeddate | string | Date the job was closed. |
| closeduserid | integer | Reference to genusers, by id. Write either this or closeduser. |
| closeduser | string(50) | The name of the referenced genusers, instead of the id. Send this or closeduserid, not both unless they agree. |
| contactname | string(100) | Job site contact. |
| contacttitle | string(32) | Title of the job site contact. |
| contractnumber | string(24) | Contract number for the job. |
| country | string(20) | Country of the job site. |
| customerid | integer | Reference to customers, by id. Write either this or customer. |
| customer | string(30) | Code for the referenced customer, instead of the id. |
| defaultshipvia | integer | Default shipping method for materials going to the job. |
| estpurchasemoney | string(6dp) | Stored as decimal(19,6). |
| jobtype | integer | Job type, from the company’s job types list. |
| lastchangedateread-only | string | Last modification. Drives modifiedsince. |
| latitudemoney | string(6dp) | Stored as decimal(19,6). |
| longitudemoney | string(6dp) | Stored as decimal(19,6). |
| numjobyears | integer | How many years the job spans (Num Job Years). |
| permitcontact | string(100) | Contact for building permits. |
| ponum | string(24) | PO# - the customer’s purchase order covering the job. |
| prelimable | boolean | True when the job qualifies for a preliminary lien notice (Job Prelimable). |
| prelimamountmoney | string(6dp) | Stored as decimal(19,6). |
| prelimcounty | string(24) | County where the preliminary notice is recorded. |
| prelimcreditlimitmoney | string(6dp) | Stored as decimal(19,6). |
| prelimdate | string | Date the preliminary notice was filed. |
| prelimestimatemoney | string(6dp) | Stored as decimal(19,6). |
| prelimnotes | text | Prelimnotes. Stored as text, no practical length limit. |
| prelimstatus | string(100) | Status text of the preliminary notice. |
| productionsalesmanid | integer | Reference to salesmen, by id. Write either this or productionsalesman. |
| productionsalesman | string(50) | The name of the referenced salesmen, instead of the id. Send this or productionsalesmanid, not both unless they agree. |
| sitesalesmanid | integer | Reference to salesmen, by id. Write either this or sitesalesman. |
| sitesalesman | string(50) | The name of the referenced salesmen, instead of the id. Send this or sitesalesmanid, not both unless they agree. |
| taskstatusid | integer | Reference to taskstatuses, by id. Write either this or taskstatus. |
| taskstatus | string(100) | The name of the referenced taskstatuses, instead of the id. Send this or taskstatusid, not both unless they agree. |
| zlienid | integer | Zlienid. Id only. |
| zlienready | boolean | True when the job is ready to send to the lien service (Zlien Ready). |
| deferredvoucherid | integer | Deferredvoucherid. Id only. |
| deferredvoucher | string(50) | The voucher of the referenced gltransactions, instead of the id. Send this or deferredvoucherid, not both unless they agree. |
| lieneddate | string | Date a lien was filed on the job. |
| prelimfirstinvoicedate | string | First invoice date used to compute the preliminary notice deadline. |
| taxexemptid | integer | Reference to taxexempts, by id. Write either this or taxexempt. |
| taxexempt | string(32) | The exemptname of the referenced taxexempts, instead of the id. Send this or taxexemptid, not both unless they agree. |
| unincorporated | integer | 1 when the job site is in an unincorporated area, so no city sales tax applies. |
| zlienhirepartyrole | string(32) | Role of the party that hired you, as sent to the lien service (e.g. Subcontractor). |
| externalid | string(100) | Your own key. Scoped to your company. |
curl -X POST \ 'https://acme.nolapro.com/!/api/v2/jobs/batch' \ -H 'Authorization: Bearer $NP_TOKEN' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: your-unique-key' \ -d '[ { "status": "active" } ]'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/jobs/batch'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN')], CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => json_encode([ [ 'status' => 'active', ], ]), ]); $res = json_decode(curl_exec($ch), true);
import os, requests r = requests.post( "https://acme.nolapro.com/!/api/v2/jobs/batch", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, json=[ { "status": "active", }, ], ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/jobs/batch', { method: 'POST', headers: { Authorization: `Bearer ${process.env.NP_TOKEN}` }, body: JSON.stringify([ { status: "active", }, ]), } ); const data = await res.json();
using System.Net.Http.Json; var token = Environment.GetEnvironmentVariable("NP_TOKEN"); using var http = new HttpClient(); http.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); var body = new[] { new { status = "active", }, }; var req = new HttpRequestMessage(HttpMethod.Post, "https://acme.nolapro.com/!/api/v2/jobs/batch") { Content = JsonContent.Create(body), }; req.Headers.Add("Idempotency-Key", "your-unique-key"); var res = await http.SendAsync(req); res.EnsureSuccessStatusCode();
List jobs.
Requires scope jobs:read.
| Name | In | Type | Notes |
|---|---|---|---|
| status | query | string | Restrict to one status. |
| customerid | query | string | Restrict to one customerid. |
| description | query | string | description. Partial match, case-insensitive. |
| jobcode | query | string | Partial match, case insensitive. |
| cancel | query | string | Defaults to false. Pass true or any. |
| modifiedsince | query | string | RFC 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. |
| externalid | query | string | Exact match on your own key. |
| include | query | string | Comma-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. |
| Status | Code | Meaning |
|---|---|---|
| 403 | insufficient_scope | Token lacks read scope. |
curl \ 'https://acme.nolapro.com/!/api/v2/jobs' \ -H 'Authorization: Bearer $NP_TOKEN'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/jobs'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN')], CURLOPT_RETURNTRANSFER => true, ]); $res = json_decode(curl_exec($ch), true);
import os, requests r = requests.get( "https://acme.nolapro.com/!/api/v2/jobs", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/jobs', { method: 'GET', headers: { Authorization: `Bearer ${process.env.NP_TOKEN}` }, } ); const data = await res.json();
using System.Net.Http.Json; var token = Environment.GetEnvironmentVariable("NP_TOKEN"); using var http = new HttpClient(); http.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); var res = await http.GetAsync( "https://acme.nolapro.com/!/api/v2/jobs"); res.EnsureSuccessStatusCode();
Create.
Requires scope jobs:write.
| Name | In | Type | Notes |
|---|---|---|---|
| Idempotency-Key | header | string | Makes the write safely retryable. Any unique string per logical operation; a UUID is fine.
The failure this prevents is specific: the request succeeds, the response is lost to a timeout, you retry, and the customer is billed twice. With a key, the retry returns the original response - same status, same body, same id - and creates nothing.
The body is part of the key's identity. Reusing a key with a different body is a bug on your side, not a retry, and answers 409 idempotency_replay rather than silently handing back the old response. Keys are remembered for 24 hours. |
| Field | Type | Description |
|---|---|---|
| idread-only | integer | NolaPro id. |
| jobcode | string(20) | Short code identifying the job. |
| jobname | string(255) | Name of the job. |
| address1 | string(100) | Street address. |
| address2 | string(100) | Second address line. |
| city | string(255) | City of the job site. |
| state | string(50) | State of the job site. |
| zip | string(20) | Postal code. |
| description | text | Description. Stored as text, no practical length limit. |
| status | string | Status. Labels are Job_model::$statuses; stored as an int and never exposed or accepted as one (D35). One of active, inactive. |
| productionmanager_userid | integer | NolaPro user assigned as the job’s production manager. |
| productionmanager_user | string(50) | The name of the referenced genusers, instead of the id. Send this or productionmanager_userid, not both unless they agree. |
| owner_companyid | integer | Owner companyid. Id only. |
| cancel | boolean | Cancelled. Always a boolean on the wire, whatever integer width the column uses (D23). |
| entrydateread-only | string | When the record was created. |
| site_manager_userid | integer | NolaPro user assigned as the job’s site manager. |
| site_manager_user | string(50) | The name of the referenced genusers, instead of the id. Send this or site_manager_userid, not both unless they agree. |
| isconstructionjob | integer | 1 marks a construction job - construction budget reports and the bank, lien, and prelim fields apply. |
| bankname | string(100) | Bank funding the construction loan. |
| bankcontact_name | string(100) | Contact at the funding bank. |
| bankcontact_email | string(255) | Email of the funding bank contact. |
| bankinspector_name | string(100) | Bank inspector who signs off draws. |
| bankinspector_email | string(255) | Email of the bank inspector. |
| msproject_jobname | string(100) | Job name as it appears in the imported Microsoft Project plan. |
| region | string(100) | Region the job belongs to. |
| isexternalclient | integer | 1 when the job’s owner is an external client rather than one of the install’s own companies. |
| sitecode | string(100) | Short code of the job site. |
| riskinsurance_underwriter | string(255) | Risk Insurance Underwriter for the job. |
| riskinsurance_amountmoney | string(6dp) | Stored as decimal(19,6). |
| riskinsurance_expiration | string | When the job’s risk insurance expires. |
| siteid | integer | Siteid. Id only. |
| projectid | integer | Row id in the project table the job belongs to. That table has no API endpoint (it is used only by tenant-specific customizations), so this reference is id-only. |
| architectvendorid | integer | Reference to vendors, by id. Write either this or architectvendor. |
| architectvendor | string(30) | The vendorcode of the referenced vendors, instead of the id. Send this or architectvendorid, not both unless they agree. |
| clientprojectnumber | string(100) | The client’s own project number for the job. |
| contractdate | string | Date the contract was signed. |
| inactive | integer | 1 hides the job from active job lists. |
| addressverifiedread-only | string(32) | Hash of the address as it stood when it last passed the AvaTax/USPS address check; when it no longer matches the current address the address counts as unverified. Maintained by the verification flow, so it cannot be written through the API. |
| apn | string(32) | APN - Assessor’s Parcel Number of the job site. |
| closed | boolean | The relationship has ended. Not the same as cancelled. |
| closeddate | string | Date the job was closed. |
| closeduserid | integer | Reference to genusers, by id. Write either this or closeduser. |
| closeduser | string(50) | The name of the referenced genusers, instead of the id. Send this or closeduserid, not both unless they agree. |
| contactname | string(100) | Job site contact. |
| contacttitle | string(32) | Title of the job site contact. |
| contractnumber | string(24) | Contract number for the job. |
| country | string(20) | Country of the job site. |
| customerid | integer | Reference to customers, by id. Write either this or customer. |
| customer | string(30) | Code for the referenced customer, instead of the id. |
| defaultshipvia | integer | Default shipping method for materials going to the job. |
| estpurchasemoney | string(6dp) | Stored as decimal(19,6). |
| jobtype | integer | Job type, from the company’s job types list. |
| lastchangedateread-only | string | Last modification. Drives modifiedsince. |
| latitudemoney | string(6dp) | Stored as decimal(19,6). |
| longitudemoney | string(6dp) | Stored as decimal(19,6). |
| numjobyears | integer | How many years the job spans (Num Job Years). |
| permitcontact | string(100) | Contact for building permits. |
| ponum | string(24) | PO# - the customer’s purchase order covering the job. |
| prelimable | boolean | True when the job qualifies for a preliminary lien notice (Job Prelimable). |
| prelimamountmoney | string(6dp) | Stored as decimal(19,6). |
| prelimcounty | string(24) | County where the preliminary notice is recorded. |
| prelimcreditlimitmoney | string(6dp) | Stored as decimal(19,6). |
| prelimdate | string | Date the preliminary notice was filed. |
| prelimestimatemoney | string(6dp) | Stored as decimal(19,6). |
| prelimnotes | text | Prelimnotes. Stored as text, no practical length limit. |
| prelimstatus | string(100) | Status text of the preliminary notice. |
| productionsalesmanid | integer | Reference to salesmen, by id. Write either this or productionsalesman. |
| productionsalesman | string(50) | The name of the referenced salesmen, instead of the id. Send this or productionsalesmanid, not both unless they agree. |
| sitesalesmanid | integer | Reference to salesmen, by id. Write either this or sitesalesman. |
| sitesalesman | string(50) | The name of the referenced salesmen, instead of the id. Send this or sitesalesmanid, not both unless they agree. |
| taskstatusid | integer | Reference to taskstatuses, by id. Write either this or taskstatus. |
| taskstatus | string(100) | The name of the referenced taskstatuses, instead of the id. Send this or taskstatusid, not both unless they agree. |
| zlienid | integer | Zlienid. Id only. |
| zlienready | boolean | True when the job is ready to send to the lien service (Zlien Ready). |
| deferredvoucherid | integer | Deferredvoucherid. Id only. |
| deferredvoucher | string(50) | The voucher of the referenced gltransactions, instead of the id. Send this or deferredvoucherid, not both unless they agree. |
| lieneddate | string | Date a lien was filed on the job. |
| prelimfirstinvoicedate | string | First invoice date used to compute the preliminary notice deadline. |
| taxexemptid | integer | Reference to taxexempts, by id. Write either this or taxexempt. |
| taxexempt | string(32) | The exemptname of the referenced taxexempts, instead of the id. Send this or taxexemptid, not both unless they agree. |
| unincorporated | integer | 1 when the job site is in an unincorporated area, so no city sales tax applies. |
| zlienhirepartyrole | string(32) | Role of the party that hired you, as sent to the lien service (e.g. Subcontractor). |
| externalid | string(100) | Your own key. Scoped to your company. |
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | A required field was missing. |
curl -X POST \ 'https://acme.nolapro.com/!/api/v2/jobs' \ -H 'Authorization: Bearer $NP_TOKEN' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: your-unique-key' \ -d '{ "status": "active" }'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/jobs'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN')], CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => json_encode([ 'status' => 'active', ]), ]); $res = json_decode(curl_exec($ch), true);
import os, requests r = requests.post( "https://acme.nolapro.com/!/api/v2/jobs", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, json={ "status": "active", }, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/jobs', { method: 'POST', headers: { Authorization: `Bearer ${process.env.NP_TOKEN}` }, body: JSON.stringify({ status: "active", }), } ); const data = await res.json();
using System.Net.Http.Json; var token = Environment.GetEnvironmentVariable("NP_TOKEN"); using var http = new HttpClient(); http.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); var body = new { status = "active", }; var req = new HttpRequestMessage(HttpMethod.Post, "https://acme.nolapro.com/!/api/v2/jobs") { Content = JsonContent.Create(body), }; req.Headers.Add("Idempotency-Key", "your-unique-key"); var res = await http.SendAsync(req); res.EnsureSuccessStatusCode();
{
"status": "active"
}
Retrieve one record.
Requires scope jobs:read.
| Name | In | Type | Notes |
|---|---|---|---|
| idrequired | path | integer | The record id. |
| include | query | string | Comma-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. |
| Status | Code | Meaning |
|---|---|---|
| 404 | not_found | No record with that id. |
curl \ 'https://acme.nolapro.com/!/api/v2/jobs/104' \ -H 'Authorization: Bearer $NP_TOKEN'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/jobs/104'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN')], CURLOPT_RETURNTRANSFER => true, ]); $res = json_decode(curl_exec($ch), true);
import os, requests r = requests.get( "https://acme.nolapro.com/!/api/v2/jobs/104", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/jobs/104', { method: 'GET', headers: { Authorization: `Bearer ${process.env.NP_TOKEN}` }, } ); const data = await res.json();
using System.Net.Http.Json; var token = Environment.GetEnvironmentVariable("NP_TOKEN"); using var http = new HttpClient(); http.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); var res = await http.GetAsync( "https://acme.nolapro.com/!/api/v2/jobs/104"); res.EnsureSuccessStatusCode();
{
"status": "active"
}
Update.
Requires scope jobs:write.
| Name | In | Type | Notes |
|---|---|---|---|
| idrequired | path | integer | The record id. |
| Idempotency-Key | header | string | Makes the write safely retryable. Any unique string per logical operation; a UUID is fine.
The failure this prevents is specific: the request succeeds, the response is lost to a timeout, you retry, and the customer is billed twice. With a key, the retry returns the original response - same status, same body, same id - and creates nothing.
The body is part of the key's identity. Reusing a key with a different body is a bug on your side, not a retry, and answers 409 idempotency_replay rather than silently handing back the old response. Keys are remembered for 24 hours. |
| Field | Type | Description |
|---|---|---|
| idread-only | integer | NolaPro id. |
| jobcode | string(20) | Short code identifying the job. |
| jobname | string(255) | Name of the job. |
| address1 | string(100) | Street address. |
| address2 | string(100) | Second address line. |
| city | string(255) | City of the job site. |
| state | string(50) | State of the job site. |
| zip | string(20) | Postal code. |
| description | text | Description. Stored as text, no practical length limit. |
| status | string | Status. Labels are Job_model::$statuses; stored as an int and never exposed or accepted as one (D35). One of active, inactive. |
| productionmanager_userid | integer | NolaPro user assigned as the job’s production manager. |
| productionmanager_user | string(50) | The name of the referenced genusers, instead of the id. Send this or productionmanager_userid, not both unless they agree. |
| owner_companyid | integer | Owner companyid. Id only. |
| cancel | boolean | Cancelled. Always a boolean on the wire, whatever integer width the column uses (D23). |
| entrydateread-only | string | When the record was created. |
| site_manager_userid | integer | NolaPro user assigned as the job’s site manager. |
| site_manager_user | string(50) | The name of the referenced genusers, instead of the id. Send this or site_manager_userid, not both unless they agree. |
| isconstructionjob | integer | 1 marks a construction job - construction budget reports and the bank, lien, and prelim fields apply. |
| bankname | string(100) | Bank funding the construction loan. |
| bankcontact_name | string(100) | Contact at the funding bank. |
| bankcontact_email | string(255) | Email of the funding bank contact. |
| bankinspector_name | string(100) | Bank inspector who signs off draws. |
| bankinspector_email | string(255) | Email of the bank inspector. |
| msproject_jobname | string(100) | Job name as it appears in the imported Microsoft Project plan. |
| region | string(100) | Region the job belongs to. |
| isexternalclient | integer | 1 when the job’s owner is an external client rather than one of the install’s own companies. |
| sitecode | string(100) | Short code of the job site. |
| riskinsurance_underwriter | string(255) | Risk Insurance Underwriter for the job. |
| riskinsurance_amountmoney | string(6dp) | Stored as decimal(19,6). |
| riskinsurance_expiration | string | When the job’s risk insurance expires. |
| siteid | integer | Siteid. Id only. |
| projectid | integer | Row id in the project table the job belongs to. That table has no API endpoint (it is used only by tenant-specific customizations), so this reference is id-only. |
| architectvendorid | integer | Reference to vendors, by id. Write either this or architectvendor. |
| architectvendor | string(30) | The vendorcode of the referenced vendors, instead of the id. Send this or architectvendorid, not both unless they agree. |
| clientprojectnumber | string(100) | The client’s own project number for the job. |
| contractdate | string | Date the contract was signed. |
| inactive | integer | 1 hides the job from active job lists. |
| addressverifiedread-only | string(32) | Hash of the address as it stood when it last passed the AvaTax/USPS address check; when it no longer matches the current address the address counts as unverified. Maintained by the verification flow, so it cannot be written through the API. |
| apn | string(32) | APN - Assessor’s Parcel Number of the job site. |
| closed | boolean | The relationship has ended. Not the same as cancelled. |
| closeddate | string | Date the job was closed. |
| closeduserid | integer | Reference to genusers, by id. Write either this or closeduser. |
| closeduser | string(50) | The name of the referenced genusers, instead of the id. Send this or closeduserid, not both unless they agree. |
| contactname | string(100) | Job site contact. |
| contacttitle | string(32) | Title of the job site contact. |
| contractnumber | string(24) | Contract number for the job. |
| country | string(20) | Country of the job site. |
| customerid | integer | Reference to customers, by id. Write either this or customer. |
| customer | string(30) | Code for the referenced customer, instead of the id. |
| defaultshipvia | integer | Default shipping method for materials going to the job. |
| estpurchasemoney | string(6dp) | Stored as decimal(19,6). |
| jobtype | integer | Job type, from the company’s job types list. |
| lastchangedateread-only | string | Last modification. Drives modifiedsince. |
| latitudemoney | string(6dp) | Stored as decimal(19,6). |
| longitudemoney | string(6dp) | Stored as decimal(19,6). |
| numjobyears | integer | How many years the job spans (Num Job Years). |
| permitcontact | string(100) | Contact for building permits. |
| ponum | string(24) | PO# - the customer’s purchase order covering the job. |
| prelimable | boolean | True when the job qualifies for a preliminary lien notice (Job Prelimable). |
| prelimamountmoney | string(6dp) | Stored as decimal(19,6). |
| prelimcounty | string(24) | County where the preliminary notice is recorded. |
| prelimcreditlimitmoney | string(6dp) | Stored as decimal(19,6). |
| prelimdate | string | Date the preliminary notice was filed. |
| prelimestimatemoney | string(6dp) | Stored as decimal(19,6). |
| prelimnotes | text | Prelimnotes. Stored as text, no practical length limit. |
| prelimstatus | string(100) | Status text of the preliminary notice. |
| productionsalesmanid | integer | Reference to salesmen, by id. Write either this or productionsalesman. |
| productionsalesman | string(50) | The name of the referenced salesmen, instead of the id. Send this or productionsalesmanid, not both unless they agree. |
| sitesalesmanid | integer | Reference to salesmen, by id. Write either this or sitesalesman. |
| sitesalesman | string(50) | The name of the referenced salesmen, instead of the id. Send this or sitesalesmanid, not both unless they agree. |
| taskstatusid | integer | Reference to taskstatuses, by id. Write either this or taskstatus. |
| taskstatus | string(100) | The name of the referenced taskstatuses, instead of the id. Send this or taskstatusid, not both unless they agree. |
| zlienid | integer | Zlienid. Id only. |
| zlienready | boolean | True when the job is ready to send to the lien service (Zlien Ready). |
| deferredvoucherid | integer | Deferredvoucherid. Id only. |
| deferredvoucher | string(50) | The voucher of the referenced gltransactions, instead of the id. Send this or deferredvoucherid, not both unless they agree. |
| lieneddate | string | Date a lien was filed on the job. |
| prelimfirstinvoicedate | string | First invoice date used to compute the preliminary notice deadline. |
| taxexemptid | integer | Reference to taxexempts, by id. Write either this or taxexempt. |
| taxexempt | string(32) | The exemptname of the referenced taxexempts, instead of the id. Send this or taxexemptid, not both unless they agree. |
| unincorporated | integer | 1 when the job site is in an unincorporated area, so no city sales tax applies. |
| zlienhirepartyrole | string(32) | Role of the party that hired you, as sent to the lien service (e.g. Subcontractor). |
| externalid | string(100) | Your own key. Scoped to your company. |
| Status | Code | Meaning |
|---|---|---|
| 404 | not_found | No record with that id. |
curl -X PATCH \ 'https://acme.nolapro.com/!/api/v2/jobs/104' \ -H 'Authorization: Bearer $NP_TOKEN' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: your-unique-key' \ -d '{ "status": "active" }'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/jobs/104'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN')], CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'PATCH', CURLOPT_POSTFIELDS => json_encode([ 'status' => 'active', ]), ]); $res = json_decode(curl_exec($ch), true);
import os, requests r = requests.patch( "https://acme.nolapro.com/!/api/v2/jobs/104", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, json={ "status": "active", }, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/jobs/104', { method: 'PATCH', headers: { Authorization: `Bearer ${process.env.NP_TOKEN}` }, body: JSON.stringify({ status: "active", }), } ); const data = await res.json();
using System.Net.Http.Json; var token = Environment.GetEnvironmentVariable("NP_TOKEN"); using var http = new HttpClient(); http.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); var body = new { status = "active", }; var req = new HttpRequestMessage(HttpMethod.Patch, "https://acme.nolapro.com/!/api/v2/jobs/104") { Content = JsonContent.Create(body), }; req.Headers.Add("Idempotency-Key", "your-unique-key"); var res = await http.SendAsync(req); res.EnsureSuccessStatusCode();
{
"status": "active"
}
Cancel.
Requires scope jobs:cancel.
| Name | In | Type | Notes |
|---|---|---|---|
| idrequired | path | integer | The record id. |
| Idempotency-Key | header | string | Makes the write safely retryable. Any unique string per logical operation; a UUID is fine.
The failure this prevents is specific: the request succeeds, the response is lost to a timeout, you retry, and the customer is billed twice. With a key, the retry returns the original response - same status, same body, same id - and creates nothing.
The body is part of the key's identity. Reusing a key with a different body is a bug on your side, not a retry, and answers 409 idempotency_replay rather than silently handing back the old response. Keys are remembered for 24 hours. |
| Status | Code | Meaning |
|---|---|---|
| 404 | not_found | No record with that id. |
curl -X DELETE \ 'https://acme.nolapro.com/!/api/v2/jobs/104' \ -H 'Authorization: Bearer $NP_TOKEN'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/jobs/104'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN')], CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'DELETE', ]); $res = json_decode(curl_exec($ch), true);
import os, requests r = requests.delete( "https://acme.nolapro.com/!/api/v2/jobs/104", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/jobs/104', { method: 'DELETE', headers: { Authorization: `Bearer ${process.env.NP_TOKEN}` }, } ); const data = await res.json();
using System.Net.Http.Json; var token = Environment.GetEnvironmentVariable("NP_TOKEN"); using var http = new HttpClient(); http.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); var req = new HttpRequestMessage(HttpMethod.Delete, "https://acme.nolapro.com/!/api/v2/jobs/104"); var res = await http.SendAsync(req); res.EnsureSuccessStatusCode();
{
"status": "active"
}
List files attached to a job.
The attachments on this job, newest first. Accepted filedefinitionid values: 33 (default 33). Metadata only - each file's bytes are at GET /attachments/{id}/content.
Requires scope jobs:read.
| Name | In | Type | Notes |
|---|---|---|---|
| idrequired | path | integer | The job id. |
| filedefinitionid | query | integer | Only files in this list. Accepted filedefinitionid values: 33 (default 33). |
| filecategoryid | query | integer | Only files filed under this category. |
| filename | query | string | Partial match on the file name, case insensitive. |
| Status | Code | Meaning |
|---|---|---|
| 404 | not_found | No job with that id in this company. |
curl \ 'https://acme.nolapro.com/!/api/v2/jobs/104/attachments' \ -H 'Authorization: Bearer $NP_TOKEN'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/jobs/104/attachments'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN')], CURLOPT_RETURNTRANSFER => true, ]); $res = json_decode(curl_exec($ch), true);
import os, requests r = requests.get( "https://acme.nolapro.com/!/api/v2/jobs/104/attachments", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/jobs/104/attachments', { method: 'GET', headers: { Authorization: `Bearer ${process.env.NP_TOKEN}` }, } ); const data = await res.json();
using System.Net.Http.Json; var token = Environment.GetEnvironmentVariable("NP_TOKEN"); using var http = new HttpClient(); http.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); var res = await http.GetAsync( "https://acme.nolapro.com/!/api/v2/jobs/104/attachments"); res.EnsureSuccessStatusCode();
Attach a file to a job.
multipart/form-data with one file part; see the AttachmentUpload schema for the other parts. Accepted filedefinitionid values: 33 (default 33). Answers 201 with the attachment's metadata and Location: /attachments/{id}. Check _meta.warnings for datatype_truncated and stored_under_parent_company.
Requires scope jobs:write.
| Name | In | Type | Notes |
|---|---|---|---|
| idrequired | path | integer | The job id. |
| Idempotency-Key | header | string | Makes the write safely retryable. Any unique string per logical operation; a UUID is fine.
The failure this prevents is specific: the request succeeds, the response is lost to a timeout, you retry, and the customer is billed twice. With a key, the retry returns the original response - same status, same body, same id - and creates nothing.
The body is part of the key's identity. Reusing a key with a different body is a bug on your side, not a retry, and answers 409 idempotency_replay rather than silently handing back the old response. Keys are remembered for 24 hours. |
| Field | Type | Description |
|---|---|---|
| filerequired | string | The file. Exactly one part named file; a second one, or file[], is 400 invalid_request so an idempotent retry can never half-succeed. Empty is refused. Over the cap (the smaller of APIV2_MAX_UPLOAD_BYTES, 64 MB by default, and PHP's upload_max_filesize / post_max_size) is 413 payload_too_large naming the limit that applied. |
| filename | string(255) | Overrides the part's file name. |
| notes | text | Free text shown beside the file. |
| filedefinitionid | integer | Only when the parent accepts more than one list. Anything the parent does not accept is 422 unknown_value naming the accepted ids. |
| filecategoryid | integer | Category by id. |
| filecategory | string(255) | Category by name. Sent with filecategoryid and disagreeing is 422 conflicting_reference. |
| Status | Code | Meaning |
|---|---|---|
| 400 | unknown_parameter | A form field that is not on the AttachmentUpload schema. |
| 400 | invalid_type | filedefinitionid or filecategoryid that is not an integer. |
| 404 | not_found | No job with that id in this company. |
| 409 | upload_limit_reached | This file list allows a fixed number of files on a job and it is full. Remove one first. |
| 413 | payload_too_large | The file is over the cap. The body names the limit that applied. |
| 415 | multipart_required | The body was not multipart/form-data. |
| 422 | unknown_value | filedefinitionid is not one this job accepts, or the category does not exist in this company. |
curl -X POST \ 'https://acme.nolapro.com/!/api/v2/jobs/104/attachments' \ -H 'Authorization: Bearer $NP_TOKEN' \ -H 'Idempotency-Key: your-unique-key' \ -F 'file=@grant-letter-signed.pdf' \ -F 'filename=grant-letter-signed.pdf' \ -F 'notes=Signed copy received 21 Sep' \ -F 'filedefinitionid=8' \ -F 'filecategory=Receipts'
$fields = [ 'filename' => 'grant-letter-signed.pdf', 'notes' => 'Signed copy received 21 Sep', 'filedefinitionid' => '8', 'filecategory' => 'Receipts', ]; $fields['file'] = new CURLFile('grant-letter-signed.pdf'); $ch = curl_init('https://acme.nolapro.com/!/api/v2/jobs/104/attachments'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN'), 'Idempotency-Key: your-unique-key'], CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $fields, ]); $res = json_decode(curl_exec($ch), true);
import os, requests with open("grant-letter-signed.pdf", "rb") as fh: r = requests.post( "https://acme.nolapro.com/!/api/v2/jobs/104/attachments", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}", "Idempotency-Key": "your-unique-key"}, files={"file": fh}, data={ "filename": "grant-letter-signed.pdf", "notes": "Signed copy received 21 Sep", "filedefinitionid": "8", "filecategory": "Receipts", }, ) r.raise_for_status()
import { openAsBlob } from 'node:fs';
const form = new FormData();
form.append('file', await openAsBlob('grant-letter-signed.pdf'), 'grant-letter-signed.pdf');
form.append('filename', "grant-letter-signed.pdf");
form.append('notes', "Signed copy received 21 Sep");
form.append('filedefinitionid', "8");
form.append('filecategory', "Receipts");
const res = await fetch(
'https://acme.nolapro.com/!/api/v2/jobs/104/attachments',
{
method: 'POST',
headers: { Authorization: `Bearer ${process.env.NP_TOKEN}`, 'Idempotency-Key': 'your-unique-key' },
body: form,
}
);
const data = await res.json();
var token = Environment.GetEnvironmentVariable("NP_TOKEN"); using var http = new HttpClient(); http.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); using var form = new MultipartFormDataContent(); form.Add(new StreamContent(File.OpenRead("grant-letter-signed.pdf")), "file", "grant-letter-signed.pdf"); form.Add(new StringContent("grant-letter-signed.pdf"), "filename"); form.Add(new StringContent("Signed copy received 21 Sep"), "notes"); form.Add(new StringContent("8"), "filedefinitionid"); form.Add(new StringContent("Receipts"), "filecategory"); var req = new HttpRequestMessage(HttpMethod.Post, "https://acme.nolapro.com/!/api/v2/jobs/104/attachments") { Content = form }; req.Headers.Add("Idempotency-Key", "your-unique-key"); var res = await http.SendAsync(req); res.EnsureSuccessStatusCode();