SAP BAPIs and RFC Integration

Type: ERP Integration System: SAP S/4HANA (2023/2024) + SAP ECC 6.0 (EHP8) Confidence: 0.92 Sources: 8 Verified: 2026-03-01 Freshness: 2026-03-01

TL;DR

System Profile

This card covers SAP's Business Application Programming Interface (BAPI) and Remote Function Call (RFC) integration layer, applicable to both SAP ECC 6.0 (all EHP levels) and SAP S/4HANA on-premise/private cloud editions. BAPIs are methods of SAP Business Objects defined in the Business Object Repository (BOR, transaction BAPI/SWO1) that wrap RFC-enabled function modules with standardized interfaces, stable naming, and guaranteed backward compatibility. [src1, src5]

RFC is the underlying transport protocol. Five variants exist: synchronous (sRFC), asynchronous (aRFC), transactional (tRFC), queued (qRFC), and background (bgRFC). This card does NOT cover SAP Cloud Integration Suite, SAP BTP destinations, or S/4HANA Cloud public edition APIs (which use OData/REST exclusively).

PropertyValue
VendorSAP
SystemSAP S/4HANA 2023/2024 + SAP ECC 6.0 EHP8
API SurfaceRFC (sRFC, aRFC, tRFC, qRFC, bgRFC) + BAPIs
Current API VersionSAP NetWeaver RFC SDK 7.50+ / JCo 3.1 / NCo 3.1 / PyRFC 3.x
Editions CoveredAll on-premise and private cloud editions
DeploymentOn-Premise / Private Cloud / Hybrid
API DocsSAP Help — RFC Variants
StatusGA (bgRFC recommended; tRFC/qRFC maintenance-only)

API Surfaces & Capabilities

BAPIs are the application-level API; RFC variants are the transport-level protocol beneath them. Choosing the right RFC variant is critical. [src1, src5]

RFC VariantProtocolBest ForDelivery GuaranteeOrderingReal-time?Target Required?
sRFC (Synchronous)RFC/CPIC or WebSocketReal-time lookups, immediate-response operationsNone (fails if target down)N/AYesYes
aRFC (Asynchronous)RFC/CPICParallel processing, non-critical background callsNone (lost if unreachable)NoPartialYes
tRFC (Transactional)RFC/CPICExactly-once delivery (legacy)Exactly-once via TIDNoNoNo
qRFC (Queued)RFC/CPICOrdered exactly-once delivery (legacy)Exactly-once + FIFOYes (per queue)NoNo
bgRFC (Background)RFC/CPIC or WebSocketAll new async/transactional workExactly-once, optional FIFOConfigurableNoNo

Rate Limits & Quotas

RFC does not have API call quotas like REST APIs. Instead, limits are defined by system resources — dialog work processes, memory, and RFC connection parameters. [src1]

Per-Request Limits

Limit TypeValueApplies ToNotes
Dialog work process time600s defaultsRFC callsParameter rdisp/max_wprun_time; exceeded = TIME_OUT dump
Max RFC connectionsConfigurable per destinationAll RFC typesSM59 settings; varies by system sizing
Memory per work processExtended memory allocationsRFC, aRFCLarge payloads exhaust work process memory
tRFC/qRFC payloadStored in ARFCSSTATE/ARFCSDATAtRFC, qRFCLarge volumes bloat database; monitor with SM58
bgRFC unit sizeStored in BGRFC* tablesbgRFCMore efficient storage than tRFC tables

System Resource Limits

Limit TypeValueWindowConfiguration
Dialog work processesTypically 10-40 per app serverConcurrentrdisp/wp_no_dia; each sRFC occupies one
RFC connection poolConfigurable per destinationConcurrentJCo: jco.destination.pool_capacity (default 1)
bgRFC scheduler threadsConfigurable per app serverPer schedulerSBGRFCCONF; multiple schedulers supported
SM58 stuck entriesN/ARollingEntries stuck >24h indicate connectivity issues

Transaction / Governor Limits

Limit TypePer-Transaction ValueNotes
Dialog step timeout600s (configurable)sRFC runs within a dialog step — long-running calls hit this
Max internal tables sizeExtended memory allocationLarge datasets cause STORAGE_PARAMETERS_WRONG_SET
Commit work frequency1 per LUWMultiple BAPIs in one LUW require single BAPI_TRANSACTION_COMMIT
RFC callback depthNo hard limitRecursive RFC calls consume work processes — avoid circular patterns

Authentication

RFC authentication is configured at the SAP system level via SM59 (RFC destination maintenance) and is fundamentally different from token-based REST authentication. [src8]

MethodUse WhenSecurity LevelMFA SupportNotes
User/PasswordDevelopment, testingLowNoStored in SM59; visible to admins
SNC (Secure Network Communication)Production — all environmentsHighVia PKIX.509 certificates; snc/only_encrypted_rfc=1
Trusted RFCSAP-to-SAP communicationMedium-HighN/AS_RFCACL required; avoid wildcard values
SSO via Kerberos/SPNEGOWindows domain environmentsHighVia domainRequires SAP Secure Login Server

Authentication Gotchas

Constraints

Integration Pattern Decision Tree

START — User needs to integrate with SAP via BAPI/RFC
|
+-- What's the integration pattern?
|   |
|   +-- Real-time (individual records, <1s latency)
|   |   +-- Need immediate response? --> sRFC: call BAPI, get RETURN
|   |   +-- Fire-and-forget OK? --> bgRFC with high-priority queue
|   |   +-- Write with confirmation? --> sRFC + check RETURN + COMMIT
|   |
|   +-- Batch/Bulk (scheduled, high volume)
|   |   +-- <1,000 records? --> sRFC loop with commit per batch
|   |   +-- >1,000 records? --> bgRFC with parallel queues (40% faster)
|   |   +-- Need ordering? --> bgRFC single named queue (FIFO)
|   |
|   +-- Event-driven
|   |   +-- SAP triggers? --> bgRFC outbound to registered RFC server
|   |   +-- Need exactly-once? --> bgRFC (replaces tRFC semantics)
|   |   +-- Not native RFC --> use SAP Event Mesh or IDoc
|   |
|   +-- File-based --> Not RFC — use IDoc, FBDI, or BW extractors
|
+-- Which connector?
|   +-- Java --> SAP JCo 3.1
|   +-- .NET --> SAP NCo 3.1
|   +-- Python --> PyRFC 3.x (via SAP NW RFC SDK)
|   +-- Node.js --> node-rfc or SAP Cloud SDK
|   +-- Other --> SAP NW RFC SDK (C/C++)
|
+-- Error tolerance?
    +-- Zero-loss --> bgRFC + SBGRFCMON + dead letter handling
    +-- Best-effort --> aRFC (fastest, no persistence)

Quick Reference

Common BAPIs for Integration

BAPIModuleOperationKey ParametersNotes
BAPI_SALESORDER_CREATEFROMDAT2SDCreate sales orderORDER_HEADER_IN, ORDER_ITEMS_INMost-used SD BAPI; requires COMMIT
BAPI_PO_CREATE1MMCreate purchase orderPOHEADER, POITEM, POSCHEDULESupports all item categories
BAPI_MATERIAL_SAVEDATAMMCreate/change materialHEADDATA, CLIENTDATA, PLANTDATASet CLIENTDATAX flags for changes
BAPI_CUSTOMER_CREATEFROMDATA1SD/FICreate customerPI_PERSONALDATA, PI_COPYREFERENCEReturns CUSTOMERNO on success
BAPI_GOODSMVT_CREATEMMGoods movementGOODSMVT_HEADER, GOODSMVT_ITEMGM_CODE determines movement type
BAPI_ACC_DOCUMENT_POSTFIPost accounting docDOCUMENTHEADER, ACCOUNTGLReplaces direct FB01 posting
BAPI_EMPLOYEE_GETDATAHRRead employee dataEMPLOYEE_ID, TIMEFRAMERead-only; no commit needed
BAPI_TRANSACTION_COMMITCrossCommit transactionWAIT = 'X'ALWAYS call after write BAPIs
BAPI_TRANSACTION_ROLLBACKCrossRollback transaction(none)Only uncommitted changes in LUW

RFC Variant Quick Comparison

FeaturesRFCaRFCtRFCqRFCbgRFC
Delivery guaranteeNoneNoneExactly-onceExactly-once + FIFOExactly-once, optional FIFO
Target must be onlineYesYesNoNoNo
Caller blockedYesNoNoNoNo
Data persistedNoNoYes (TID)Yes (queue)Yes (unit)
OrderingN/ANoNoYesConfigurable
Recommended for new devYes (reads)LimitedNoNoYes (all async)
Monitoring txnSM58SM58SM58SMQ1/SMQ2SBGRFCMON

Step-by-Step Integration Guide

1. Configure RFC Destination (SM59)

Create an RFC destination in the SAP system to define connection parameters for external systems. [src1]

Transaction: SM59
1. Create new destination: Type T (TCP/IP) for external, Type 3 for SAP-to-SAP
2. Set Activation Type: "Registered Server Program"
3. Set Program ID (must match external application)
4. For SNC: Technical Settings tab, set SNC partner name and QoP
5. Test connection: green light = success

Verify: SM59 → select destination → "Connection Test" → expected: green status, round-trip time displayed

2. Call a BAPI via sRFC with JCo (Java)

Use SAP JCo 3.1 to invoke a BAPI synchronously. JCo handles connection pooling, data type conversion, and RFC protocol details. [src2]

// Get destination from properties file
JCoDestination destination = JCoDestinationManager.getDestination("SAP_SYSTEM");

// Get function template from SAP metadata
JCoFunction function = destination.getRepository()
    .getFunction("BAPI_COMPANYCODE_GETLIST");

// Execute synchronous RFC call
function.execute(destination);

// Check RETURN for errors
JCoStructure ret = function.getExportParameterList().getStructure("RETURN");
if ("E".equals(ret.getString("TYPE")))
    throw new RuntimeException("BAPI error: " + ret.getString("MESSAGE"));

// Process results
JCoTable codes = function.getTableParameterList().getTable("COMPANYCODE_LIST");
for (int i = 0; i < codes.getNumRows(); i++) {
    codes.setRow(i);
    System.out.println(codes.getString("COMP_CODE") + " - " + codes.getString("COMP_NAME"));
}

Verify: Run application → expected: list of company codes printed; no exceptions

3. Call a Write BAPI with Commit/Rollback Pattern

Write BAPIs require explicit BAPI_TRANSACTION_COMMIT. Never call COMMIT WORK directly — it skips BAPI buffer refresh logic. [src3, src4]

// Execute the write BAPI
createSO.execute(dest);

// Check ALL RETURN table entries for errors
JCoTable returnTable = createSO.getTableParameterList().getTable("RETURN");
boolean hasErrors = false;
for (int i = 0; i < returnTable.getNumRows(); i++) {
    returnTable.setRow(i);
    String msgType = returnTable.getString("TYPE");
    if ("E".equals(msgType) || "A".equals(msgType)) {
        hasErrors = true;
    }
}

// Single commit or rollback for entire LUW
if (!hasErrors) {
    JCoFunction commit = dest.getRepository()
        .getFunction("BAPI_TRANSACTION_COMMIT");
    commit.getImportParameterList().setValue("WAIT", "X"); // Synchronous
    commit.execute(dest);
} else {
    JCoFunction rollback = dest.getRepository()
        .getFunction("BAPI_TRANSACTION_ROLLBACK");
    rollback.execute(dest);
}

Verify: SE16 → table VBAK → expected: new sales order with correct header data

4. Implement bgRFC for Guaranteed Async Delivery

bgRFC replaces tRFC and qRFC with better performance and monitoring. [src1, src6]

" Get bgRFC destination (configured in SBGRFCCONF)
DATA(lo_dest) = cl_bgrfc_destination_outbound=>create( 'DESTINATION_NAME' ).

" Create bgRFC unit (use create_qrfc_unit for ordered delivery)
DATA(lo_unit) = lo_dest->create_trfc_unit( ).

" Call function module within bgRFC unit
CALL FUNCTION 'BAPI_SALESORDER_CREATEFROMDAT2'
  IN BACKGROUND UNIT lo_unit
  EXPORTING order_header_in = ls_header
  TABLES order_items_in = lt_items return = lt_return.

" Unit persisted to DB on COMMIT WORK
COMMIT WORK.
" bgRFC scheduler delivers when target is available

Verify: SBGRFCMON → expected: unit ID visible with status "Executed" or "Waiting"

Code Examples

Python: Read Material Master via PyRFC

# Input:  SAP connection parameters, material number
# Output: Material description and base unit of measure
# Requires: pyrfc>=3.3 + SAP NW RFC SDK installed

from pyrfc import Connection

conn = Connection(
    ashost='sap-server.example.com', sysnr='00',
    client='100', user='RFC_USER', passwd='secure_password', lang='EN'
)

result = conn.call('BAPI_MATERIAL_GETDETAIL', MATERIAL='MAT-001', PLANT='1000')

ret = result.get('RETURN', {})
if ret.get('TYPE') == 'E':
    raise RuntimeError(f"BAPI error: {ret['MESSAGE']}")

mat_desc = result['MATERIAL_GENERAL_DATA']['MATL_DESC']
print(f"Material: {mat_desc}")
conn.close()

JavaScript/Node.js: Call BAPI via node-rfc

// Input:  SAP connection parameters
// Output: List of company codes
// Requires: [email protected] + SAP NW RFC SDK

const noderfc = require('node-rfc');
const client = new noderfc.Client({
    ashost: 'sap-server.example.com', sysnr: '00',
    client: '100', user: 'RFC_USER', passwd: 'secure_password'
});

async function getCompanyCodes() {
    await client.open();
    const result = await client.call('BAPI_COMPANYCODE_GETLIST', {});
    if (result.RETURN?.TYPE === 'E')
        throw new Error(`BAPI error: ${result.RETURN.MESSAGE}`);
    for (const cc of result.COMPANYCODE_LIST)
        console.log(`${cc.COMP_CODE} - ${cc.COMP_NAME}`);
    await client.close();
}
getCompanyCodes().catch(console.error);

cURL: N/A — RFC Is Not HTTP-Based

# RFC is a binary protocol, not HTTP. Cannot use cURL directly.
# For HTTP-based SAP integration, use:
# - SAP API Business Hub (api.sap.com) with OData/REST
# - SAP Cloud Connector + BTP for RFC-over-HTTP tunneling
# - SAP Gateway (SEGW) to expose BAPIs as OData services

Data Mapping

BAPI Parameter Structure Reference

Parameter TypeABAP TypeDirectionExampleNotes
IMPORTScalar/StructureInORDER_HEADER_INSingle values or flat structures
EXPORTScalar/StructureOutSALESDOCUMENTReturn values from BAPI
TABLESInternal TableIn/OutORDER_ITEMS_IN, RETURNTabular data; RETURN has error messages
CHANGINGStructureIn/Out(rare in BAPIs)Modified by BAPI and returned

BAPI RETURN Structure (BAPIRET2)

FieldTypeValuesPurpose
TYPECHAR 1S=Success, E=Error, W=Warning, I=Info, A=AbortMessage severity
IDCHAR 20Message class (e.g., 'V1')For lookup in SE91
NUMBERNUMC 3Message numberCombined with ID for unique identification
MESSAGECHAR 220Human-readable textThe actual error/success message
LOG_NOCHAR 20Application log numberFor detailed investigation via SLG1
MESSAGE_V1-V4CHAR 50Variable replacementsDynamic parts of message text

Data Type Gotchas

Error Handling & Failure Points

Common Error Codes

ErrorMeaningCauseResolution
COMMUNICATION_FAILURECannot reach SAPNetwork issue, SAP downCheck SM59 connection test; verify network
SYSTEM_FAILUREABAP runtime errorShort dump on targetCheck ST22 for dump details
RFC_ERROR_LOGON_FAILUREAuth failedWrong credentials, locked userCheck SU01 user status; use type B users
TABLE_ENTRIES_EXCEED_LIMITToo much dataQuery returns too many rowsAdd filter parameters; paginate
RETURN TYPE='E'Business logic errorInvalid data, missing fieldsRead MESSAGE; check SU53 for auths
RFC_ERROR_SYSTEM_NOT_AVAILABLETarget unreachableSystem down during tRFC/bgRFCEntries in queue; auto-retry; check SBGRFCMON

Failure Points in Production

Anti-Patterns

Wrong: COMMIT WORK Instead of BAPI_TRANSACTION_COMMIT

" BAD — COMMIT WORK skips BAPI buffer refresh logic
CALL FUNCTION 'BAPI_SALESORDER_CREATEFROMDAT2' ...
COMMIT WORK.  " Missing BUFFER_REFRESH_ALL, stale buffers

Correct: Always Use BAPI_TRANSACTION_COMMIT

" GOOD — calls BUFFER_REFRESH_ALL internally
CALL FUNCTION 'BAPI_SALESORDER_CREATEFROMDAT2' ...
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
  EXPORTING WAIT = 'X'.  " Synchronous — waits for DB commit

[src4]

Wrong: Committing Inside a Loop

// BAD — each iteration is a separate LUW; cannot rollback later
for (Item item : items) {
    function.execute(destination);
    commitFunction.execute(destination); // COMMIT per item -- WRONG
}

Correct: Batch All Calls, Single Commit at End

// GOOD — all items in one LUW; single commit/rollback
boolean hasErrors = false;
for (Item item : items) {
    function.execute(destination);
    if (checkReturnForErrors(function)) { hasErrors = true; break; }
}
if (!hasErrors) commitFunction.execute(destination);
else rollbackFunction.execute(destination);

[src3, src4]

Wrong: Using tRFC for New Projects

" BAD — tRFC deprecated; single scheduler, poor performance
CALL FUNCTION 'Z_SEND_ORDER'
  IN BACKGROUND TASK DESTINATION 'TARGET_SYSTEM' ...
COMMIT WORK.

Correct: Use bgRFC for All New Async Work

" GOOD — multiple schedulers, parallel queues, 40% better throughput
DATA(lo_dest) = cl_bgrfc_destination_outbound=>create( 'TARGET_SYSTEM' ).
DATA(lo_unit) = lo_dest->create_trfc_unit( ).
CALL FUNCTION 'Z_SEND_ORDER'
  IN BACKGROUND UNIT lo_unit DESTINATION 'TARGET_SYSTEM' ...
COMMIT WORK.

[src6, src7]

Common Pitfalls

Diagnostic Commands

# SAP transaction codes for RFC diagnostics

# Check RFC destination connectivity
SM59 -> select destination -> "Connection Test"

# Monitor stuck tRFC entries (legacy)
SM58 -> filter by date/destination

# Monitor bgRFC units and queues
SBGRFCMON -> filter by destination/status

# bgRFC history and performance
SBGRFCHIST (history) / SBGRFCPERFMON (throughput)

# Short dumps from failed RFC calls
ST22 -> filter by date/user

# RFC work process usage
SM66 (running processes) / SM04 (active sessions)

# Authorization failure diagnosis
SU53 -> shows last auth failure

# External: Check JCo version
java -cp sapjco3.jar com.sap.conn.jco.JCo

# External: Check PyRFC version
python -c "import pyrfc; print(pyrfc.__version__)"

# External: Test RFC connection from Python
python -c "
from pyrfc import Connection
c = Connection(ashost='host', sysnr='00', client='100', user='USER', passwd='PASS')
print('Connected:', c.get_connection_attributes())
c.close()
"

Version History & Compatibility

ComponentVersionStatusKey ChangesNotes
bgRFCNetWeaver 7.0+Current, recommendedReplaces tRFC/qRFCUse for all new async development
tRFCAll NW versionsDeprecated (functional)Original async exactly-onceMigrate to bgRFC
qRFCNetWeaver 6.20+Deprecated (functional)FIFO ordering on tRFCMigrate to bgRFC create_qrfc_unit()
sRFCAll versionsCurrentSynchronous — unchangedStill correct for real-time lookups
aRFCAll versionsCurrent (limited)No delivery guaranteeNon-critical parallel calls only
JCo 3.13.1.x (2025)CurrentWebSocket RFC, bgRFCMin Java 8
NCo 3.13.1.x (2025)Current.NET 6+, WebSocket RFCReplaces NCo 3.0
PyRFC3.3+ (2024)CurrentPython 3.8+ requiredArchived but functional
NW RFC SDK7.50+CurrentRequired by all connectorsS-user required for download

Deprecation policy: SAP does not formally sunset tRFC/qRFC — they remain functional indefinitely. However, all new documentation and features target bgRFC exclusively. SAP Note 1889823 recommends bgRFC migration. [src1, src6]

When to Use / When Not to Use

Use WhenDon't Use WhenUse Instead
Integrating with SAP ECC or S/4HANA on-premise/private cloudUsing S/4HANA Cloud public editionOData V4 APIs via SAP API Business Hub
Calling existing ABAP function modules or BAPIsBuilding new APIs from scratch on S/4HANARAP (RESTful ABAP Programming) + OData
Need exactly-once async delivery (bgRFC)Need real-time event streaming/webhooksSAP Event Mesh or ALE/IDocs
Using Java, .NET, Python, or C/C++ clientsBrowser-based or mobile integrationSAP Gateway OData services
Batch processing with guaranteed orderingHigh-frequency, low-latency microservicesSAP Cloud SDK + API Management
Landscape without SAP BTPFull cloud-native on SAP BTPSAP Integration Suite + Cloud Connector

Important Caveats

Related Units