Quickstart
Five minutes from nothing to a working request. You need a NolaPro login with supervisor rights, or an administrator who can issue you a token.
v2 is still being finished. Reads, writes and the transactional documents answer today; webhooks and full delta sync do not. Every endpoint carries a planned or live chip — check it before you write against it. Follow the steps below on a development install first, not a production one.
1. Create a token#
Tokens live on the user they belong to, not on a page of their own:
| Where | Whose tokens |
|---|---|
| My Info | your own |
| Admin → user edit | anyone's |
Fill in the label (what this token is for, say Shopify sync (production) — you will thank yourself when there are nine of them) and tick the scopes it needs. Start with the least that does the job; create a second token later rather than widening this one.
The token is shown once. It is stored hashed and cannot be recovered, only replaced. Put it straight into your secret store.
The company is not something you pick. A token is issued in the company you are working in and only ever acts there. To integrate with three companies, switch company and issue a token in each.
The token's user must be a supervisor in that company. That is the gate on who may hold a token; the scopes are what bound it. A supervisor in a different company gets 403 forbidden.
Note that write does not include cancel, and posting raw journal entries (gltransactions:write) is off unless you ask for it. See Authentication.
2. Make a request#
Your base URL is your NolaPro address plus /!/api/v2 — including the !, which is where the application lives. On a hosted site that is https://yoursite.nolapro.com/!/api/v2; on a self-hosted install it is wherever NolaPro answers, plus the same path.
export NP_TOKEN='np_v2_...' curl 'https://acme.nolapro.com/!/api/v2/customers?perpage=3' \ -H "Authorization: Bearer $NP_TOKEN"
{
"data": [
{
"id": 104,
"companyname": "Acme Tool & Die",
"customercode": "ACME-01",
"invoiceterms": "Net 30",
"creditlimit": "25000.0000",
"currency": "USD",
"cancel": false
}
],
"page": 1,
"perpage": 3,
"total": 214
}
If that worked, your token, its company and its scopes are all correct, and everything else is just more endpoints.
3. Write something#
Creating a customer is the safest first write: no ledger impact, easy to clean up.
curl -X POST 'https://acme.nolapro.com/!/api/v2/customers' \ -H "Authorization: Bearer $NP_TOKEN" \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: quickstart-001' \ -d '{ "companyname": "Bridgewater Fabrication", "customercode": "BRIDGE-01", "email1": "ap@bridgewater.example", "invoiceterms": "Net 30" }'
Two things in that body are worth copying carefully. The address field is email1, not email - customers carry two - and invoiceterms resolves against the term's own wording, so it is "Net 30", not "NET30". Get either wrong and you get a 400 or a 422 that names the field; see Pointing at another record.
A 201 returns the created record with its id. Send the exact same request again with the same Idempotency-Key and you get the same 201 and the same record back, not a duplicate customer. That is worth internalising now, before you are creating invoices.
One more thing worth knowing early: a parent and its children go in one request. A project carries its milestones and tasks, and an invoice carries its lines — created together, in one transaction, with no ids to juggle. See Conventions.
4. Handle the failure case#
Try it once more with a different key and the same customercode:
{
"error": {
"code": "duplicate",
"message": "customercode \"BRIDGE-01\" is already in use.",
"field": "customercode"
}
}
Every error has this shape. code is stable and safe to branch on. message is for humans and may be reworded. field tells you where to look. Do not parse message.
What to read next#
- Authentication for scopes, rotation, and what the 401s mean
- Conventions before you write any money or date handling
- Recipes for whole tasks, like syncing a storefront's orders nightly