Skip to Content
Technical Articles
Author's profile photo Babu Lal Limba

Passing base64 encoded raw content as attachment (pdf) to S/4HANA Business Object via Attachment API, using SAP CPI as middleware


I came across a problem while working on a customer project, where we were implementing an interface to upload PDF files to S/4 HANA public cloud business object via Attachments API. Here I am sharing my experience and implementation via this blog with you, hoping that this will be useful to you sometime. Please add your comments and suggestions about this blog.

Use case:

There is an external system which sends, over HTTPS, the pdf file content, encoded as base64, along with other information like the business object and its instance to which the file is to be added. S/4 HANA public cloud uses Attachments API to upload this file to the specified instance of the object Billing Document.

Message format:

The external system sends the payload as mentioned below. This payload includes

  • Billing Document ID (0090000044) to which the pdf file needs to be attached
  • File name to be used for attachment (BLL2.pdf)
  • Content of the pdf file encoded as base64 (highlighted in image). File content should not be sent without encoding for security reasons.




The Attachments API does not consume the base64 encoded file content directly as a message body. It required decoding of this content and obtaining technical parameters before the file could be uploaded to the Billing Document instance. Hence, we need to do these steps in the middleware like SAP CPI and pass the message header and body as expected by Attachments API.


To solve this problem I will focus only on the development required in the middleware (SAP CPI), in this blog. Assuming, below pre-requisites and other required things are already in place.

  • Communication system and Communication user for inbound is defined in S/4. For help refer to blog
  • Communication Arrangement is defined for Billing Integration scenario in S/4. For help refer to blog
  • Have basic idea of various components used in integration flow in SAP CPI
  • Nice to have read the help documentation on Attachments Refer to blog for reading.


We need a middleware like SAP CPI which can decode the base64 content and help to obtain other technical parameters to consume the services of the Attachments API. Thus, we developed an integration flow (iflow) which receives the payload from external system, transforms it and passes it to S/4 system. The contents of the iflow can be seen in the image below.



iflow Overview

Integration flow:

The iflow basically reads the incoming payload and extracts the various elements out of it to prepare the required header and body content that is required by the Attachments API. Iflow does the following steps and activities within.

1. Sender: Element Type: Participants ->Sender

Sender is an external system (element type: Participant) , e.g., postman, which sends the payload over HTTPS to the endpoint of this iflow. The endpoint needs to be defined in this connection as shown in the image. You can give endpoint of your choice.



Define endpoint address


2. Receive Payload (Step 1) : Element Type: Transformation->Content Modifier

  • This component receives the payload (format mentioned above in the picture Payload_format.jpg ) from external system over HTTPS and stores it as part of message body
  • Also, we define a message header element X-CSRF-Token as a constant. The value of X-CSRF-Token  needs to be obtained in next step, by connecting with S/4 system before we can trigger the Attachments  API


Receive payload and define csrf-token


3. Get CSRF-token and Cookie (Step 2): The Attachments API need a CSRF token as part of message header to get invoked. This token and the cookie are retrieved by making a HTTP GET call to S/4 Attachments Later these parameters are passed in step 6 while posting data to the API.

3.1 Create Branch: Element Type: Routing->Multicast->Sequential Multicast

This element is required to send the message to multiple paths in a sequential manner. Since we need to make a call to S/4 to fetch the X-CSRF-Token and at the same time retain the payload body, we need to create two branches that are executed sequentially.



  • Branch 1 is executed first. This makes a GET HTTP call to S/4 endpoint defined in communication arrangement and in response receives the value of the message header elements X-CSRF-Token and  Cookie  which is used later.


HTTP Get CSRF token

  • Branch 2 is processed later, and it just carries the payload as is to next step.

3.2 Aggregate and Merge: Element Type: Routing->Gather

Aggregates the messages coming from two branches. Define the aggregation strategy as shown in the picture.




4. Define Message Headers (Step 3): Element Type: Transformation->Content Modifier

To trigger the Attachments API on S/4 a set of message headers needs be passed along with the body. Define and create these message headers here as shown in the picture and described below

  • Cookie: defined as a constant and the value will be filled using the script
  • X-CSRF-Token: Source type is header i.e., the value is picked from header data
  • Slug: Refers to the name of the file to be uploaded and the value will be filled using the script (fetched from payload)
  • Content-type: Refers to the type of file to be attached and here we hardcode it to application/pdf for PDF file.
  • BusinessObjectTypeName: Refers to the name of the business object to which the file needs to be attached. VBRK refers to Billing Document.
  • LinkedSAPObjectKey: Refers to Billing Document ID in S/4 to which the file needs to be attached. Value will be filled using script (fetched from payload)


Define message headers


5. Set Message Headers & Body (Step 4): Element Type: Transformation->Script->Groovy Script

In this step we will set the values to the message headers defined in previous step. Define a groovy script where you write the logic to read the payload received from external system and set the values of some of the message headers: Cookie, Slug and LinkedSAPObjectKey. The code is mentioned in the image.

A key point to note here is that we must set the message body with the base64 encoded content of the file in scripting (line 21). Only then the decoder can decode it and it can be consumed by S/4.


Script to set message headers


6. Decode Message Body (Step 5): Element Type: Transformation->Decoder->Base64 Decoder

In this step we decode the base64 content of the pdf file passed in the payload under the element <attachment>. The output of this step is the decoded content which can be passed to Attachments API in S/4.

7. Invoke Attachments API (Step 6): Element Type: Call->External Call->Request Reply

In this step the Attachments API on S/4 is triggered by passing the message headers and the message body (which is decoded base64 content) with a POST HTTP call to S/4.

Connect this element to a receiver system, in this case S/4, using HTTP adapter. The connection must be defined as shown in the image below.


POST header and body



The content should be attached as a pdf file to the specified Billing Document in S/4 HANA public cloud system as shown in the image below. You should be able to download this pdf file and open it.


Attachment in Billing Document



To test the process your user should have the required authorization in BTP. Take the following steps to test:

  • Save and deploy the above mentioned iflow.
  • Once successfully deployed go to Monitor->Integration->Manage Integration Content->All.
  • Iflow should appear here, and you should copy the endpoint URL, thus generated.
  • Create a POST request in postman and specify the end point URL obtained in previous step.
  • Specify the payload in Body section as Raw->text file.
  • Click on Send and you should receive a response code 201 for successful operation.
  • Login to S/4 system and open the app Manage Billing Document.
  • Select and open the Billing Document ID that was used in payload for file to attach.
  • You should be able to see the attachment under the Attachments



Assigned Tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo Owen McQuaide
      Owen McQuaide

      Very interesting, thank you Babu.

      Author's profile photo Saumitra Deshmukh
      Saumitra Deshmukh

      Great explanation on a solution to a common challenge!


      Author's profile photo Philip Chen
      Philip Chen

      Thanks for sharing, it is very helpful!

      Author's profile photo Robert Quindt
      Robert Quindt

      Hello Babu,

      thanks for sharing. I have some suggestions on the Iflow.

      1. You Could extract all information in a Content Modifier instead of the Groovy script
      2. You can use the ODATA adapter instead of the HTTPS adapter to leverage the CSRF functionality.


      Modified IFlow:


      Content Modifier:


      OData adapter:


      Simulation Input:

      Simulation Output:


      What do you think about the suggestions?


      Best Regards



      Author's profile photo Allen Chew
      Allen Chew

      Much simplified and worth trying. Thank you.

      Author's profile photo Christopher Linke
      Christopher Linke

      Hello Robert Quindt Robert Quindt

      thank you so much, that helped me with .txt files. BUT, the same algorithm with a base64 PDF File does not work. Here I get this error:



      Author's profile photo Robert Quindt
      Robert Quindt

      Hello Christopher,

      this error is mostly because I did not set the header "Content-Type" to "application/pdf" like in the blog. You can check the send Content-Type by tracing your message. The error would suggest, that the send Content-Type was probably "application/xml". Either set the "Content-Type" manually to "application/pdf" or deside on it based on the file extension.


      best regards



      Author's profile photo Christopher Linke
      Christopher Linke

      Hello Robert Quindt ,

      thanks for your quick reply, unfortunately that's not the reason, Content-Type looks good to me:

      I think what we see in the log/trace is the OData Adapter that changes the Content-Type to XML, no!?

      I sent you a request through a big german business network, maybe we can check my iFlow together!?


      Thank you,



      Author's profile photo Ankit Porwal
      Ankit Porwal

      Please let me know from where I can get details about mandatory headers for this API.