Skip to Content
SimulatorsQuickBooks OnlineTransactions and list entities

Simulators

Transactions and list entities

The list entities (Vendor, Employee, Item, Account, Class, Department, Term and PaymentMethod) and the fourteen transactions, from Invoice to Transfer, share one envelope and one write pattern (Ids and writes). The scenarios seed no list entity or transaction, so create what a transaction references first.

Reference other records

The simulator checks the records a body references, such as a line’s ItemRef, and returns 400 610 naming an unknown one. This block creates an income account, an item that sells into it and an invoice for three of the item:

R=4620816365320737870
curl -s "$RYSTIC_URL/v3/company/$R/account" -H 'Authorization: Bearer placeholder' -H 'Content-Type: application/json' -d '{"Name":"Sales","AccountType":"Income"}' | jq -c '.Account | {Id, Name, SyncToken}'
# -> {"Id":"1","Name":"Sales","SyncToken":"0"}
curl -s "$RYSTIC_URL/v3/company/$R/item" -H 'Authorization: Bearer placeholder' -H 'Content-Type: application/json' -d '{"Name":"Sourdough loaf","Type":"NonInventory","IncomeAccountRef":{"value":"1"},"UnitPrice":8}' | jq -c '.Item | {Id, Name, UnitPrice}'
# -> {"Id":"1","Name":"Sourdough loaf","UnitPrice":8}
curl -s "$RYSTIC_URL/v3/company/$R/invoice" -H 'Authorization: Bearer placeholder' -H 'Content-Type: application/json' -d '{"CustomerRef":{"value":"1"},"Line":[{"Amount":24,"DetailType":"SalesItemLineDetail","SalesItemLineDetail":{"ItemRef":{"value":"1"},"Qty":3,"UnitPrice":8}}]}' | jq -c '.Invoice | {Id, TotalAmt, Balance, SyncToken}'
# -> {"Id":"1","TotalAmt":24,"Balance":24,"SyncToken":"0"}

An item’s IncomeAccountRef must name an account that exists, and an invoice’s lines must name items that exist.

Differs from QuickBooks: an item with no IncomeAccountRef is accepted, where QuickBooks requires one on Service, Inventory, Assembly, Other Charge and Product items (unconfirmed).

Delete or void a transaction

To delete a transaction, send POST …/<entity>?operation=delete with its Id and SyncToken. The response has "status":"Deleted", and a later read of that Id returns 400 610. Invoice, Payment, SalesReceipt and BillPayment can also be voided:

TransactionVoid request
InvoicePOST …/invoice?operation=void
Payment, SalesReceipt and BillPaymentPOST …/<entity>?include=void&operation=update

This block records a payment against the invoice, which settles its Balance and raises its SyncToken (Amounts), then voids the invoice and deletes the payment:

curl -s "$RYSTIC_URL/v3/company/$R/payment" -H 'Authorization: Bearer placeholder' -H 'Content-Type: application/json' -d '{"CustomerRef":{"value":"1"},"TotalAmt":30,"Line":[{"Amount":24,"LinkedTxn":[{"TxnId":"1","TxnType":"Invoice"}]}]}' | jq -c '.Payment | {Id, TotalAmt, UnappliedAmt}'
# -> {"Id":"1","TotalAmt":30,"UnappliedAmt":6}
curl -s "$RYSTIC_URL/v3/company/$R/invoice/1" -H 'Authorization: Bearer placeholder' | jq -c '.Invoice | {Id, Balance, SyncToken}'
# -> {"Id":"1","Balance":0,"SyncToken":"1"}
curl -s "$RYSTIC_URL/v3/company/$R/invoice?operation=void" -H 'Authorization: Bearer placeholder' -H 'Content-Type: application/json' -d '{"Id":"1","SyncToken":"1"}' | jq -c '.Invoice | {Id, TotalAmt, PrivateNote, SyncToken}'
# -> {"Id":"1","TotalAmt":0,"PrivateNote":"Voided","SyncToken":"2"}
curl -s "$RYSTIC_URL/v3/company/$R/payment?operation=delete" -H 'Authorization: Bearer placeholder' -H 'Content-Type: application/json' -d '{"Id":"1","SyncToken":"0"}' | jq -c '.Payment'
# -> {"Id":"1","domain":"QBO","status":"Deleted"}

A void sets the transaction’s amounts to 0 and empties a Payment’s or BillPayment’s lines. It writes Voided in PrivateNote, before any note already there.

Ids and writes

Creating a record sets SyncToken to "0". A write that names an Id and the current SyncToken updates the record and raises its SyncToken; a stale one is refused (Idempotency). Error format covers refusals, and Auth a request with no token.

Amounts

TransactionTotalAmt
Paymentthe TotalAmt you send, or 0; UnappliedAmt is what its lines leave unapplied
Estimate and BillPaymentthe TotalAmt you send, or the sum of its lines
JournalEntrythe sum of its debit lines, which must equal its credit lines
Transfernone: it has one Amount
every other transactionthe sum of its lines, whatever you send; an Invoice whose lines hold no detail line keeps the TotalAmt you send, else the one it had, or 0

A payment moves the balances it touches:

  • Each line pays the first invoice its LinkedTxn names. That invoice loses the line’s Amount from its Balance, lists the payment in its own LinkedTxn and raises its SyncToken.
  • Its customer’s Balance drops by its TotalAmt.
  • Deleting or voiding the payment reverses both, and raises the invoice’s SyncToken again.

An invoice adds its Balance to its customer’s, and deleting or voiding it takes off what it was billed. A payment that paid it stays, now unapplied: its lines that paid the invoice are dropped, their amount moves to UnappliedAmt, and its SyncToken rises.

This block bills customer 1 for 40, pays 25 of it, deletes the payment, pays 30 with 25 applied and then voids the invoice, reading the balances after each step. The customer ends 30 lower than it started: the voided invoice bills nothing, and the second payment stays as unapplied credit.

curl -s "$RYSTIC_URL/v3/company/$R/customer/1" -H 'Authorization: Bearer placeholder' | jq -c '.Customer | {Id, Balance}'
# -> {"Id":"1","Balance":239}
curl -s "$RYSTIC_URL/v3/company/$R/invoice" -H 'Authorization: Bearer placeholder' -H 'Content-Type: application/json' -d '{"CustomerRef":{"value":"1"},"Line":[{"Amount":40,"DetailType":"SalesItemLineDetail","SalesItemLineDetail":{"ItemRef":{"value":"1"},"Qty":5,"UnitPrice":8}}]}' | jq -c '.Invoice | {Id, Balance}'
# -> {"Id":"2","Balance":40}
curl -s "$RYSTIC_URL/v3/company/$R/customer/1" -H 'Authorization: Bearer placeholder' | jq -c '.Customer | {Id, Balance}'
# -> {"Id":"1","Balance":279}
curl -s "$RYSTIC_URL/v3/company/$R/payment" -H 'Authorization: Bearer placeholder' -H 'Content-Type: application/json' -d '{"CustomerRef":{"value":"1"},"TotalAmt":25,"Line":[{"Amount":25,"LinkedTxn":[{"TxnId":"2","TxnType":"Invoice"}]}]}' | jq -c '.Payment | {Id, TotalAmt, UnappliedAmt}'
# -> {"Id":"2","TotalAmt":25,"UnappliedAmt":0}
curl -s "$RYSTIC_URL/v3/company/$R/invoice/2" -H 'Authorization: Bearer placeholder' | jq -c '.Invoice | {Id, Balance, SyncToken, LinkedTxn}'
# -> {"Id":"2","Balance":15,"SyncToken":"1","LinkedTxn":[{"TxnId":"2","TxnType":"Payment"}]}
curl -s "$RYSTIC_URL/v3/company/$R/customer/1" -H 'Authorization: Bearer placeholder' | jq -c '.Customer | {Id, Balance}'
# -> {"Id":"1","Balance":254}
curl -s "$RYSTIC_URL/v3/company/$R/payment?operation=delete" -H 'Authorization: Bearer placeholder' -H 'Content-Type: application/json' -d '{"Id":"2","SyncToken":"0"}' | jq -c '.Payment.status'
# -> "Deleted"
curl -s "$RYSTIC_URL/v3/company/$R/invoice/2" -H 'Authorization: Bearer placeholder' | jq -c '.Invoice | {Id, Balance, SyncToken, LinkedTxn}'
# -> {"Id":"2","Balance":40,"SyncToken":"2","LinkedTxn":[]}
curl -s "$RYSTIC_URL/v3/company/$R/customer/1" -H 'Authorization: Bearer placeholder' | jq -c '.Customer | {Id, Balance}'
# -> {"Id":"1","Balance":279}
curl -s "$RYSTIC_URL/v3/company/$R/payment" -H 'Authorization: Bearer placeholder' -H 'Content-Type: application/json' -d '{"CustomerRef":{"value":"1"},"TotalAmt":30,"Line":[{"Amount":25,"LinkedTxn":[{"TxnId":"2","TxnType":"Invoice"}]}]}' | jq -c '.Payment | {Id, UnappliedAmt}'
# -> {"Id":"3","UnappliedAmt":5}
curl -s "$RYSTIC_URL/v3/company/$R/customer/1" -H 'Authorization: Bearer placeholder' | jq -c '.Customer | {Id, Balance}'
# -> {"Id":"1","Balance":249}
curl -s "$RYSTIC_URL/v3/company/$R/invoice?operation=void" -H 'Authorization: Bearer placeholder' -H 'Content-Type: application/json' -d '{"Id":"2","SyncToken":"3"}' | jq -c '.Invoice | {Id, TotalAmt, Balance}'
# -> {"Id":"2","TotalAmt":0,"Balance":0}
curl -s "$RYSTIC_URL/v3/company/$R/payment/3" -H 'Authorization: Bearer placeholder' | jq -c '.Payment | {Id, UnappliedAmt, SyncToken, Line}'
# -> {"Id":"3","UnappliedAmt":30,"SyncToken":"1","Line":[]}
curl -s "$RYSTIC_URL/v3/company/$R/customer/1" -H 'Authorization: Bearer placeholder' | jq -c '.Customer | {Id, Balance}'
# -> {"Id":"1","Balance":209}

Request ids

Replay support for requestid varies by entity (Idempotency).

Last updated on