Purchases
Purchases (sometimes called bills or vendor invoices) record what your organization owes to suppliers. Each purchase stores the supplier contact, currency, due date, line-level expense accounts, VAT, and payment status. This guide covers the public GraphQL operations you can call to import purchase data, sync statuses, or issue payments from your own back office tools.
Authenticate with an API secret or OAuth-issued secret as described in the Authentication guide, then include the organization slug on every query or mutation.
Core objects
Purchase
| Field | Type | Description |
|---|---|---|
id | ID! | Stable identifier for follow-up mutations. |
number | Int! | Auto-incremented sequence, unique per organization. |
date | Date! | Posting date used for ledgers and reporting. |
dueDate | Date! | Required for credit purchases; equals date for cash purchases. |
status | PurchaseStatus! | draft, active, paid, partial, or voided. |
paymentStatus | String | Derived indicator in the UI (unpaid, overdue, etc.). |
total / subtotal / vat | String | Decimal strings in the organization's base currency. |
remainder | String | Outstanding balance (negative numbers represent amounts still owed). |
currency / exchangeRate | String | Original document currency and applied exchange rate. |
originalTotal | String | Total expressed in the original currency. |
contact | Contact | Supplier info (name, email, address). |
lines | [PurchaseLine!]! | Ledger distribution for the expense and VAT. |
journalEntries | [JournalEntry!] | Ledger postings created for the purchase and any payments. |
PurchaseLine
| Field | Type | Description |
|---|---|---|
id | ID! | Line identifier. |
description | String! | Human-readable text shown on the document. |
cost | String! | Decimal cost in purchase currency. |
accountId | ID! | Expense or asset account to debit. |
vatId | ID | Optional VAT code applied to the line. |
Status and type rules
PurchaseTypevalues arecash(immediately paid from a bank or cash account) andcredit(posted to accounts payable).- New purchases can only be created as
draftoractive. Drafts can be edited; active purchases represent posted payables. - Voiding a purchase sets
statustovoidedand voids all related journal entries.
Query purchases
Fetch a single purchase
query Purchase($id: ID!) {
purchase(purchaseID: $id) {
id
number
status
currency
total
remainder
contact {
id
name
email
}
lines {
id
description
cost
account {
id
name
code
}
}
journalEntries {
id
number
date
}
}
}
Use this to display all metadata for reconciliation or auditing tools.
List purchases with filters
query Purchases($slug: Slug!, $filter: JSONObject) {
organization(slug: $slug) {
purchases(
limit: 50
orderBy: { field: "due_date", order: ASC }
filter: $filter
) {
count
entries {
id
number
date
dueDate
status
contact {
name
}
total
remainder
}
}
}
}
Filters accept the standard operators (equalTo, notEqualTo, lessThan, greaterThanOrEqualTo, in, plus and/or). Common fields include status, contactId, due_date, and currency. The orderBy object supports any column on the underlying purchase (for example created_at, date, or due_date). Max page size is 1,000 entries.
Create and update purchases
Create
mutation CreatePurchase($input: CreatePurchaseInput!) {
createPurchase(input: $input) {
id
number
status
total
remainder
}
}
CreatePurchaseInput fields:
| Field | Required | Notes |
|---|---|---|
slug | ✅ | Organization identifier tied to the API secret. |
type | ✅ | cash requires accountId; credit posts to accounts payable. |
date | ✅ | Posting date; dueDate defaults to this when type is cash. |
dueDate | ⚠️ | Required for credit purchases. |
contactId | ⚠️ | Optional but recommended for tracking suppliers. |
accountId | ⚠️ | Expense account for cash purchases (the credit side of the journal entry). |
currency / exchangeRate | ⚠️ | Default to the org base currency when omitted. Provide both for multi-currency docs. |
status | ✅ | Must be draft or active. |
lines | ✅ | At least one PurchaseLineInput with cost, description, and accountId. |
docs | ⚠️ | Array of existing document IDs (from createDoc) to attach receipts. |
Update
mutation UpdatePurchase($input: UpdatePurchaseInput!) {
updatePurchase(input: $input) {
id
status
dueDate
lines {
id
description
cost
}
}
}
Updates are only allowed while status = draft. To revise a posted document, void it and re-create it. When sending new lines, the mutation replaces every existing line item, so always send the complete set.
Pay purchases
Use payPurchase when you record an actual bank disbursement or cash payment.
mutation PayPurchase($input: PayPurchaseInput!) {
payPurchase(input: $input) {
id
number
remainder
journalEntries {
id
date
}
}
}
PayPurchaseInput fields:
| Field | Required | Notes |
|---|---|---|
purchaseId | ✅ | Target purchase ID. |
amount | ✅ | Decimal string (positive numbers reduce the payable). Partial payments are supported. |
accountId | ⚠️ | Credit account used for the payment (cash or bank). Defaults to the organization's defaultBankAccount if omitted. |
date | ⚠️ | Defaults to the current date. |
currency / exchangeRate | ⚠️ | Provide when paying in a currency different from the purchase currency. Exchange gains/losses are posted automatically. |
comment | ⚠️ | Optional narration shown on the journal entry. |
Naqood automatically posts the debit to the selected cash/bank account and the credit to accounts payable. When you pay in another currency, the system routes any gain or loss to the configured exchange-rate accounts.
Void purchases
mutation DeletePurchase($id: ID!) {
deletePurchase(purchaseId: $id)
}
deletePurchase voids the purchase and every associated journal entry. Only non-voided purchases can be voided. Use this for mistakes rather than archival; the purchase ID remains but its status becomes voided.