Quick answer

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.

  1. 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 for BAPI_ACC_DOCUMENT_POST by name in PostNow.ai's BAPI search and let Mapping AI match your own column headers to its fields. Choose that BAPI, not BAPI_INCOMINGINVOICE_CREATE, which is MIRO's and needs purchase order lines.
  2. Group the header and the lines. A marker column turns one H row (company code, dates, document type, supplier reference, vendor, gross amount, payment terms) and its D rows (G/L account, amount, cost object) into one invoice. A grouping key such as VI-0001 keeps the rows of one invoice together.
  3. 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.
  4. Simulate. PostNow.ai calls the BAPI for every invoice and then BAPI_TRANSACTION_ROLLBACK instead of a commit, so SAP's own messages (balance, closed period, missing cost object, blocked vendor) appear per invoice and nothing posts.
  5. Run. For each invoice PostNow.ai calls the BAPI and commits with BAPI_TRANSACTION_COMMIT only 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 in FB03.
  6. 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.

StructureOne perFields an FB60 upload usually fills
DOCUMENTHEADERInvoiceCOMP_CODE, DOC_DATE (invoice date), PSTNG_DATE, DOC_TYPE (KR), REF_DOC_NO (the supplier's invoice number), HEADER_TXT, BUS_ACT = RFBU
ACCOUNTPAYABLEVendor lineITEMNO_ACC, VENDOR_NO, PMNTTRMS, BLINE_DATE, PMNT_BLOCK, PYMT_METH, ITEM_TEXT
ACCOUNTGLExpense lineITEMNO_ACC, GL_ACCOUNT, TAX_CODE, COSTCENTER or ORDERID or WBS_ELEMENT, PROFIT_CTR, ITEM_TEXT
ACCOUNTTAXTax code on the invoiceITEMNO_ACC, TAX_CODE; only when the invoice carries tax
ACCOUNTWTWithholding tax typeITEMNO_ACC of the vendor line, WT_TYPE, WT_CODE, base and amount where entered manually
CURRENCYAMOUNTEvery line aboveITEMNO_ACC, CURRENCY, AMT_DOCCUR (signed), and AMT_BASE for a tax line
ExportsInvoiceOBJ_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".

ⓘ
FB60 posts through the accounting BAPI, not the invoice BAPI. 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 example N030) and the baseline date (BLINE_DATE) together give the due date. Map both explicitly, then open the first posted invoice in FB03 and confirm the due date is what the supplier expects.
  • Payment block (PMNT_BLOCK): A blocks 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.

InvoiceWhat the file sendsThe rule
No tax (exempt, out of scope)Vendor line and G/L lines only, as the free template doesGross amount = sum of the G/L lines
Input taxTax 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_BASEGross 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. A COUNTIFS on 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.

RouteWhat the run createsFits when
PostPosted invoices, open for payment by the termsThe file was reviewed and approved before the run
Post with payment block APosted invoices that the payment run skips until the block is removedThe liability should be in the books now, payment only after review
ParkParked documents, no ledger update until someone posts them in FBV0Your 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 rowInvoice RefColumns filled
HVI-0012Type 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
DVI-0012Line 2, G/L 0000470000 cleaning, cost center 1010-210, tax code V1, 650.00
DVI-0012Line 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.

  1. Duplicates. The operator runs AP Vendor Document Detail 360 for the nine vendors and the last six months. A COUNTIFS on vendor and reference finds one utility invoice already posted in October; it comes out of the file. 24 invoices remain.
  2. 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.
  3. Simulate. 21 invoices pass. Two return F5 702 because their tax was copied from the supplier's invoice and differs from the calculated 19% by a cent; one returns KI 235 because an expense line has no cost center. All three are corrected and pass a second Simulate.
  4. Run. All 24 post. Each H row now holds its accounting document number, from 1900000731 to 1900000754, with user, time and system.
  5. Check. The clerk opens the first invoice in FB03 from 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.

QuestionFB60 (FI vendor invoice)MIRO (logistics invoice verification)
BasisNo purchase order; G/L account and cost object come from the filePurchase order item, and the goods receipt where GR-based IV is set
MatchingNone against an order; review happens before posting, or through parking or a payment blockPrice, quantity and date against the PO; variances above tolerance block payment
GR/IR clearing accountNot touchedCleared against the goods receipt
BAPI PostNow.ai usesBAPI_ACC_DOCUMENT_POSTBAPI_INCOMINGINVOICE_CREATE
ReversalFB08MR8M

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, FB08 stops with a cleared-items message such as F5 802 "Document … already contains cleared items - reversal not possible". Reset the clearing in FBRA, 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:

MessageWhat it meansFix
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 zeroCheck 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 openThe period is closed for the posting date, and periods are opened per account type in OB52Have 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 objectAn expense line has no cost center, order or WBS elementFill one real cost object on every expense line, not only the first line of each invoice
F5 117 duplicate invoice messageRaised 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 clearedReset 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 postedLook 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.

  1. No invoice in the file has a purchase order; PO invoices are in a separate MIRO file.
  2. The file has been compared with SAP on vendor and reference, and with itself.
  3. Each H row carries the supplier's real invoice number in the reference column.
  4. Document type is KR (or the type your company uses for vendor invoices) on every H row.
  5. Per invoice, vendor line + G/L lines + tax lines add up to zero, with the vendor line negative.
  6. Every expense line has a cost object; balance sheet lines correctly have none.
  7. Tax amounts are calculated from your tax codes, and withholding tax types exist on each vendor that needs them.
  8. The posting period is open for account type K on the posting date in the file.
  9. Payment terms, baseline dates and any payment block are set, and treasury has seen the due-date profile.
  10. 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 BP in 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.

Frequently asked questions

How do I do an FB60 mass upload from Excel?
With PostNow.ai, put one header row per invoice (vendor, dates, reference, gross amount) and one detail row per G/L line in a template mapped to BAPI_ACC_DOCUMENT_POST, such as the free FB60 template. Validate checks the sheet, Simulate lets SAP check every invoice and rolls it back, and Run posts each invoice, commits only when SAP returns no error, and writes the accounting document number back to its header row.
What is FB60 in SAP?
FB60 is the Financial Accounting transaction for entering a vendor invoice without a purchase order. It posts a credit to the vendor and debits to the expense G/L accounts with their cost objects, usually with document type KR. FV60 is its parking counterpart.
Which BAPI posts an FB60 vendor invoice?
BAPI_ACC_DOCUMENT_POST. The vendor line goes in ACCOUNTPAYABLE, the expense lines in ACCOUNTGL, tax lines in ACCOUNTTAX, withholding tax in ACCOUNTWT, and every amount in CURRENCYAMOUNT, joined by ITEMNO_ACC. BAPI_INCOMINGINVOICE_CREATE is the MIRO BAPI for purchase order invoices. The caller has to commit with BAPI_TRANSACTION_COMMIT.
How is tax calculated on an FB60 upload?
Through the BAPI it is not calculated for you: BAPI_ACC_DOCUMENT_POST has no equivalent of the FB60 "Calculate tax" checkbox. Pass a tax line per tax code in ACCOUNTTAX with the tax amount and its base in CURRENCYAMOUNT, calculated from the net lines with your tax code's rate. If the lines and tax do not add up to the vendor line, SAP returns F5 702.
How do I post withholding tax on a non-PO invoice?
Add an ACCOUNTWT row per withholding tax type, pointing at the vendor line's ITEMNO_ACC, with the type in WT_TYPE and the code in WT_CODE, plus a manual base or amount where your setup needs one. The vendor must carry those types in its company code data. Check the withholding tax data on the first posted invoice in FB03 before posting the rest.
Can I park invoices (FV60) instead of posting them?
Yes. In releases whose BAPI_ACC_DOCUMENT_POST header has the DOC_STATUS field, value 2 parks the document (code samples cite SAP Note 2092366); check the field in SE37 and test one invoice to confirm it arrives parked, not posted. Otherwise, record FV60 and post the file through PostNow.ai as a recording. Parked invoices are posted later in FBV0.
How does SAP catch a duplicate vendor invoice?
In FB60, when the vendor has the double-invoice check flag, SAP compares company code, vendor, currency, document date and the reference (or the amount when there is no reference) and raises message F5 117. SAP KBA 2389365 states that this message is not raised for invoices posted through BAPI_ACC_DOCUMENT_POST, so compare the file with the references already in SAP before a bulk run.
When should I use FB60 instead of MIRO?
Only for invoices that have no purchase order, such as rent, utilities or professional fees billed without an order. FB60 posts the liability straight to G/L accounts without matching. A PO invoice posted through FB60 leaves the purchase order open for invoicing and the goods receipt uncleared in GR/IR, so it belongs in MIRO.
Your invoice file. SAP's posting rules.

Post your next batch of non-PO invoices from Excel

Map FB60 once, simulate every invoice, then post and see each accounting document number on its row.

Start free trial
  • 14-day free trial
  • Works with ECC and S/4HANA
  • Posts under your own SAP login