BAPI_PO_CREATE1 Call Skeleton Generator
BAPI_PO_CREATE1 is the standard function module for creating purchase orders from ABAP, and the fiddly part is always the pairs of data and X structures. This generator builds a complete call you can adapt: header, item, schedule line, the flag structures, error check and commit.
Fill in
On releases with long material numbers, use MATERIAL_LONG.
1. Declarations
DATA: ls_header TYPE bapimepoheader,
ls_headerx TYPE bapimepoheaderx,
lt_item TYPE STANDARD TABLE OF bapimepoitem,
lt_itemx TYPE STANDARD TABLE OF bapimepoitemx,
lt_sched TYPE STANDARD TABLE OF bapimeposchedule,
lt_schedx TYPE STANDARD TABLE OF bapimeposchedulx,
lt_return TYPE STANDARD TABLE OF bapiret2,
lv_po TYPE bapimepoheader-po_number.2. Header, item and schedule line data
ls_header-comp_code = '1000'.
ls_header-doc_type = 'NB'.
ls_header-vendor = '0000100010'.
ls_header-purch_org = '1000'.
ls_header-pur_group = '001'.
ls_header-currency = 'USD'.
ls_headerx-comp_code = abap_true.
ls_headerx-doc_type = abap_true.
ls_headerx-vendor = abap_true.
ls_headerx-purch_org = abap_true.
ls_headerx-pur_group = abap_true.
ls_headerx-currency = abap_true.
APPEND VALUE #( po_item = '00010'
material = 'RM-1001'
plant = '1000'
quantity = 100
po_unit = 'EA'
net_price = '12.50' ) TO lt_item.
APPEND VALUE #( po_item = '00010'
po_itemx = abap_true
material = abap_true
plant = abap_true
quantity = abap_true
po_unit = abap_true
net_price = abap_true ) TO lt_itemx.
APPEND VALUE #( po_item = '00010'
sched_line = '0001'
delivery_date = sy-datum + 14
quantity = 100 ) TO lt_sched.
APPEND VALUE #( po_item = '00010'
sched_line = '0001'
po_itemx = abap_true
sched_linex = abap_true
delivery_date = abap_true
quantity = abap_true ) TO lt_schedx.3. Call, error check and commit
CALL FUNCTION 'BAPI_PO_CREATE1'
EXPORTING
poheader = ls_header
poheaderx = ls_headerx
IMPORTING
exppurchaseorder = lv_po
TABLES
return = lt_return
poitem = lt_item
poitemx = lt_itemx
poschedule = lt_sched
poschedulex = lt_schedx.
IF line_exists( lt_return[ type = 'E' ] ) OR line_exists( lt_return[ type = 'A' ] ).
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
* report the messages in lt_return to the user or the log
ELSE.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING
wait = abap_true.
* lv_po now holds the new purchase order number
ENDIF.Pass TESTRUN = 'X' first to validate without saving. Every field you fill in the data structure needs its flag in the matching X structure, otherwise the BAPI ignores the value. Check the exact parameter and field names in SE37 and SE11 for your release, because they vary slightly between ECC and S/4HANA. Test with your own customizing for document types, tax codes and number ranges.
Automate purchase order intake
Want PO data prepared from emails or spreadsheets with human approval before posting? Describe your flow.
Optional. The tool and every export work without this. No spam.
How to use the skeleton
Fill in company code, document type, vendor, purchasing organization and group, then the material, plant, quantity, unit, price and delivery lead time. The output declares the structures, fills data and flag tables together, calls the BAPI and decides between commit and rollback based on the RETURN table. Paste it into a method, replace the constants with your inputs, and add more items by looping over your source data with an incrementing item number such as 00010, 00020.
Why every field needs an X flag
The BAPI works on a change-flag principle. For each field you supply in POHEADER, POITEM or POSCHEDULE, you set the same field to 'X' in POHEADERX, POITEMX or POSCHEDULEX, and you must also set the item key fields in the X tables. If the flag is missing, the value is silently ignored and the default or customizing value is used. This is the most common reason that a created PO does not contain the data you sent.
- POITEMX carries PO_ITEM and PO_ITEMX plus one flag per filled field
- POSCHEDULEX needs PO_ITEM, SCHED_LINE, PO_ITEMX and SCHED_LINEX
- Test first with the TESTRUN parameter set to X
Reading RETURN and committing
The RETURN table is a list of BAPIRET2 messages. Types E and A mean the PO was not created, so roll back and report the text. Types S, I and W are information. BAPI_TRANSACTION_COMMIT with WAIT set makes the commit synchronous, so a following read finds the document. Do not call COMMIT WORK directly after a BAPI unless you know the update task logic, and never commit inside a loop of unrelated documents without handling failures.
Common mistakes
Typical defects are missing X flags, vendor numbers without leading zeros, material numbers in the wrong format or length, no unit conversion between order unit and base unit, and ignoring warning messages that point to missing price conditions. Another is forgetting that the BAPI uses the caller's authorizations, so a batch user needs the right purchasing authorizations. Newer releases also offer BAPI_PO_CREATE1 alongside the OData and API-based purchase order services, so check the recommended interface for your S/4HANA release.
Frequently Asked Questions
What is the difference between BAPI_PO_CREATE and BAPI_PO_CREATE1?
BAPI_PO_CREATE1 is the newer interface that uses the BAPIMEPOHEADER style structures with separate X structures, and it supports more functions such as account assignment and conditions. BAPI_PO_CREATE is the older one and is not recommended for new development.
Why is my price or plant not saved on the purchase order?
Most often the matching X flag is missing. Each value in the item or header must have the same field set to X in the X structure. Also check that the item key PO_ITEM and PO_ITEMX are set in the X table.
Do I need BAPI_TRANSACTION_COMMIT?
Yes. The BAPI does not commit on its own, so you must call BAPI_TRANSACTION_COMMIT after a successful call. Use WAIT = 'X' if later steps read the new document. On errors call BAPI_TRANSACTION_ROLLBACK.
How do I test without creating a PO?
Set the TESTRUN export parameter to 'X'. The BAPI runs the checks and returns messages in RETURN, but nothing is saved. This is the best way to find missing flags and customizing issues before going live.
If you build PO creation interfaces repeatedly, we can discuss a reviewed approach where an agent prepares the data and a person approves before anything is written to the ERP.
Related Tools
ABAP SELECT Statement Generator
Fill in table, fields and a WHERE condition and get modern ABAP Open SQL: SELECT INTO TABLE, SELECT SINGLE and a safe FOR ALL ENTRIES pattern.
SAPABAP Internal Table Declaration Generator
Choose table kind, key and line type and get the DATA declaration, a local TYPES version and the common table operations.
SAPABAP Code Review Checklist
A practical review checklist for ABAP changes: database access, security, error handling, structure and S/4HANA compatibility.
SAPSAP System Fields Reference (SY-SUBRC, SY-DATUM and more)
A searchable list of the ABAP system fields in structure SYST with data type, meaning and a typical use in code.
More SAP tools
See all- SAP Sales Document Types Reference
- SAP Pricing Procedure Design Worksheet
- SAP Item Category Determination Reference
- SAP Delivery Block Reasons Template
- SAP Credit Management Checklist
- SAP Output Determination Checklist
- SAP Billing Types Reference
- SAP Incompletion Log Checklist
- SAP SD Tables Reference (VBAK, VBAP, LIKP, VBRK and More)