Skip to Content
Technical Articles

SAP Business ByDesign – OData API Examples

The SAP Business ByDesign OData API for Business Objects is designed for user centric applications to access business objects in SAP Business ByDesign.

The OData API provides you with additional metadata to ease UI development, such as localized field labels, code descriptions, value help support.
In addition the API supports typical navigations between business object nodes like “from header to detail”, navigations to associated business objects (for example “from sales order item to product details”) and efficient fine grained data access.

The authentication using business users enable you to combine frontend single sign-on and principal propagation using OAuth to benefit from the role-based authorization management of ByD. Of course you can use basic authentication (user/password) as well.

Using the work center view “Application and User Management – OData Services”, key users are empowered to decide which business objects, business object elements and actions are exposed via OData APIs. Those Custom OData Services may cover the OData-enabled part of the Public Solution Model (PSM) of ByD, key user extension fields and SAP Cloud Applications Studio Add-ins.

You find more information in the SAP Business ByDesign Help Portal by searching with key words “OData User Guide”.

API Sample Packages

To get some hands-on experience using the OData API for Business Objects you find a repository of API Examples on GitHubSAP Business ByDesign – API Usage Samples.

The repository is structured in API sample packages. Each package contains Postman collections, a Postman environment and all ByD Custom OData Services required to run the OData requests of the Postman collection.

All sample Postman collections are tailored to SAP Business ByDesign Partner Demo Tenants (Full scope US) with preconfigured and loaded sample data provided by SAP.

Nevertheless you can use the Postman collections and sample Custom OData Services in other ByD systems as well, if you adopt Postman environment variables and Postman requests according the business configuration and master data of your ByD system.

The following API sample packages are available:

  • End-to-End Scenarios: Run ByD business processes using APIs to get insights how to create, change and read involved business documents and how to create business document relationships to achieve a meaningful document flow
    • Lead to Opportunity to Quote
    • Selling Services
    • Field Service and Repair
    • Procure to Stock
    • Sell from Stock
    • Drop Shipment
    • Make to Stock
    • Clear Due Items using Bank Statements
  • Projects: Create, change and read cost collecting projects and customer projects
    • Cost collecting projects with task hierarchies
    • Cost collecting projects with team and work
    • Customer projects with planning data
    • Selling project-based services incl. sales order, project and project time recordings
  • Sales Orders: Create, change and sales orders; contains examples to use business object attachments as well
  • Analytics: Access ByD built-in analytics incl. reports and data sources
  • Product and Service Portfolio: Create, change and read price lists and discount lists
  • Product Data: Create, change and read materials and service products

Please check the description of the respective Postman collection for further details about the individual steps performed for each scenario.

How to run an API Sample Scenario?

The easiest way to run an API sample scenario would be using a SAP Business ByDesign Partner Demo Tenant (Full scope US) with preconfigured and loaded sample data provided by SAP.
The following example is based on such a tenant and I am running the scenario “End-to-End Scenarios – Procure to Stock“:

  1. Install the API sample package “End-to-End Scenarios” and configure your ByD system following the instructions in  chapters “Download and Installation” and “Configuration” of the GitHub repository readme file.
  2. Open the Postman Runner and select the collection “End-to-End Scenarios”, the collection folder “Procure to Stockand the environment “ByD End-to-End Scenarios …“:
         
  3. Click on “Run Procure to Stock” and see the process flow:
         

If you are using OData services the first time or after ByD upgrades/patches you may need to start the process twice, because my settings in Postman might be too short for recompiling ByD objects.

For more detailed analysis you can open the Postman Console to log detailed traces or simply execute the requests one-by-one in the Postman collection itself.

By the way:
The sample Postman collections may serve as well as approach to create meaningful data along process chains to prepare a ByD system for demo purposes, or to run regression tests by processing end-to-end business processes.

Blog Posts with further Examples

8 Comments
You must be Logged on to comment or reply to a post.
  • Update of API sample package “End-to-End Scenarios”:

    • Sample OData service tmserviceorder.xml enhanced by service order lifecycle status
    • Scenario “Drop Shipment”: SOAP request to create third-party delivery notification replaced by corresponding OData request.
    • Scenario “Procure to Stock”: Request “Accept supplier invoice exception” removed (not needed after ByD update to SP02)
  • Thanks Knut Heusermann  for this very helpful blog.

    We have a doubt about Sales Order Item Pricing:

    We are building an integration which fits on “Selling Services Scenario” provided on the API Sample Package.

    Since our Services are not price defined, we tried to create a SalesOrder indicating the price on each Item, but we got an error.

    We also tried to update the SalesOrder when it is created, and since we get no error, the price is not updated.

    Could help us with that? We saw that it is possible to do on SOAP, but for this integration we are building, REST is a Must.

    Thank you.

    • Hi Marc,

      my OData sample for sales orders assume that prices and taxes are calculated by ByD. As of today sales order price components are not yet OData enabled and hence the sales order SOAP service would be the only possibility to create sales orders with given prices.

      In general I would suggest to request an enhancement of the public solution model as described in my blog post SAP ByDesign Public Solution Model, but very likely enabling the sales order price components is no quick fix.

      Best regards,
      Knut

  • Update of API sample package “Projects”: Added a sample Custom OData Service and corresponding Postman OData requests to create and read project time recordings.

  • Hello.

    Using the provided POST request “Update fulfilled quantity” in the “Field Service and repair” Scenario, we are getting the following error:

    The server has not found any resource matching the Data Services Request URI.

    Has anyone ever found a solution for this?

    Thank you in advance.

     

     

    • Hi Marc,

      I’m using Postman environment variables in the OData URL. Those variables are either values provided or are populated by previous requests.

      In your request the environment variable “ServiceConfirmationItemScheduleLineObjectID” seems to be empty or invalid. Please enter a valid value for variable “ServiceConfirmationItemScheduleLineObjectID” in your Postman environment or run the OData requests of folder “Field Service and Repair” in the given sequence such that the variable is populated by request “Get service confirmation” (see Postman request test script of request “Get service confirmation”).

      Best regards,
      Knut

  • Hi Knut,

    We’ve got a requirement to create Customer Invoice Requests directly via OData rather than via Sales Orders. Looking at the PSM, it should be possible to create a Customer Invoice Request by setting Business Process Variant Type to 3 (for a manual request), the CustomerInvoiceProcessingTypeCode to CI and buy setting the buyer party and sales unit party (as well as items of course).

    I’ve taken your example web service for Selling Services and have imported the customer invoice request service into my BYD tenant and then altered the service to expose the relevant fields and objects.

    However when I try to create a request with a POST, I find that the Sales Unit Party is read only. I am able to set the Business Process Variant Type, and the CustomerInvoiceProcessingTypeCode but the sales unit party ID is read only.

    Is this why you’ve used a sales order and then released the order, and then get the invoice request from the sales order ID, because you ca’t create an invoice request directly?

    Greg

    • Hi Greg,

      I’m using sales orders because of the scenario that I realized (for example incl. deliveries and ATP check); using sales orders was not intended as workaround for creating invoice requests directly.

      You can change the sales unit party of customer invoice requests by a Patch on the corresponding resource of the SalesUnitPartyCollection. The fact that you can’t create the sales unit party with the invoice request directly is a gap in our PSM for OData.
      However, if you dig deeper you will find out that there are more invoice request elements not yet create/update enabled or missing and hence as of today you can’t create an external customer invoice request using OData.
      For that reason, I would suggest to use the SOAP API Manage Customer Invoice Requests to create external customer invoice requests. This API provides you with the possibility to create and change invoice requests incl. prices and external payments, and you can furthermore trigger invoicing directly.

      Here is an example for an invoice request using API Manage Customer Invoice Requests:

      <?xml version="1.0" encoding="UTF-8"?>
      <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:glob="http://sap.com/xi/SAPGlobal20/Global" xmlns:glob1="http://sap.com/xi/AP/Globalization">
          <soapenv:Header/>
          <soapenv:Body>
              <glob:CustomerInvoiceRequestBundleMaintainRequest_sync>
                  <BusinessDocumentBasicMessageHeader>
                      <!-- Enter message header UUID for idem potency! -->
                      <!-- <UUID>?</UUID> -->
                  </BusinessDocumentBasicMessageHeader>
                  <CustomerInvoiceRequest actionCode="01" itemListCompleteTransmissionIndicator="false">
                      <ObjectNodeSenderTechnicalID>HDR_1</ObjectNodeSenderTechnicalID>
                      <BaseBusinessTransactionDocumentID>{{CustomerInvoiceRequestID}}</BaseBusinessTransactionDocumentID>
                      <Name>My customer invoice with external payment</Name>
                      <!-- SettlementPriorityCode: 
                       1 = Immediate - create custom invoice, 
                       2 = Urgent - stop if a down payment exists
                       3 = Normal - save invoice request with status "to be invoiced" -->
                      <SettlementPriorityCode>1</SettlementPriorityCode>
                      <ReferenceBusinessTransactionDocumentID>{{InvoiceRequestExternalReference}}</ReferenceBusinessTransactionDocumentID> <!-- External Reference -->
                      <BuyerParty>
                          <InternalID>{{CustomerID}}</InternalID>
                      </BuyerParty>
                      <SalesUnitParty>
                          <InternalID>{{SalesUnitID}}</InternalID>
                      </SalesUnitParty>
                      <CashDiscountTerms>
                          <!-- 1001 = immediately net; 1006 = 10 days 5% -->
                          <Code>1001</Code>
                          <!-- <FullPaymentEndDate>2019-05-30</FullPaymentEndDate> -->
                      </CashDiscountTerms>
                      <PaymentControl>
                          <!-- PaymentFormCode: 04 = Direct Debit, 20 = External Payment -->
                          <PaymentFormCode>20</PaymentFormCode>
                          <PaymentReferenceID>{{PaymentReferenceID}}</PaymentReferenceID>
                          <!-- used to clear the payment -->
                          <PaymentReferenceTypeCode>5</PaymentReferenceTypeCode>
                          <PaymentServiceSubscriberID>{{CompanyID}}</PaymentServiceSubscriberID>
                          <PaymentServiceCustomerID>{{CustomerID}}</PaymentServiceCustomerID>
                          <ExternalPayment actionCode="01">
                              <!-- <UUID>?</UUID> -->
                              <!-- Bank Account ID from UI screen My Bank >> View All >> Bank Accounts -->
                              <HouseBankAccountKeyInternalID>{{HouseBankAccountID}}</HouseBankAccountKeyInternalID>
                              <!-- House bank: 1000644 - ABN AMRO Bank -->
                              <PaymentTransactionReferenceID>{{PaymentTransactionReferenceID}}</PaymentTransactionReferenceID>
                              <DocumentDate>{{DocumentDate}}</DocumentDate>
                              <ValueDate>{{ValueDate}}</ValueDate>
                              <Amount currencyCode="USD">220</Amount>
                          </ExternalPayment>
                      </PaymentControl>
                      <PricingTerms>
                          <!-- PricingProcedureCode: PPGP02 = Standard Gross Procedure, PPSTD1 = Standard Procedure -->
                          <PricingProcedureCode>PPGP02</PricingProcedureCode>
                          <CurrencyCode>USD</CurrencyCode>
                      </PricingTerms>
      <!-- Invoice item | service product | tax code derived by system -->
                      <Item>
                          <BaseBusinessTransactionDocumentItemID>10</BaseBusinessTransactionDocumentItemID>
                          <!-- ReceivablesPropertyMovementDirectionCode: 1 = Invoice item, 2 = Credit memo item -->
                       <ReceivablesPropertyMovementDirectionCode>2</ReceivablesPropertyMovementDirectionCode>
                          <!-- <Description languageCode="EN">My invoice item</Description> -->
                          <CashDiscountDeductibleIndicator>false</CashDiscountDeductibleIndicator>
                          <Product>
                              <InternalID>{{ServiceProductID2}}</InternalID>
                              <TypeCode>2</TypeCode>
                          </Product>
                          <Quantity unitCode="HUR">10</Quantity>
                          <QuantityTypeCode>TIME</QuantityTypeCode>
                          <PriceAndTax>
                              <!-- List Price -->
                              <PriceComponent>
                                  <!-- TypeCode: 8PR1 = Gross list price, 7PR1 = Net list price -->
                                  <TypeCode>8PR1</TypeCode>
                                  <Rate>
                                      <DecimalValue>120</DecimalValue>
                                      <CurrencyCode>USD</CurrencyCode>
                                      <BaseDecimalValue>10</BaseDecimalValue>
                                      <BaseMeasureUnitCode>HUR</BaseMeasureUnitCode>
                                  </Rate>
                              </PriceComponent>
                          </PriceAndTax>
                          <ObjectNodeSenderTechnicalID>ITM_1</ObjectNodeSenderTechnicalID>
                      </Item>
      <!-- Invoice item | free text -->
                      <Item>
                          <BaseBusinessTransactionDocumentItemID>20</BaseBusinessTransactionDocumentItemID>
                          <ReceivablesPropertyMovementDirectionCode>2</ReceivablesPropertyMovementDirectionCode>
                          <Description languageCode="EN">My free text invoice item</Description>
                          <CashDiscountDeductibleIndicator>false</CashDiscountDeductibleIndicator>
                          <Quantity unitCode="EA">1</Quantity>
                          <QuantityTypeCode>EA</QuantityTypeCode>
                          <PriceAndTax>
                              <!-- List Price -->
                              <PriceComponent>
                                  <TypeCode>8PR1</TypeCode>
                                  <Rate>
                                      <DecimalValue>100.00</DecimalValue>
                                      <CurrencyCode>USD</CurrencyCode>
                                  </Rate>
                              </PriceComponent>
                          </PriceAndTax>
                          <ProductTaxDetails>
                              <ProductTaxationCharacteristicsCode listID="US">500</ProductTaxationCharacteristicsCode>
                          </ProductTaxDetails>
                          <AccountingCodingBlockAssignment>
                              <AccountingCodingBlock>
                                  <AccountingCodingBlockTypeCode>ACC</AccountingCodingBlockTypeCode>
                                  <GeneralLedgerAccountAliasCode>A-1700</GeneralLedgerAccountAliasCode>
                              </AccountingCodingBlock>
                          </AccountingCodingBlockAssignment>
                          <ObjectNodeSenderTechnicalID>ITM_2</ObjectNodeSenderTechnicalID>
                      </Item>
                  </CustomerInvoiceRequest>
              </glob:CustomerInvoiceRequestBundleMaintainRequest_sync>
          </soapenv:Body>
      </soapenv:Envelope>

      Best regards,
      Knut