All blog articles
Integrating Nordoon with SAP BTP  for end-to-end PO automation

Integrating Nordoon with SAP BTP for end-to-end PO automation

Jan Rupnik
TIME TO READ:
MINUTES

This articles explains how Nordoon integrates natively with SAP Business Technology Platform (BTP) Integration Suite to automate purchase order confirmation processing.

Nordoon, the agentic AI platform for supply chain automation, equips organizations with AI Agents that transform back-office operations by replicating, expanding, and consolidating day-to-day processes while structuring and cleaning data on the go. SAP BTP Integration Suite ensures these workflows are connected, governed, and extensible across the SAP landscape.

Combined, these 2 technologies give companies a scalable path to intelligent PO automation with full visibility and control.

Here are the 6 aspects of the integration that we are going to further explain in order to illustrate a production-ready, working integration (not a theoretical architecture).

1.       Complete BPMN flow canvas: Full integration flow showing all steps and system connections.

2.       Message processing log: Real execution showing 15.7-second processing time and processed PO data.

3.       Groovy script editor: Implementation of Nordoon's API request construction.

4.       Nordoon Agent data flow: Configuration of the PO Processing AI Agent.

5.       Nordoon REST API connector: Secure API key management and multi-tenant setup.

6.       SAP API Business Hub: Purchase Order OData service used for validation.

The power of native integration

Nordoon is an agentic platform designed designed to be incorporated into sophisticated automation workflows.

This integration showcases Nordoon’s technical flexibility for:

  • Native BTP integration: Deploys as a standard integration flow in SAP Integration Suite.
  • Enterprise-grade orchestration: Combines AI processing with SAP validation and write-back operations.
  • Extensibility: Provides the foundation for SAP Events, Business Workflow approvals, and multi-system orchestration.
  • Operational excellence: Full monitoring, logging, and error handling through SAP’s standard tooling.

Architecture overview

Integration flow components

The integration flow (POAgent) orchestrates a multi-step process that spans three systems: External System → SAP BTP Integration Suite →Nordoon AI → SAP S/4HANA


Key technical participants:

1.       Sender (HTTPS): External system sending PDF documents

2.       Nordoon_AI: AI Agent platform processing documents

3.       SAP_S4HANA: Enterprise system for validation and data persistence

Process flow sequence

Figure 0: Complete BPMN 2.0 integration flow canvas in SAP Integration Suite showing the “PO Agent Flow” end-to-end.

The flow orchestrates the communication between three systems (Sender, Nordoon_AI, SAP_S4HANA) through a series of transformation steps, API calls, and validation logic. Each box represents a processing step (Content Enricher, Groovy Script, or HTTP Service Task), connected by sequence flows. This visual representation demonstrates the enterprise-grade orchestration capabilities of SAP BTP.

Flow overview

Process flow sequence showing all 12 steps from HTTPS trigger to end event. Color coding: Green (Start/End), Blue(HTTP calls to external systems), Yellow (Groovy scripts for data transformation), White (Content enrichers for header/property management).

Key components visible in Figure 0:

  • Start Event (HTTPS): Receives incoming PDF documents
  • Content Enrichers (blue boxes): Set headers and properties
  • Groovy Scripts (gear icons): Data transformation and validation logic
  • Service Tasks (external call icons): HTTP calls to Nordoon and SAP APIs
  • Message Flows (dashed lines): Show communication with external systems
  • Sequence Flows (solid lines): Processing order within integration flow

Technical implementation details

1. Integration flow definition

Technology Stack:

  • Standard: BPMN 2.0 (Business Process Model and Notation)
  • Runtime: SAP Cloud Integration (BTP Integration Suite)
  • Scripting:Groovy (Apache Groovy 2.4+)
  • Protocol: HTTP/HTTPS with OAuth/API Key authentication

Integration Flow File: PO Agent.iflw

  • Component version: 1.2
  • Transaction handling: Not Required (stateless)
  • Transaction timeout: 30 seconds
  • Logging: All events captured

2. Entry Point: HTTPS sender adapter

Endpoint configuration:

URL Path:/po-confirmation/extract
Protocol: HTTPS (TLS 1.2+)
Authentication: Role-Based (ESBMessaging.send)
Max Body Size: 40 MB
XSRF Protection: Disabled (API endpoint)

Security model:

  • Role-based authorization ensures only authenticated callers can trigger the flow
  • Supports client certificate authentication
  • No basic authentication (enterprise SSO integration)


3. Nordoon AI integration layer

Step 3a: Prepare Nordoon request

Content Enricher Pattern (CallActivity_5)

  • Creates exchange properties for API credentials
  • Stores: nordoon.api.key, nordoon.endpoint.uuid, sap.api.key
  • Credentials sourced from secure SAP credential store (production best practice)

Step 3b: Build request payload

Script:
build_nordoon_request.groovy

Figure1: Groovy script editor in SAP Integration Suite showing the build_nordoon_request.groovy implementation.

The editor provides syntax highlighting, code folding, and integrated validation. Note the structured JSON construction and debug logging for security (only first 10 characters of API key logged).

def nordoonRequest = [
    name: 'PO Confirmation ' + new Date().format('yyyy-MM-dd HH:mm:ss'),
    input_file: [
        filename: 'confirmation.pdf',
        mimetype: 'application/pdf',
        base64: pdfContent  // Base64-encoded PDF from sender
    ]
]


Key technical aspects:

  • Accepts PDF as base64-encoded string in HTTP body
  • Constructs JSON payload conforming to Nordoon API v2.0 spec
  • Sets Content-Type: application/json header
  • Injects API key via x-api-key header
  • Generates unique job name with timestamp for traceability
  • Includes debug logging attachment for troubleshooting (visible in Message Processing Logs)


Step 3c: Call Nordoon API

Nordoon Agent Configuration

Figure2: Nordoon platform showing the “SAP BTP Order Confirmations Flow”configuration.

The agent data flow consists of a RESTAPI trigger, business logic agent, and REST API output formatter.

The endpoint UUID (320da0f68c324e019547d2e8a8118cc2) uniquely identifies this agent configuration.

Figure3: REST API connector configuration in Nordoon showing tenant ID, region (EU),and API key management.

This connector is used by the “SAP BTP Order Confirmations Flow” as an Agent Data Flow, demonstrating how Nordoon Agents can be reused across multiple automation workflows.

HTTP adapter configuration:

Endpoint: https://app-eu.nordoon.ai/api/v2.0/public/extract/${property.nordoon.endpoint.uuid}/sync/
Method: POST
Timeout: 60000ms (60 seconds)
Retry: 1 iteration, 5-second interval
Authentication: API Key (x-api-key header)
Region: EU (app-eu.nordoon.ai)


Synchronous processing:

  • Uses /sync/ endpoint for real-time response
  • Nordoon processes document and returns structured JSON
  • No polling required, the AI agent completes processing within timeout window

Response structure:

{
  "result": [{
    "General Info": {
      "Purchase Order Number": "4500000001"
    },
    "Items": [
      {
        "Item Number": "10",
        "Material Description": "VAI101 - Widget Type A",
        "Confirmed Quantity": "100",
        "Confirmed Delivery Date": "2025-11-20"
      }
    ]
  }]
}


Step 3d: Parse Nordoon Response

Script: parse_nordoon_response.groovy

def nordoonResult = jsonSlurper.parseText(responseBody)

// Extract structured data from AI agent response
def poNumber = nordoonResult.result[0]?.'General Info'?.'Purchase Order Number'
def items = nordoonResult.result[0]?.Items

// Store in message exchange properties
message.setProperty('po.number', poNumber)
message.setProperty('po.items.count', items?.size()?.toString() ?: '0')
message.setProperty('nordoon.result', responseBody)  // Full result for transformation

// Set PO number as body for next step (SAP validation)
message.setBody(poNumber)


Data processing:

  • Safe navigation operators (?.) handle missing fields gracefully
  • Stores full AI response for downstream processing
  • Extracts PO number and item count as discrete properties
  • Prepares body for SAP OData GET request

4. SAPS/4HANA integration layer

Step 4a: Validate that PO exists in SAP
Purpose:
Verify that the PO number processed by Nordoon actually exists in SAP before posting confirmations.

Figure4: SAP API Business Hub showing the Purchase Order Process Service API (API_PURCHASEORDER_PROCESS_SRV). The “Try Out” functionality in the Sandbox environment allows testing the GET /A_PurchaseOrder(‘{PurchaseOrder}’)endpoint.

This same OData service is used in the integration flow to validate PO numbers extracted by Nordoon.

HTTP GET request:

Endpoint: https://sandbox.api.sap.com/s4hanacloud/sap/opu/odata/sap/API_PURCHASEORDER_PROCESS_SRV/A_PurchaseOrder('${in.body}')
Method: GET
Headers:
  - Accept: application/json
  - apikey: ${property.sap.api.key}


Real-world example:

  • Nordoon extracts PO Number: 4500003529
  • SAP Integration Suite constructs OData URL: /A_PurchaseOrder('4500003529')
  • SAP validates existence and returns PO master data
  • Flow proceeds only if validation succeeds (HTTP 200)

Dynamic URL Construction:

  • ${in.body} contains PO number from Nordoon parsing step
  • OData V2 entity retrieval by key
  • Example: /A_PurchaseOrder('4500000001')

Validation script: check_call_got_200.groovy

Endpoint: https://sandbox.api.sap.com/s4hanacloud/sap/opu/odata/sap/API_PURCHASEORDER_PROCESS_SRV/A_PurchaseOrder('${in.body}')
Method: GET
Headers:
  - Accept: application/json
  - apikey: ${property.sap.api.key}


Error handling

  • 200: PO exists, proceed to transformation
  • 404: PO not found in SAP (data mismatch)
  • 401: Authentication failure
  • Other: Network/API errors

Step 4b: Tranform to SAP OData format


Script:
transform_to_sap_format.groovy

if (item.'Confirmed Quantity') {
        sapConfirmations.add([
            PurchaseOrder: poNumber,
            PurchaseOrderItem: item.'Item Number',
            ConfirmedQuantity: (item.'Confirmed Quantity' as Integer),
            ScheduleLineDeliveryDate: item.'Confirmed Delivery Date' ?: null,
            Material: extractMaterialNumber(item.'Material Description'),
            Plant: "1000"
        ])
    }
}


Data mapping:


Material number:

def extractMaterialNumber(String description) { def parts = description.split(' - ') return parts.length > 0 ? parts[0].trim() : description }

Output payload:

{ "confirmations": [ { "PurchaseOrder": "4500000001", "PurchaseOrderItem": "10", "ConfirmedQuantity": 100, "ScheduleLineDeliveryDate": "2025-11-20", "Material": "VAI101", "Plant": "1000" } ] }

Step 4c: Post Confirmations to SAP

HTTP POST request:

Endpoint: https://sandbox.api.sap.com/s4hanacloud/sap/opu/odata/sap/API_PURCHASEORDER_PROCESS_SRV/A_PurchaseOrderScheduleLine Method: POST Headers: - Accept: application/json - Content-Type: application/json - apikey: ${property.sap.api.key}

Production considerations:

  • For multiple items, use OData $batch endpoint for atomic operations
  • Transaction handling ensuresall-or-nothing posting
  • SAP will trigger workflow events (PO confirmationposted)

Step 4d: Response validation

Script: post_to_sap_check.groovy

if (responseCode >= 200 && responseCode < 300) { // Success String successResponse = """ { "status":"success", "message":"PO confirmation posted to SAP successfully", "po_number":"${poNumber}", "items_confirmed":${itemsCount}, "sap_response_code":${responseCode} } """ message.setBody(successResponse) } else if (responseCode == 405) { // Sandbox limitation - treat as success String successResponse = """ { "status":"success_simulated", "message":"PO validated successfully. Posting simulated (sandbox limitation)", "note":"SAP sandbox does not allow POST operations..." } """ message.setBody(successResponse) }

Response codes:

  • 2xx: Successful posting, return confirmation JSON
  • 400: Bad request, data validation failed
  • 401: Authentication error
  • 405: Method not allowed (sandbox limitation, production returns 201)

Monitoring and observability

ABOUT THE AUTHOR
Jan Rupnik

Enjoyed this read?

Subscribe to our newsletter, and we will send AI automation insights like this straight to your inbox on a regular basis.