How an FB60 mass upload works
FB60 in SAP is the transaction for entering a vendor invoice without a purchase order: one vendor line for the amount owed and one or more G/L lines for the expense. PostNow.ai does an FB60 mass upload from Excel through BAPI_ACC_DOCUMENT_POST, with one header row per invoice and one detail row per G/L line, so a whole file of non-PO invoices posts in one run. Validate checks the sheet, Simulate lets SAP check every invoice and rolls it back, and Run writes each accounting document number back to its row.
- The BAPI does not calculate tax. Unlike the FB60 screen, the interface has no "calculate tax" option: a taxed invoice needs its tax line passed with the amount, or SAP rejects the balance.
- Check duplicates before the run. SAP KBA 2389365 states that the duplicate invoice check (message F5 117) is not raised for invoices posted through
BAPI_ACC_DOCUMENT_POST, so compare supplier references with SAP first.
This page covers one job: posting vendor invoices that have no purchase order, in bulk, from Excel. Invoices that refer to a purchase order belong in MIRO mass invoice posting, G/L-only journals with no vendor belong in FB50 mass upload, and the wider AP process from invoice receipt to payment is covered in SAP accounts payable automation.
How PostNow.ai posts FB60 invoices from Excel
PostNow.ai treats an FB60 mass upload as a template: a designer builds it once against your SAP system and publishes it, and AP clerks run their own invoice files through it, each under their own SAP login on their own computer.
- Start from the template or the BAPI. Download the free FB60 vendor invoice template, whose columns are already mapped to
BAPI_ACC_DOCUMENT_POST, or search forBAPI_ACC_DOCUMENT_POSTby name in PostNow.ai's BAPI search and let Mapping AI match your own column headers to its fields. Choose that BAPI, notBAPI_INCOMINGINVOICE_CREATE, which is MIRO's and needs purchase order lines. - Group the header and the lines. A marker column turns one
Hrow (company code, dates, document type, supplier reference, vendor, gross amount, payment terms) and itsDrows (G/L account, amount, cost object) into one invoice. A grouping key such asVI-0001keeps the rows of one invoice together. - Validate the sheet. Validate checks every cell offline: required fields, type, length, date format, decimals and allowed values, such as an allow-list of document types or tax codes. Whether a vendor, account or period is valid is SAP's answer, and SAP gives it in Simulate.
- Simulate. PostNow.ai calls the BAPI for every invoice and then
BAPI_TRANSACTION_ROLLBACKinstead of a commit, so SAP's own messages (balance, closed period, missing cost object, blocked vendor) appear per invoice and nothing posts. - Run. For each invoice PostNow.ai calls the BAPI and commits with
BAPI_TRANSACTION_COMMITonly when SAP returned no error; otherwise it rolls back. The H row gets "Accounting Document number posted successfully" by default, with user, time and SAP system. The document number is taken from the BAPI's object key, and clicking it opens the document inFB03. - Re-run only what failed. Retry Failed re-posts only the invoices marked ERROR. If someone clicks Run again on the same sheet, PostNow.ai first lists the invoices that already hold a document number and offers Skip posted rows, Post again or Cancel.
Where the business wants a second pair of eyes on a non-PO file, an approval policy on the template holds the run until an approver has reviewed the rows in the PostNow.ai portal. The approval is tied to that exact data, so a sheet changed after approval needs a new one.
How an FB60 invoice is built: vendor line and G/L lines
An FB60 invoice is one accounting document with a credit to the vendor and debits to expense accounts, and in PostNow.ai each part maps to one structure of BAPI_ACC_DOCUMENT_POST ("Accounting: Posting"). The screen hides this split; the interface does not.
| Structure | One per | Fields an FB60 upload usually fills |
|---|---|---|
DOCUMENTHEADER | Invoice | COMP_CODE, DOC_DATE (invoice date), PSTNG_DATE, DOC_TYPE (KR), REF_DOC_NO (the supplier's invoice number), HEADER_TXT, BUS_ACT = RFBU |
ACCOUNTPAYABLE | Vendor line | ITEMNO_ACC, VENDOR_NO, PMNTTRMS, BLINE_DATE, PMNT_BLOCK, PYMT_METH, ITEM_TEXT |
ACCOUNTGL | Expense line | ITEMNO_ACC, GL_ACCOUNT, TAX_CODE, COSTCENTER or ORDERID or WBS_ELEMENT, PROFIT_CTR, ITEM_TEXT |
ACCOUNTTAX | Tax code on the invoice | ITEMNO_ACC, TAX_CODE; only when the invoice carries tax |
ACCOUNTWT | Withholding tax type | ITEMNO_ACC of the vendor line, WT_TYPE, WT_CODE, base and amount where entered manually |
CURRENCYAMOUNT | Every line above | ITEMNO_ACC, CURRENCY, AMT_DOCCUR (signed), and AMT_BASE for a tax line |
| Exports | Invoice | OBJ_TYPE BKPFF and OBJ_KEY: document number, company code and fiscal year in one key, which PostNow.ai splits and writes back to the H row |
Three rules decide whether the document balances. Money never sits on the vendor or G/L line itself: every amount is a row in CURRENCYAMOUNT, joined to its line by ITEMNO_ACC, so each line of one invoice, the vendor line included, needs its own item number. The sign carries debit and credit, because the interface has no posting key: the vendor line is negative, the expense lines positive. And the lines of one invoice must add up to zero, or SAP answers with F5 702 "Balance in transaction currency".
BAPI_INCOMINGINVOICE_CREATE belongs to logistics invoice verification: it expects purchase order lines and posts what MIRO posts. A non-PO invoice goes through BAPI_ACC_DOCUMENT_POST. SAP also ships BAPI_ACC_DOCUMENT_CHECK with the same interface, which checks a document without posting it.Document type KR and the header
FB60 defaults to document type KR, the standard vendor invoice type; Customizing can set a different default per company code (Define Document Types for Enjoy Transactions). The BAPI has no transaction default, so the file sends DOC_TYPE on every H row. Put the supplier's invoice number in REF_DOC_NO, never a number of your own: it is the field SAP's duplicate check and every AP clerk searches on.
Payment terms, baseline date and payment block
In a PostNow.ai FB60 template the payment fields sit on the H row and go to the vendor line in ACCOUNTPAYABLE. They decide when the invoice is paid, so they deserve the same care as the amount.
- Payment terms (
PMNTTRMS, for exampleN030) and the baseline date (BLINE_DATE) together give the due date. Map both explicitly, then open the first posted invoice inFB03and confirm the due date is what the supplier expects. - Payment block (
PMNT_BLOCK):Ablocks the invoice for payment until AP removes it. On a file that has not been reviewed invoice by invoice, posting with a block and releasing after review keeps the liability in the books without paying it early. - Backlogs fall due at once. Two hundred invoices dated six weeks ago, posted today with 30-day terms from the invoice date, are mostly due already. Show treasury the due-date profile before the run.
Once the invoices are paid, the vendor payment history report lists each cleared vendor item with its clearing date, baseline date and payment terms, so you can see the days to pay per invoice.
Tax codes on an FB60 upload: the BAPI does not calculate tax
PostNow.ai sends exactly the lines the template maps, and BAPI_ACC_DOCUMENT_POST has no counterpart to the "Calculate tax" checkbox on the FB60 screen. Tax on a non-PO invoice is therefore a line you pass, with its amount, not a figure SAP adds for you.
| Invoice | What the file sends | The rule |
|---|---|---|
| No tax (exempt, out of scope) | Vendor line and G/L lines only, as the free template does | Gross amount = sum of the G/L lines |
| Input tax | Tax code on each G/L line, plus one ACCOUNTTAX line per tax code with its own CURRENCYAMOUNT row: tax amount in AMT_DOCCUR, taxable base in AMT_BASE | Gross amount = G/L lines + tax lines |
Work the tax out before the run, per tax code, from the net lines: in Excel with the rate your tax code carries, or in a program with SAP's CALCULATE_TAX_FROM_NET_AMOUNT. Copying the supplier's printed tax is fine only where it matches what your tax code yields; a rounding cent becomes a balance error. The free template posts invoices without a tax line, so for taxed invoices the designer adds the tax columns and confirms on Simulate that the first invoices balance.
Withholding tax on a non-PO invoice
Withholding tax rides on the vendor line. In BAPI_ACC_DOCUMENT_POST it goes in ACCOUNTWT: one row per withholding tax type, with ITEMNO_ACC pointing at the vendor line, the type in WT_TYPE and the code in WT_CODE. A base or amount entered by hand goes in BAS_AMT_TC or MAN_AMT_TC with its indicator. The vendor must already carry those types and codes in its company code data. Open the first posted invoice in FB03 and check its withholding tax data before the rest of the file runs, because a document can post with the vendor line correct and the withholding item missing.
Duplicate invoice check in FB60 and on the BAPI route
PostNow.ai stops the same sheet from posting twice with its already-posted check, and the AP Vendor Document Detail 360 report in the PostNow.ai Report Library lets AP compare a new file with the vendor invoices already in SAP. Both matter, because SAP's own duplicate check does not cover this route.
In FB60, SAP compares a new invoice with posted ones when the vendor has the Chk double inv. flag in its company code data (LFB1-REPRF). With a reference number it matches company code, vendor, currency, document date and reference; without one it matches the amount instead of the reference (SAP Help). A hit raises F5 117, usually configured as a warning that the clerk reads and decides on.
For interfaces the check is not there. SAP KBA 2389365, "Error message F5117 is not raised when the document is posted via BAPI or Idoc", describes that invoices uploaded through BAPI_ACC_DOCUMENT_POST skip the duplicate check (SAP KBA 2389365). A bulk FB60 file therefore needs its own check before the run:
- Check the file against SAP. Run AP Vendor Document Detail 360 for the company code, the vendors in the file and the last months, filtered to document type
KR. It returns each invoice's vendor, reference (XBLNR), document date and amount. ACOUNTIFSon vendor and reference marks the rows already posted. - Check the file against itself. Two copies of one invoice in the same file are both absent from SAP until the first one posts.
- Normalise before you compare, but post the supplier's real reference. "INV-0447" and "inv 0447" are one invoice. An invoice posted with a blank reference can only be matched on amount and date later.
- Re-run from the same workbook. A second Run on the same sheet offers Skip posted rows before anything is sent. A copied file with the same invoices has no Run Log, so only the SAP-side comparison protects it.
Park (FV60) or post: two ways to keep a review step
PostNow.ai can post FB60 invoices directly, post them with a payment block, or park them, and the choice is a control decision for AP, not a technical one. FV60 is the parking twin of FB60: a parked invoice is saved without updating the ledger, reviewed, and posted later in FBV0.
| Route | What the run creates | Fits when |
|---|---|---|
| Post | Posted invoices, open for payment by the terms | The file was reviewed and approved before the run |
Post with payment block A | Posted invoices that the payment run skips until the block is removed | The liability should be in the books now, payment only after review |
| Park | Parked documents, no ledger update until someone posts them in FBV0 | Your process requires approval before anything reaches the ledger |
Parking through the BAPI depends on your release. Depending on release and support package, DOCUMENTHEADER carries a DOC_STATUS field, and code samples that cite SAP Note 2092366 set it to 2 to park the document instead of posting it; parked documents are then edited or posted in FBV0 and FBV2, not through a BAPI. Check in SE37 that your system's interface has the field, and test one invoice: confirm it arrives parked, not posted, because community reports show systems where the value is ignored. Where it is not available, a PostNow.ai recording of FV60 parks invoices from the same Excel file.
When to record FB60 instead of using the BAPI
PostNow.ai can also post FB60 as a recorded transaction (BDC): you record one invoice in SHDB, map the screen fields to columns, and PostNow.ai replays the recording for every invoice. The BAPI stays the first choice for a vendor invoice, because it returns a structured result and passes no screens. A recording earns its place where the screen does something the file should not have to do, such as a customer-specific field on the FB60 screen that the BAPI would only reach through an extension.
- The item grid repeats. FB60's G/L lines sit in a table control, so a recording with several lines needs a loop over the line block. The BDC recording guide covers how to record it so it replays.
- Simulate on a recording presses FB60's own Simulate function instead of Save, so SAP runs its document check without posting. Prove it once in Debug on your system before you rely on it.
- Recording mode needs PostNow.ai's
ZPOSTNOW_*objects in SAP, installed once per system. The BAPI route needs no add-on objects: RFC access plus the user's normal FI posting authorisations.
The trade-offs between the two methods are compared in BAPI vs BDC in SAP.
Worked example: 25 non-PO invoices at month-end in company code 1010
PostNow.ai handles this with one published FB60 template and one run. AP in company code 1010 has 25 non-PO invoices to post on 30.10.2026: facility services, utilities and legal fees from nine vendors, 61 G/L lines in all, currency EUR. One invoice from vendor 100045 looks like this:
| Excel row | Invoice Ref | Columns filled |
|---|---|---|
| H | VI-0012 | Type KR, invoice date 20261027, posting date 20261030, reference FS-88412, vendor 100045, gross -1,190.00, terms N030, baseline 20261027, tax code V1, tax 190.00 on base 1,000.00 |
| D | VI-0012 | Line 2, G/L 0000470000 cleaning, cost center 1010-210, tax code V1, 650.00 |
| D | VI-0012 | Line 3, G/L 0000470000 cleaning, cost center 1010-220, tax code V1, 350.00 |
Tax code V1 carries 19% input tax in this company code, so 1,000.00 net + 190.00 tax = 1,190.00. In SAP the invoice becomes four lines (vendor, two expense lines, tax) whose amounts add up to zero.
- Duplicates. The operator runs AP Vendor Document Detail 360 for the nine vendors and the last six months. A
COUNTIFSon vendor and reference finds one utility invoice already posted in October; it comes out of the file. 24 invoices remain. - Validate. Two cells are flagged: a posting date typed as 30/10/2026 and a tax code outside the allow-list. Both are fixed in the sheet.
- Simulate. 21 invoices pass. Two return
F5 702because their tax was copied from the supplier's invoice and differs from the calculated 19% by a cent; one returnsKI 235because an expense line has no cost center. All three are corrected and pass a second Simulate. - Run. All 24 post. Each H row now holds its accounting document number, from
1900000731to1900000754, with user, time and system. - Check. The clerk opens the first invoice in
FB03from the Run Log: vendor line, two expense lines, one tax line, due date 26.11.2026.
The invoice that was already in SAP was not posted again, and every posted invoice can be traced from its Excel row to its FI document.
FB60 or MIRO: which one for a vendor invoice
Use FB60, and in PostNow.ai the BAPI_ACC_DOCUMENT_POST template, only for invoices that never had a purchase order. Whenever a purchase order exists, the invoice belongs in MIRO.
| Question | FB60 (FI vendor invoice) | MIRO (logistics invoice verification) |
|---|---|---|
| Basis | No purchase order; G/L account and cost object come from the file | Purchase order item, and the goods receipt where GR-based IV is set |
| Matching | None against an order; review happens before posting, or through parking or a payment block | Price, quantity and date against the PO; variances above tolerance block payment |
| GR/IR clearing account | Not touched | Cleared against the goods receipt |
| BAPI PostNow.ai uses | BAPI_ACC_DOCUMENT_POST | BAPI_INCOMINGINVOICE_CREATE |
| Reversal | FB08 | MR8M |
Posting a PO invoice through FB60 records the liability but leaves the purchase order open for invoicing and the goods receipt uncleared in GR/IR. PO invoices are covered in MIRO mass invoice posting.
Reverse an FB60 invoice with FB08
PostNow.ai writes each accounting document number, company code and fiscal year back to its row, which is exactly what a reversal needs. An FB60 invoice is reversed in FB08 with a reversal reason; SAP posts a reversal document and both stay visible for audit.
- Reverse, don't delete. A posted FI document cannot be deleted; a wrong invoice is reversed and, if needed, posted again correctly.
- Pick the reversal reason deliberately. The reason decides whether the reversal may post in a different period than the original. Use the reasons your FI team has configured.
- Paid invoices must be reset first. If the vendor line has been cleared, for example by a payment run,
FB08stops with a cleared-items message such asF5 802"Document … already contains cleared items - reversal not possible". Reset the clearing inFBRA, then reverse.
FB60 upload errors and the fix
PostNow.ai writes SAP's message to each failed invoice's row, so the fix starts from the message text. These are the ones a bulk FB60 run meets most:
| Message | What it means | Fix |
|---|---|---|
F5 702 Balance in transaction currency (on the interface also RW 033) | Vendor line, G/L lines and tax lines do not add up to zero | Check the signs (vendor negative), the tax amount against the tax code, and that no line lost its amount through a wrong ITEMNO_ACC |
F5 201 Posting period … is not open | The period is closed for the posting date, and periods are opened per account type in OB52 | Have FI open the period for account type K (vendors) as well as S; a period open for journals can still be closed for vendor invoices |
KI 235 Account … requires an assignment to a CO object | An expense line has no cost center, order or WBS element | Fill one real cost object on every expense line, not only the first line of each invoice |
F5 117 duplicate invoice message | Raised by FB60 on screen; not raised for the BAPI route (KBA 2389365) | Run the duplicate comparison against SAP before the run, as described above |
F5 802 Document … already contains cleared items - reversal not possible (or F5 308, same meaning) | FB08 cannot reverse an invoice whose vendor line is cleared | Reset the clearing in FBRA, then reverse |
| Run Log: UNKNOWN (PostNow.ai) | SAP's answer was lost after the invoice was sent, so it may have posted | Look the reference up in FBL1N or AP Vendor Document Detail 360 before posting the row again; Retry Failed leaves UNKNOWN rows alone |
Checklist before an FB60 mass upload
PostNow.ai checks formats and allowed values and keeps operators on the published template; this list covers the decisions that stay with AP and finance.
- No invoice in the file has a purchase order; PO invoices are in a separate MIRO file.
- The file has been compared with SAP on vendor and reference, and with itself.
- Each H row carries the supplier's real invoice number in the reference column.
- Document type is
KR(or the type your company uses for vendor invoices) on every H row. - Per invoice, vendor line + G/L lines + tax lines add up to zero, with the vendor line negative.
- Every expense line has a cost object; balance sheet lines correctly have none.
- Tax amounts are calculated from your tax codes, and withholding tax types exist on each vendor that needs them.
- The posting period is open for account type
Kon the posting date in the file. - Payment terms, baseline dates and any payment block are set, and treasury has seen the due-date profile.
- Simulate has run clean on the whole file, and the first posted invoice has been checked in
FB03.
What to plan for in an FB60 mass upload
PostNow.ai posts through SAP's accounting interface, so SAP's own account, period, tax and cost object checks decide every result.
- Run SAP's checks in Simulate. Validate checks formats, lengths and allowed values in Excel; balance, period, account and cost object checks start when SAP sees the invoice in Simulate.
- Own the duplicate check. Compare the file with the references already posted in SAP before every run, because the interface does not raise
F5 117. - Calculate tax before the run. Decide per tax code how the tax line is built, and keep that logic in the template rather than in each clerk's file.
- Agree the review step. Approval of the file before the run, a payment block, or parking: pick one per template, so every operator follows the same control.
- Keep re-runs in the same workbook. The re-post check reads this sheet's Run Log, and UNKNOWN rows are checked in SAP before anyone posts them again.
- Keep the PostNow.ai portal reachable for approved templates. The approval check runs against the portal; if the portal cannot be reached, the check lets the run through.
Making a template like this repeatable for a team (designers who build, operators who only run, a published template in the central library) is covered in Excel to SAP automation. Where FB60 sits among the other finance postings is in SAP FICO mass posting.
FB60 mass upload on S/4HANA
PostNow.ai uses the same template on S/4HANA: FB60, FV60, FB08 and BAPI_ACC_DOCUMENT_POST are all there, and SAP KBA 2389365 on the BAPI's missing duplicate check is filed for both SAP ERP and SAP S/4HANA.
- Vendors are Business Partners. The invoice still names the vendor number; payment terms, the duplicate-check flag and withholding tax data are maintained in transaction
BPin the supplier role. Creating them in bulk is covered in vendor master upload. - The document lands in the Universal Journal (
ACDOCA). The posting and the file are the same; reconciliation reports read the new table. - Re-test the configuration, not just the file. Tax codes, period variants and duplicate-check settings are company-code configuration; confirm them in the S/4HANA system before the first production run.
Free FB60 vendor invoice template
PostNow.ai publishes a free FB60 vendor invoice template: H rows for the invoice header and vendor line, D rows for the G/L lines, three sample invoices, and a field guide that maps every column to its BAPI_ACC_DOCUMENT_POST structure and field. It carries the sign rule (gross amount negative, expense lines positive) and the cost object columns: cost center, order, WBS element and profit center. Open it in PostNow.ai to map and simulate it against your own system, or browse the other SAP upload templates.
