GL transactions

Direct journal entries. The most powerful endpoint here, and the one with the strictest rules.

Ledger rule

A transaction set must balance: the signed amounts must sum to exactly zero. An unbalanced set is rejected with 422 gl_set_unbalanced and nothing is written.

Ledger rule

A set needs at least two lines. A one-line journal entry is not a journal entry.

The object#

FieldTypeDescription
idread-onlyintegerNolaPro id.
voucherstring(50)Voucher number identifying the entry set.
descriptionstring(50)Description of the journal entry.
commentsstring(50)Free-form comments on the entry.
wherefromintegerModule that wrote the voucher: 1 = AP, 2 = AR, 3 = GL journal entry, 4 = inventory, 6 = payroll.
statusread-onlyinteger0 = unposted, 1 = posted, 2 = year-end closing entry.
cancelbooleanCancelled. NolaPro cancels rather than deletes, so a cancelled row is still readable.
standardsetbooleanTrue when the voucher is a recurring standard journal set - a template that generates entries, not a posted entry itself.
entrydatestringWhen the record was created.
posteddateread-onlystringWhen the voucher was posted.
post2datestringThe GL period the entry landed in.
lastchangedateread-onlystringLast modification. Drives modifiedsince.
postuseridintegerPostuserid. Id only.
postuserstring(50)The name of the referenced genusers, instead of the id. Send this or postuserid, not both unless they agree.
bankdepositidintegerBankdepositid. Id only.
referencetablestring(255)Table of the document that produced the voucher (arinvoice, apbill, ...); empty for manual journal entries.
referenceidintegerReferenceid. Id only.
tajbooleanA year-end tax adjusting entry. These are allowed into a closed MONTH, but never a closed year.
canceledbyvoucheridintegerCanceledbyvoucherid. Id only.
canceledbyvoucherstring(50)The voucher of the referenced gltransactions, instead of the id. Send this or canceledbyvoucherid, not both unless they agree.
cancelsvoucheridintegerCancelsvoucherid. Id only.
cancelsvoucherstring(50)The voucher of the referenced gltransactions, instead of the id. Send this or cancelsvoucherid, not both unless they agree.
reversedbyvoucheridintegerReversedbyvoucherid. Id only.
reversedbyvoucherstring(50)The voucher of the referenced gltransactions, instead of the id. Send this or reversedbyvoucherid, not both unless they agree.
reversesvoucheridintegerReversesvoucherid. Id only.
reversesvoucherstring(50)The voucher of the referenced gltransactions, instead of the id. Send this or reversesvoucherid, not both unless they agree.
standardsetperiodendsstringDate the recurrence stops.
standardsetperiodendscountintegerStop after this many recurrences.
standardsetperiodstartsstringDate the recurrence starts.
standardsetperiodtypeintegerHow the standard set recurs: 0 = manually as needed, 1 = daily, 2 = weekly, 3 = monthly, 4 = yearly.
standardsetperiodvalueintegerRecurs every X days/weeks/months/years - this is the X.
standardsetposthowbooleanTrue posts the generated entries as one set; false posts them individually.
entrydayread-onlystringEntry date as a plain date, derived from entrydate for period math. Maintained by the model, so it cannot be written through the API.
entrymonthread-onlystringFirst day of the entry month, derived from entrydate for period math. Maintained by the model, so it cannot be written through the API.
standardsetzeroactivepost2periodread-onlyintegerSTORED GENERATED in the database. Read-only - MySQL computes it.
externalidstring(100)Your own key. Scoped to your company.
linesarray of GlLine

Endpoints#

GET/gltransactions/{id}/lines 200422

The lines of one journal voucher.

Every debit and credit the voucher wrote. /gltransactions publishes the voucher header - who wrote it, when, what it totals. This is what it actually did to the ledger, which is what reconciliation and trial-balance work needs. Amounts are signed and the lines of one voucher sum to zero. The rows carry no company of their own; they are scoped through the voucher, so a voucher in another company answers 404 rather than an empty page.

Requires scope gltransactions:read.

Parameters
NameInTypeNotes
idrequiredpathintegerThe voucher id.
When it fails
StatusCodeMeaning
422unknown_valueNo such parent record in this company. The same answer whether it does not exist or belongs to someone else, so a caller cannot probe another company's ids.
curl \
  'https://acme.nolapro.com/!/api/v2/gltransactions/104/lines' \
  -H 'Authorization: Bearer $NP_TOKEN'
POST/gltransactions 201400422

Post a journal entry.

Writes and posts a balanced journal entry in one transaction. This is the strictest endpoint in the API, and deliberately so - an unbalanced or half-written set makes the trial balance wrong and keeps it wrong. Every rule below is checked before anything is written: | Rule | Refusal | |---|---| | The signed amounts sum to exactly zero | 422 gl_set_unbalanced, with the difference | | At least two lines | 400 invalid_request | | Every account exists in your company | 422 unknown_value, naming the line | | The period is open | 422 period_closed | | Amounts are decimal strings | 400 invalid_type | Idempotency-Key matters more here than anywhere else: a retry after a lost response must not post the entry twice.

Requires scope gltransactions:write.

Parameters
NameInTypeNotes
Body
FieldTypeDescription
daterequiredrequest-onlystringThe date the entry posts. Determines the GL period, so posting a July-dated entry in August is normal; posting into a closed period is refused with 422 period_closed. Request-only: stored as post2date (the period) and entrydate.
memorequest-onlystring(50)Header description, stored as gltransvoucher.description. Request-only: stored as description.
commentsrequest-onlystring(50)
voucherrequest-onlystring(50)Your own voucher number. NolaPro assigns one when you leave it out.
tajrequest-onlybooleanA year-end tax adjusting entry. These are allowed into a closed MONTH, but never a closed year.
externalidstring(100)Your own key for this entry. Scoped to your company.
linesrequiredrequest-onlyarray of GlLineAt least two. One line is not a journal entry, even when it sums to zero.
When it fails
StatusCodeMeaning
400invalid_requestMalformed: no date, a float amount, lines missing entirely.
422conflicting_referenceAn id and its name sibling were both sent and disagree.
422gl_set_too_shortFewer than two lines. A one-sided entry is not a journal entry.
422gl_set_unbalancedThe signed amounts do not sum to zero.
422period_closedThe GL period containing the date is closed.
422unknown_valueA reference did not resolve in this company.
curl -X POST \
  'https://acme.nolapro.com/!/api/v2/gltransactions' \
  -H 'Authorization: Bearer $NP_TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: your-unique-key' \
  -d '{
    "date": "2026-08-01",
    "lines": [
        {
            "amount": "125.0000"
        }
    ]
}'
Response 201
{
    "lines": [
        []
    ]
}
GET/gltransactions 200

Journal entries.

Vouchers in this company, newest id first. The lines are on /glaccounts/{id}/activity.

Requires scope gltransactions:read.

Parameters
NameInTypeNotes
pagequeryinteger
perpagequeryinteger
cancelquerystringDefaults to false, which hides cancelled records. Pass true for only cancelled, or any for both.
externalidquerystringLook up by your own key instead of by id. Unique per company and per system tag.
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.
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.
curl \
  'https://acme.nolapro.com/!/api/v2/gltransactions' \
  -H 'Authorization: Bearer $NP_TOKEN'
Response 200
{
    "lines": [
        {
            "amount": "125.0000"
        }
    ]
}
GET/gltransactions/{id} 200404

One journal entry.

The voucher a POST created. Its Location header points here.

Requires scope gltransactions:read.

Parameters
NameInTypeNotes
idrequiredpathinteger
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 voucher with that id.
curl \
  'https://acme.nolapro.com/!/api/v2/gltransactions/104' \
  -H 'Authorization: Bearer $NP_TOKEN'
Response 200
{
    "lines": [
        {
            "amount": "125.0000"
        }
    ]
}
DELETE/gltransactions/{id} 200409422

Reverse a journal entry.

Unposts the entry, which writes the reversing lines, then cancels the voucher. The ledger keeps both, which is the point. There is no PATCH. You do not amend a posted journal entry - you reverse it and post a correct one. An endpoint that edited a posted entry would be a way to make the trial balance disagree with its own history. Idempotent: an entry that is already cancelled returns 200 and changes nothing. The reversal posts into the CURRENT period, so that is the period which must be open, not the one the original landed in.

Requires scope gltransactions:cancel.

Parameters
NameInTypeNotes
idrequiredpathintegerThe voucher id.
When it fails
StatusCodeMeaning
409cannot_cancelNolaPro refused to reverse it. message carries its reason.
422period_closedThe current GL period is closed, so the reversal has nowhere to post.
422unknown_valueNo such voucher in this company.
curl -X DELETE \
  'https://acme.nolapro.com/!/api/v2/gltransactions/104' \
  -H 'Authorization: Bearer $NP_TOKEN'
Response 200
{
    "voucher": "Example voucher",
    "cancelled": false,
    "unposted": false,
    "lines": 1
}
GET/gltransactions/{id}/pdf 200

Journal entry as a PDF

The journal entry behind a voucher, with both sides of every line. Answers application/pdf, not JSON. Because the body is binary it cannot be carried inside a /batch results array; asking for it there returns 415 not_batchable.

Requires scope gltransactions:read.

Parameters
NameInTypeNotes
idrequiredpathinteger
curl \
  'https://acme.nolapro.com/!/api/v2/gltransactions/104/pdf' \
  -H 'Authorization: Bearer $NP_TOKEN'
GET/gltransactions/incomestatement 200

Income statement as a PDF

The profit and loss statement for a period. Defaults to the year to date. Answers application/pdf, not JSON. Because the body is binary it cannot be carried inside a /batch results array; asking for it there returns 415 not_batchable.

Requires scope gltransactions:read.

Parameters
NameInTypeNotes
begindatequerystringStart of the period, YYYY-MM-DD. Defaults to 1 January.
enddatequerystringEnd of the period, YYYY-MM-DD. Defaults to today.
curl \
  'https://acme.nolapro.com/!/api/v2/gltransactions/incomestatement' \
  -H 'Authorization: Bearer $NP_TOKEN'