# SAP Ariba APIs

Note: To view the entire list of SAP Ariba APIs, see [SAP API Business Hub](https://api.sap.com/package/SAPAribaOpenAPIs/rest).

An API can include multiple sub-APIs. For instance, the Operational Reporting for Procurement API (ORP API) is made up of several sub-APIs. With the Fairmarkit integration, we use the [Operational Reporting for Procurement - Synchronous API](#operatio) and [Operational Reporting for Procurement - View Management API](https://api.sap.com/api/procurement_reporting_view_v2/overview). In addition, an API can include a single sub-API. For example, the Document Approval API includes the [Document Approval API: SAP API Business Hub](https://api.sap.com/api/approval_v2/overview) sub-api, which we also use. Each API requires it’s own set of OAuth credentials to access the sub-APIs.

Ariba also has a set of SOAP web services (e.g., [WSDL](https://s1.au.cloud.ariba.com/Buyer/soap/FairmarkitDSAPP-T/RequisitionImportPull?wsdl\&validate=false)).

### Realms <a href="#realms" id="realms"></a>

A particular SAP Ariba instance is identified by the realm. The realm is passed as a query parameter to all API endpoints. A realm that we might use in production will look like *FairmarkitDSAPP*. The corresponding child instance will usually look like *FairmarkitDSAPP-1*. The test instance will look like *FairmarkitDSAPP-T*. The test instance of the child instance will look like *FairmarkitDSAPP-1-T*.

### Operational Reporting for Procurement API <a href="#operatio" id="operatio"></a>

With the Fairmarkit SAP Ariba integration, we use the ORP API to access requisitions. While there are five sub-APIs, we only use the Synchronous API and the View Management API.

In this API, a view is a way to list and filter certain objects in SAP Ariba. These can be created using the View Management API. The Synchronous API is used to get the objects from the view. When setting up a customer, we first create a view for requisitions that can filter by *TimeUpdated* and *Status*. During the integration, we query this view and pull requisitions in status *Submitted* and updated within some window.

#### View Management API

For more information, see [Filter parameters for the Operational reporting API](https://help.sap.com/docs/ariba-apis/operational-reporting-api-for-procurement/filter-parameters-for-operational-reporting-api) and [View template structure](https://help.sap.com/docs/ariba-apis/operational-reporting-api-for-procurement/view-template-structure).

The View Management API allows us to generate a view to get requisition data. To create a view, we need to specify the name of the view, the object we are viewing, the selected fields we are going to include from that object, and the filters we can include to query the object. The available fields and filters can be found by hitting the metadata endpoint for requisitions (this is setup in Postman). Some example fields are:

* AmountAccepted
* ApprovalRequests.AssignedDate
* LineItems.Description.Description

Some example filters are:

* UniqueName
* StatusString
* TimeUpdated

Once a view is created, it will be in draft status. We then need to publish it using the view name. Both of these requests are done in Postman.

Views can be created, but they can’t be edited or deleted. This means that if we have a standard view and name, we want to use it across all customers, making sure that it is available in all instances.

#### Synchronous API

We use the Synchronous API to get all recent requisitions. This API returns a page containing a list of requisitions. Each page can contain 40 requisitions. If there is another page, a page token is added in the response, and that can be used to get the next page.

The ORP API has a rate limit of 3/min, 300/day. This means we can get 120 requisitions before we need to wait for the rate limit to reset. Fetching attachments also counts towards this limit. Increasing the look back window or the frequency of scheduled runs will risk hitting the API rate limit. This may make it difficult to pick up any missed requisitions due to unknown errors.

**Structure**

The requisition data has a unique structure. For example, we have the fields *LineItems.Description.Description* and *LineItems.Description.ShortName*. You would think the . represent nested objects. And that’s true for objects that are lists, like *LineItems* and *ApprovalRequests*.

However, that structure that doesn’t work for json fields. So instead of looking like:

<figure><img src="https://1711751134-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F95QWDcOsKn95Me8sE2RP%2Fuploads%2F4BwRQBvRuMWgZVuL9q5C%2Fariba-req-structure_2.png?alt=media&#x26;token=31e441da-6fff-48b8-a0b6-709f53914978" alt=""><figcaption></figcaption></figure>

The requisition looks like:

<figure><img src="https://1711751134-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F95QWDcOsKn95Me8sE2RP%2Fuploads%2FsG5V9Q0E2ajyeZZ5MYTn%2Fariba-req-structure_1.png?alt=media&#x26;token=ad984bfb-fe60-44ec-8846-c0f9f4e8a751" alt=""><figcaption></figcaption></figure>

### Document Approval API <a href="#document" id="document"></a>

The Document Approval API can be used to get a requisition, check pending approvals of a user, comment on a requisition, and approve a requisition. We use it extensively during integration because it doesn’t have a low rate limit. The requisition data retrieved from the Document Approval API (in code, often referred to as document\_details) looks cleaner than that of the ORP API. Additionally, it contains extra data that isn’t included from the ORP view, such as line comments.

The Document Approval API offers a simple way to add a comment by acting as a certain user. We often use this feature to indicate certain steps of an integration.

We also can approve the requisition as a certain user. We can only approve requisitions when we are the current approver. Otherwise, SAP Ariba will return a 400 error. An approval must contain an approval comment. We have a default message in the client.

### RequisitionImportPull (SOAP Web Service) <a href="#requisit" id="requisit"></a>

While SAP Ariba has well-documented REST APIs to pull data, they are not great for pushing information back into SAP Ariba. So, the integration uses the RequisitionImportPull service to update requisition data. This service was designed to create requisitions and uses Basic Auth.

### Importing requisitions <a href="#importingrequisitions" id="importingrequisitions"></a>

The following outlines how the APIs are used to import requisitions to create requests for quote in Fairmarkit.

#### Current flow

{% stepper %}
{% step %}
Hit an ORP API view that can be filtered by *UpdatedFrom*, *UpdatedTo*, and *Status*. We always filter status by *Submitted*.
{% endstep %}

{% step %}
On the client side, we filter out all requisitions where Fairmarkit is not the current approver.
{% endstep %}

{% step %}
Fetch the requisition from the Document Approval API (if available, this gives us two different versions of the same requisition).
{% endstep %}

{% step %}
Remap the two views of and import the request for quote event into Fairmarkit.
{% endstep %}

{% step %}
Fetch the attachment data from Ariba using the ORP API, and add the attachments and comments to the event.
{% endstep %}

{% step %}
Add a comment on the requisition in Ariba indicating the requisition was imported
{% endstep %}
{% endstepper %}

#### Item titles

To format item titles, we use *Description.Description* and *Description.ShortName*. Description.Description is the main field that we use for the item title. However, sometimes Description.ShortName has an additional description for the item. When it has additional information, we will add it to the regular description. Otherwise, we ignore it.

Additionally, service line items will include start and end dates in the item title.

#### NumberInCollection

Items are identified by a *NumberInCollection* field, which is just the line number. When sending information back to SAP Ariba, this field is very important, so we save it in additional info.

Additionally, *ParentLineNumber* determines group items. If the value is 0, it is a parent item. Otherwise, the item is a child item, and the *ParentLineNumber* will be the *NumberInCollection* of its parent item. Only service items can have this parent-child structure. We import these as Group services. Though, since the group service itself isn’t awarded, only the subitems, we use the Parent item to populate the Group service information and the first subitem information.

#### Tax Items

SAP Ariba tracks taxes on items by creating an entirely new item on the requisition that is hidden on the user interface but exposed in the API. These hidden items have *NumberInCollection* 10000 greater than the original items. For instance, if the regular item has NumberInCollection 1, there will be a hidden number with mostly the same information, but with *NumberInCollection* 10001. We skip these items on import.

### Exporting request for quote events <a href="#exportingrequestforquoteevents" id="exportingrequestforquoteevents"></a>

With the SAP Ariba RequisitionImportPull web service, you can create requisitions. By setting the header level *UniqueName* as an existing requisition, it will instead update that requisition. We use this method to update requisitions.

#### Deleting attachments

SAP Ariba does not have a way to add attachments to a requisition via API. Instead, we add a comment to the requisition indicating the number of supplier attachments.

The SOAP update will delete all line item attachments, so we skip any line item attachments. This is a condition we check on import and export. Header level attachments are preserved.

#### Deleting comments

The SOAP update will delete all comments, but we are able to pull all line item comments before updating. However, only one comment can be added to each line when updating. So, we pull all of the line comments, format them with the user, timestamp, and content, and then add our own comment.

If we have to update twice (e.g. first partial award, then fully award), we check if we made the line comment, and remap it accordingly. For example, if an item is not awarded in the first update, we roll up all existing comments, and add a note indicating the item hasn’t been awarded yet. When the item is awarded, we’d need to roll up all comments again, but we’d want to look out for the comment we already formatted. We’d want to take that comment, remove our original note about how the item hasn’t been awarded yet, roll up any new comments added between the two updates, and then add our regular note we add when awarding a line item.

#### Contracts that block updates

If a line item has an associated contract, we will send the same SOAP update twice. The first will remove the contract id, the second will update the price. This updates the price and removed the contract ID (as intended).

### Awarding to Benchmark <a href="#awardingtobenchmark" id="awardingtobenchmark"></a>

When a request for quote event is exclusively awarded to the benchmark supplier, we don't update with SOAP. If the event is partially awarded, we leave a comment indicating this. If it is fully awarded, we approve and add a comment indicating it is awarded to the benchmark supplier.

#### Parent-Child Service Items

As part of integration, we do not send group services back to SAP Ariba because we don't always have the relevant fields to preserve a group service. We split the group service into separate line items.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.fairmarkit.com/buyers/integrations/sap-ariba-integration/setup-in-sap-ariba/sap-ariba-apis.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
