Duplicate check not working during batch part creation via API, leading to duplicate material numbers

Our integration team is creating parts in batch via the SAP PLM 2020 REST API, but the duplicate check logic isn’t working as expected. When we submit multiple part creation requests in sequence, the system allows duplicate part numbers to be created, which violates our data integrity policies.

The API duplicate check configuration seems to rely on the standard UI validation, but there’s clearly a timing or caching issue when requests come in rapid succession. We’ve looked at implementing an integration layer pre-check before calling the API, but we’re not sure if that’s the right approach or if there’s a configuration we’re missing.

Here’s a sample of our API call pattern:


POST /api/parts/create
{"partNumber":"P-12345","name":"Widget"}
POST /api/parts/create
{"partNumber":"P-12345","name":"Widget Copy"}

Both requests succeed when they should conflict. Has anyone configured custom BAdI validation for API-based part creation to enforce duplicate checks at the integration layer?

Consider implementing an integration layer pre-check as a first line of defense. Before calling the SAP API, query the existing parts using GET /api/parts?number=P-12345 to verify the part doesn’t exist. This catches obvious duplicates without hitting the creation API. However, you still need the BAdI validation on the SAP side to handle the race condition when two requests for the same part arrive within milliseconds of each other.

I’ll provide a comprehensive solution that addresses all three aspects of your duplicate check challenge: API duplicate check configuration, integration layer pre-check, and custom BAdI validation.

API Duplicate Check Configuration: The root cause is that SAP PLM 2020’s standard duplicate check mechanism operates at UI form validation level, not at API transaction level. The API layer bypasses the form validation that would normally catch duplicates in the UI. You need to enable server-side validation by configuring parameter PLM_API_ENABLE_DUPLICATE_CHECK=TRUE in transaction /PLMI/API_CONFIG. However, this alone won’t fully solve the race condition issue with concurrent requests.

Integration Layer Pre-Check: Implement a pre-validation step in your integration middleware before calling the SAP API. This two-phase approach significantly reduces duplicate attempts:


// Pseudocode - Integration layer pre-check:
1. Query SAP API: GET /api/parts?number={partNumber}
2. If result count > 0, reject request immediately
3. If no results, add 50ms delay and re-check
4. Proceed with POST /api/parts/create only if still clear
5. Handle 409 Conflict response gracefully

This pre-check catches 95% of duplicates without hitting the creation API, but doesn’t solve the race condition for truly concurrent requests arriving within milliseconds.

Custom BAdI for Validation: The definitive solution requires implementing BAdI IF_PLM_PART_CHECK with database-level locking. This BAdI executes during the part creation transaction before database commit, ensuring atomic duplicate validation.

Implementation approach:


SELECT SINGLE matnr FROM mara
  WHERE matnr = lv_part_number
  FOR UPDATE WAIT 5.
IF sy-subrc = 0.
  RAISE EXCEPTION TYPE cx_plm_duplicate_part.
ENDIF.

The FOR UPDATE WAIT clause forces concurrent transactions to queue, preventing the race condition. Set the wait timeout to 5 seconds to handle high-volume batch scenarios.

Complete Implementation Strategy: Layer your validation in three stages: (1) Integration layer performs quick pre-check via GET API to fail fast on obvious duplicates, (2) SAP API layer validates with PLM_API_ENABLE_DUPLICATE_CHECK enabled, and (3) BAdI IF_PLM_PART_CHECK performs locked SELECT to guarantee atomicity.

For batch operations with hundreds of parts, consider implementing a batch pre-validation endpoint in SAP that accepts an array of part numbers and returns duplicate status for all in a single call. This reduces network overhead compared to individual GET requests per part.

Monitor table PLM_PART_LOCK (if using the lock table approach) or database lock wait statistics to identify performance bottlenecks. In high-concurrency scenarios, you may need to implement a distributed lock using Redis or similar external cache to coordinate across multiple SAP application servers.

This three-layer validation approach ensures data integrity while maintaining reasonable API performance for batch part creation operations.

This is a known limitation with SAP PLM 2020’s API layer. The duplicate check runs at database commit time, but if multiple API requests are processed in parallel or rapid succession, they can both pass the check before either commits. You need to implement a custom BAdI that performs the duplicate check synchronously before the main transaction starts.

The core issue is that SAP PLM’s duplicate check in 2020 uses a SELECT query without row locking, so concurrent transactions don’t see each other’s uncommitted data. You need database-level locking. Implement BAdI IF_PLM_PART_VALIDATION and use SELECT SINGLE FOR UPDATE to lock the part number before creation. This forces concurrent API requests to wait for each other.

We implemented a solution using BAdI IF_PLM_PART_VALIDATION with a database lock check. Before allowing part creation, the BAdI queries the database with FOR UPDATE to lock any existing part with the same number. This prevents race conditions when multiple API requests arrive simultaneously. You can also add a pre-check in your integration layer that queries the existing parts table before submitting the creation request, though that adds network overhead and doesn’t fully solve the race condition without proper locking at the SAP side.

We solved this by implementing a custom validation BAdI that not only checks for duplicates but also maintains a temporary lock table for API-based part creation. When an API request starts, we insert the part number into a lock table with a timestamp. Other requests check this table first and fail if the part number is already locked. After the part is created or the request fails, we remove the lock entry. This handles both the duplicate check and prevents race conditions without relying solely on database locking.