Docs
/
EN DE

Book a vendor bill

This recipe books a supplier’s bill into accounts payable. It is the most common integration: an expense tool, a procurement system or a script sending bills to neoo.

The example is a Swisscom phone bill for CHF 120.00 plus 8.1% VAT, due at the end of the month. It uses the account numbers of the standard neoo Swiss chart of accounts. Yours may differ, and step 2 shows how to look them up.

You need: an API key whose user’s role includes Vendors → Postings → Vendor Transaction. See Getting started.

1. Identify the vendor

Every bill needs a vendor that already exists in neoo. If you store the neoo vendor number in your own system, skip the lookup and send vendornumber in step 3.

Otherwise, search by name:

curl "https://apineo.z83.ch/client/acme/arap/vendor?name=swisscom" \
  -H "X-API-Key: ak_your_key_here"
[
  {
    "id": 1001,
    "name": "Swisscom (Schweiz) AG",
    "vendornumber": "V-1042",
    "city": "Bern",
    "country": "CH"
  }
]

No match? Create the vendor with POST /arap/vendor. The street name goes in address1 and the house number in street: Swiss payment files need them separately.

2. Look up accounts and tax

A bill line needs two account numbers:

  • the expense account the cost is booked to, here 6510 Telecommunications
  • the tax account for the VAT, here 11700 Input VAT 8.1%

The bill as a whole also needs the accounts payable account (recordAccount), here 2000 Trade accounts payable.

Get the chart once and cache it. Accounts usable on vendor bills carry AP_amount in their link, and payable accounts carry AP:

curl https://apineo.z83.ch/client/acme/system/chart/accounts \
  -H "X-API-Key: ak_your_key_here"

For tax rates and their accounts:

curl https://apineo.z83.ch/client/acme/system/taxes \
  -H "X-API-Key: ak_your_key_here"

3. Book the bill

Send the bill to POST /arap/transaction/vendor. Leave out pending, and it is saved as a draft for someone to review in the app:

curl -X POST https://apineo.z83.ch/client/acme/arap/transaction/vendor \
  -H "X-API-Key: ak_your_key_here" \
  -H "Content-Type: application/json" \
  -d @bill.json
{
  "type": "transaction",
  "vendor_id": 1001,
  "documentNumber": "SC-2026-448812",
  "invDate": "2026-09-01",
  "dueDate": "2026-09-30",
  "curr": "CHF",
  "recordAccount": "2000",
  "description": "Mobile subscription September",
  "lines": [
    {
      "account": "6510",
      "description": "Business mobile, 4 lines",
      "amount": 120.00,
      "taxAccount": "11700"
    }
  ]
}

The response is the new transaction’s id:

{ "id": 15659 }

A few things to note:

  • documentNumber is the vendor’s own invoice number. Always send it: it is searchable in the app and lets you find the bill again (see step 5).
  • invNumber is neoo’s own document number. Leave it out and neoo takes the next one from the company’s number sequence.
  • Tax is calculated from taxAccount: 8.1% of 120.00 = 9.72, so the bill totals 129.72. If the vendor’s bill shows a slightly different tax because of rounding, send their figure as taxAmount on the line.
  • Amounts are net unless you send "taxincluded": true. With it, amount is the gross amount and the tax is taken out of it.
  • Currency is curr. For a foreign-currency bill, also send exchangerate.

Attach the PDF

Add the original bill in the same request, so reviewers see it next to the entry. Send it as a base64 data URI in files:

{
  "type": "transaction",
  "vendor_id": 1001,
  "…": "…",
  "files": [
    { "name": "swisscom-2026-09.pdf", "data": "data:application/pdf;base64,JVBERi0xLjcK…" }
  ]
}

On the command line, base64 -w0 swisscom-2026-09.pdf produces the part after base64,. If you prefer not to base64-encode, send the request as multipart/form-data with one files part per file.

4. Approve: now or later

Later (recommended). The draft appears on a workstation in the app. A person checks it against the PDF and approves it. Your integration doesn’t need to do anything else.

Now. If the integration itself is trusted to post, add "pending": "0" to the request in step 3. The bill is posted straight away, subject to the company’s approval rules: if the user behind your key may only approve up to a certain amount, a larger bill is refused with amount_exceeded.

Approve an existing draft. Send the complete transaction again, with "pending": "0", to the approve endpoint:

curl -X POST https://apineo.z83.ch/client/acme/arap/transaction/vendor/15659/approve \
  -H "X-API-Key: ak_your_key_here" \
  -H "Content-Type: application/json" \
  -d @bill-approved.json

The approve endpoint saves the body you send before posting it. Send the full transaction, not just the id, and include "pending": "0".

5. Check the result

Read the transaction back to see what was booked, including the calculated tax and the attached files:

curl https://apineo.z83.ch/client/acme/arap/transaction/vendor/15659 \
  -H "X-API-Key: ak_your_key_here"

To find bills by the vendor’s number instead of by id:

curl "https://apineo.z83.ch/client/acme/arap/transactions/vendor?document_number=SC-2026-448812" \
  -H "X-API-Key: ak_your_key_here"

Pay it

To have neoo include the bill in the next bank payment file, send "payment_file": 1 and the vendor’s bank account as vc_bank_id when you book it. The Bank Payments endpoints in the reference cover the rest of the flow.

When it fails

You get Because Fix
400 vc_not_found vendornumber matched no vendor Look the vendor up, or create it (step 1).
400 about curr Currency isn’t three letters, or you sent currency Send "curr": "CHF".
422 closed_period invDate is in a closed period Ask the accountant, or use a date after the close.
400 amount_exceeded You approved a bill above the user’s limit Send it as a draft instead.

The full list is on Errors.