BAPI_CONTRACT_CREATE — Create Purchasing Contract
BAPI_CONTRACT_CREATE creates a purchasing outline agreement of category contract, the same document ME31K produces, writing header and item data to EKKO and EKPO with document category K. It does not commit the database itself and returns a BAPIRET2 table that must be scanned for error and abort messages before the caller trusts the returned contract number.
This page covers what BAPI_CONTRACT_CREATE actually writes, which parameters carry the header and item data, and why calls that look successful still leave no contract in the database. The bulk of the content is about reading RETURN correctly and the configuration gaps that cause silent partial creation.
Published 16 Sept 2026· 1,092 words
What it does
BAPI_CONTRACT_CREATE creates a purchasing contract, an outline agreement with document category K, covering both quantity contracts and value contracts. It mirrors the transaction ME31K rather than standard purchase order creation. The call writes a header record to EKKO and one or more item records to EKPO, populating vendor, purchasing organization, purchasing group, contract validity dates, and per-item target quantity or target value, material, plant, and price. It does not create release orders against the contract, does not maintain long texts, and does not maintain conditions beyond the basic net price passed at item level; those need separate follow-up calls. Functional consultants should think of it as the API equivalent of manually keying a contract header and item overview screen, without the screen-level defaulting and checks that ME31K performs interactively.
Important parameters
- HEADER - import structure carrying contract type, purchasing organization, purchasing group, vendor, validity start and end dates, and currency for the header being created
- HEADERX - flag structure marking which fields in HEADER are actually populated and should be written; fields left unflagged are ignored even if HEADER contains a value
- ITEM - table of item-level data: item number, material, plant, storage location, target quantity or target value, net price, price unit, order unit
- ITEMX - flag table paired with ITEM, same purpose as HEADERX but at line level; a common source of dropped fields when a new field is added to ITEM but never flagged here
- PURCHASINGDOCUMENT - export parameter returning the contract number once the document is created; blank if creation failed
- RETURN - table of BAPIRET2 messages returned from the call, covering both header-level and item-level problems
Commit behaviour
BAPI_CONTRACT_CREATE does not commit the database on its own. It builds the contract in the current work process but leaves the update pending until the caller explicitly issues a commit, normally through the standard commit BAPI, with WAIT set so the caller can rely on the document existing before doing anything else in the same session. Programs that call BAPI_CONTRACT_CREATE and then immediately try to read the returned contract number back from the database, or pass it into a follow-on BAPI in the same LUW without committing first, will intermittently fail to find it. Batch jobs that skip the commit entirely produce a RETURN table full of success messages and a PURCHASINGDOCUMENT value that was never actually persisted, which is one of the more confusing failure patterns to debug because everything upstream of the commit looked correct.
Return handling
RETURN is a table, not a single message, and every row needs to be inspected, not just the first one. A contract create can fail at header level with one message and then generate a separate message per rejected item, so code that reads RETURN[1] and stops will report success while several lines silently dropped. Message type matters: type E and type A both mean the document was not created and must be treated as failure; type W is a warning and the document may still exist; type S is informational. The reflex mistake is checking sy-subrc after the function call instead of the RETURN content, because BAPI_CONTRACT_CREATE returns sy-subrc 0 even when it has rejected the entire request. A second common bug is assuming PURCHASINGDOCUMENT being non-blank proves success; in some failure paths the number range is drawn and then the document is rolled back on error, leaving a plausible-looking contract number in the export parameter that never actually posted, which only becomes visible once the caller tries to display it in ME33K.
ECC vs S/4HANA
BAPI_CONTRACT_CREATE remains usable on S/4HANA and is still the practical route for programmatic contract creation in most custom interfaces and migration tooling. There is no broadly adopted released OData or API Business Hub service that fully replaces contract creation with equivalent field coverage, so projects generally keep calling this BAPI wrapped in custom error handling rather than rebuilding on a newer API. Contract display and reporting have moved toward Fiori apps in many S/4HANA implementations, but the creation and mass-load path still runs through this classic BAPI or through LSMW-style batch input where the BAPI is not suitable.
Common pitfalls
- Vendor not extended to the purchasing organization on the contract header, which fails at header level before any item is processed
- Missing or incomplete material master data at the plant for one item causing that single line to be rejected while the header and other items still post, leaving a contract with fewer items than expected
- Document type not configured to allow external creation or missing number range assignment, producing a header-level abort message that is easy to misread as an authorization problem
- Conditions and pricing not created because BAPI_CONTRACT_CREATE only accepts the flat net price on the item; anything beyond that needs a separate condition maintenance call, and teams forget this until the contract is used and pricing comes out wrong
- Release strategy not triggered because the BAPI bypasses the same screen exits and status checks that ME31K fires, so contracts created via this BAPI sometimes skip release workflows that business assumed were mandatory
- Long texts and header notes not populated at all, requiring a separate text BAPI call keyed on the returned contract number, forgotten in first-pass interface builds
Whose problem this is
Configuration problems, document type restrictions, release strategy assignment, and vendor-purchasing-organization extension belong to the MM functional consultant. Interface failures where RETURN is misread, commit is missing, or item flags in ITEMX are wrong belong to the developer. When a contract silently comes out incomplete, functional needs the full RETURN dump per item, and development needs confirmation of which document type and purchasing organization were expected.
Related SAP objects
Reviewed pages this object connects to in the ERPClimb knowledge graph.
Source: ERPClimb — https://erpclimb.com/sap-bapis/bapi-contract-createERPClimb is an independent platform and is not affiliated with SAP SE. Reference pages are written and reviewed by SAP consultants for learning and troubleshooting.