Purchasing API notes
There is one API for the whole platform. There is no separate Purchasing API and no separate host for it. For the path grammar, access endpoints, authentication, paging, response envelopes and error codes, see the developer integration path.
Integrate an external system →
The document types this module produces
All of them are generic documents, reachable through the generic document endpoints by their server document type:
INTERNAL_PURCHASE_REQUISITION · INTERNAL_PURCHASE_QUOTATION · INTERNAL_BLANKET_PURCHASE_ORDER ·
INTERNAL_PURCHASE_ORDER · INTERNAL_PURCHASE_GOODS_RECEIVED_NOTE · INTERNAL_PURCHASE_GRN_STOCK_IN ·
INTERNAL_PURCHASE_GOODS_ISSUED_NOTE · INTERNAL_PURCHASE_INVOICE ·
INTERNAL_PURCHASE_INVOICE_NO_STOCK_IN · INTERNAL_PURCHASE_RETURN · INTERNAL_PURCHASE_DEBIT_NOTE ·
INTERNAL_PURCHASE_CREDIT_NOTE · INTERNAL_PURCHASE_REFUND_NOTE ·
INTERNAL_PURCHASE_CONSIGNMENT_ORDER · INTERNAL_PURCHASE_CONSIGNMENT_GRN ·
INTERNAL_PURCHASE_CONSIGNMENT_GIN · INTERNAL_PURCHASE_CONSIGNMENT_RETURN ·
INTERNAL_PURCHASE_CONSIGNMENT_INVOICE
Each applet’s reference page names the four API permissions its document type needs.
Consignor Purchase Billing is not a generic document. It writes its own billing tables through
its own resource; there is no FINAL, no journal and no open queue behind it. The Supplier Delivery
Order applet writes the tenant’s ordinary INTERNAL_OUTBOUND_DELIVERY_ORDER, not a purchase type.
How knock-off looks from outside
Knock-off is two tables, not a field. When a document goes FINAL, a processor reads the company’s knock-off configuration and writes one line open-queue row per line for each enabled downstream type, carrying the open quantity. A downstream document that knocks a line off writes a document link between the two and reduces the queue row’s open quantity.
Three consequences for an integration:
- A document you create through the API is knocked off by writing the link, not by naming the source on the new document. Read the source’s open-queue rows first; a fully knocked-off line has no open quantity and must not be linked again.
- The queue exists only where the configuration says so. A finalised order in a company with no order → GRN row has no queue rows, and nothing downstream can find it.
- Two backend converters copy a receipt into its invoice — plain GRN → Purchase Invoice, and GRN Stock In → No Stock In invoice — with the links already written. The company’s document-flow configuration decides whether they run and whether the result is DRAFT or FINAL. If you post invoices yourself, make sure the auto-convert is off for that pair, or you will get two.
Two things an integration must respect
The signums are the server’s, not yours. A document type’s quantity and amount signums are fixed in the backend, and the applet’s own copy is overwritten on every save. Sending a quantity signum of +1 on a plain GRN changes nothing; if you need the receipt to move stock you post a GRN Stock In, and you then bill with a No Stock In invoice. The receiving pair is a document-type choice, and an integration that mixes the pairs double-counts exactly as a user does.
Posting is asynchronous. Setting a purchase invoice to FINAL queues the work: one processor writes the journal, another the stock ledger lines, others the tax, cashbook and e-Invoice queues. An integration that finalises and immediately reads the supplier’s balance or the stock balance can legitimately see the old figure. Poll the document’s posting statuses — Journal, Inventory, Tax — or subscribe to the webhook, rather than reading straight back. A journal that fails (a missing default GL code, most often) leaves the document FINAL with that status unposted; for a GRN Stock In the stock is already in.
What the API will not do for you
There is no matching endpoint, no tolerance check and no approval gate. An invoice posted with a price different from its knocked-off order finalises. If you need a variance rule, it lives in your system before you post.