INTRODUCTION
In this document I'll try to explain the basics of the web services usage giving essential information that are valid for all of them. Each webservice has its own peculiarities and if you need more specific details have a look in Web Service APIs in SAP Cloud for Customer 1511 - November 2015.
In C4C, you can find the webservice list in: "Application and User Management > Input and Output Management > Service Explorer".
This topic is important for developers and analysts that are planning some custom integration or are just looking for another way of query and manipulate information in C4C. You can create the requests using tools like SOAPUI.
Basically, I'll explain how to use Query*In and Manage*In webservices and its main concepts.
My knowledge is still insufficient and I'm sorry if I wrote something wrong and for my english grammar mistakes =P. I hope you like it and, if necessary, please leave a post to correct me, so we can learn together.
QUERY*IN
When you download a webservice .wsdl file and open its definition, you will find the available methods that can be used, such as FindByElements, FindByIdentification, FindByCommunicationData etc, that vary from which webservice you are using. Despite of it, all of them work exactly the same way, but for different purposes. In this example, I'll use the QueryCustomerIn webservice and its FindByElements method.
First of all, lets understand the basic request structure tags.
Each tag SelectionBy<FieldName> filters the query by a field and all of them have the following sub tags:
- IntervalBoundaryTypeCode:
- 1: Equal to
- 2: Between (excl. upper boundary)
- 3: Between
- 4: Between (excl. both boundaries)
- 5: Between (excl. lower boundary)
- 6: Less Than
- 7: Less Than or Equal to
- 8: Greater Than
- 9: Greater Than or Equal to
- Used to specify the initial value.
- Used to specify the upper value. It's not mandatory when the IntervalBoundaryTypeCode is '1'.
This tag is not mandatory. It's used to filter the result size.
- QueryHitsMaximumNumberValue
- Number of records that will be send in the response. By default, only 100 records are returned.
- QueryHitsUnlimitedIndicator
- If true, it blocks the response if exists more records than the number specified in QueryHitsMaximumNumberValue.
- All responses that returns at least one record contains the last returned object ID. I'll show the use of it in the example 6 .
This tag is used to filter the response. You can use it to hide response tags you don't need and, consequently, reduce the message size. I'll show the use of it in the example 4. The table below shows a simplified options descriptions.
1 | Complete Structure | The node element and all its elements, its child node elements and all their elements will be returned. |
2 | Complete Node | The node element and all its elements will be returned. |
3 | Node with Key Elements | The node element and its key elements will be returned (not supported by all web service interfaces). |
4 | Excluded Node | The node element and its child node elements will not be returned. |
- Example 1: Query customer with ID 1000012.
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:glob="http://sap.com/xi/SAPGlobal20/Global">
<soap:Header/>
<soap:Body>
<glob:CustomerByElementsQuery_sync>
<CustomerSelectionByElements>
<SelectionByInternalID>
<InclusionExclusionCode>I</InclusionExclusionCode>
<IntervalBoundaryTypeCode>1</IntervalBoundaryTypeCode>
<LowerBoundaryInternalID>1000012</LowerBoundaryInternalID>
</SelectionByInternalID>
</CustomerSelectionByElements>
</glob:CustomerByElementsQuery_sync>
</soap:Body>
</soap:Envelope>
- Example 2: Query customers with ID between 1000000 and 1000012.
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:glob="http://sap.com/xi/SAPGlobal20/Global">
<soap:Header/>
<soap:Body>
<glob:CustomerByElementsQuery_sync>
<CustomerSelectionByElements>
<SelectionByInternalID>
<InclusionExclusionCode>I</InclusionExclusionCode>
<IntervalBoundaryTypeCode>3</IntervalBoundaryTypeCode>
<LowerBoundaryInternalID>1000000</LowerBoundaryInternalID>
<UpperBoundaryInternalID>1000012</UpperBoundaryInternalID>
</SelectionByInternalID>
</CustomerSelectionByElements>
</glob:CustomerByElementsQuery_sync>
</soap:Body>
</soap:Envelope>
- Example 3: Query customers with ID between 1000000 and 1000012 excluding 1000011.
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:glob="http://sap.com/xi/SAPGlobal20/Global">
<soap:Header/>
<soap:Body>
<glob:CustomerByElementsQuery_sync>
<CustomerSelectionByElements>
<SelectionByInternalID>
<InclusionExclusionCode>I</InclusionExclusionCode>
<IntervalBoundaryTypeCode>3</IntervalBoundaryTypeCode>
<LowerBoundaryInternalID>1000000</LowerBoundaryInternalID>
<UpperBoundaryInternalID>1000012</UpperBoundaryInternalID>
</SelectionByInternalID>
<SelectionByInternalID>
<InclusionExclusionCode>E</InclusionExclusionCode>
<IntervalBoundaryTypeCode>1</IntervalBoundaryTypeCode>
<LowerBoundaryInternalID>1000011</LowerBoundaryInternalID>
</SelectionByInternalID>
</CustomerSelectionByElements>
</glob:CustomerByElementsQuery_sync>
</soap:Body>
</soap:Envelope>
* It's possible to use the same selection tag more than once \o/
- Example 4: Query customers with ID between 1000000 and 1000012 excluding 1000011. The response must contain only the customer node with key elements but the address information must exists.
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:glob="http://sap.com/xi/SAPGlobal20/Global">
<soap:Header/>
<soap:Body>
<glob:CustomerByElementsQuery_sync>
<CustomerSelectionByElements>
<SelectionByInternalID>
<InclusionExclusionCode>I</InclusionExclusionCode>
<IntervalBoundaryTypeCode>3</IntervalBoundaryTypeCode>
<LowerBoundaryInternalID>1000000</LowerBoundaryInternalID>
<UpperBoundaryInternalID>1000012</UpperBoundaryInternalID>
</SelectionByInternalID>
<SelectionByInternalID>
<InclusionExclusionCode>E</InclusionExclusionCode>
<IntervalBoundaryTypeCode>1</IntervalBoundaryTypeCode>
<LowerBoundaryInternalID>1000011</LowerBoundaryInternalID>
</SelectionByInternalID>
</CustomerSelectionByElements>
<RequestedElements customerTransmissionRequestCode="3">
<Customer addressInformationTransmissionRequestCode="1"></Customer>
</RequestedElements>
</glob:CustomerByElementsQuery_sync>
</soap:Body>
</soap:Envelope>
- Example 5: Query customers with ID between 1000000 and 1000012 excluding 1000011. The response must contain only the customer node with key elements but the address information must exists. Only the first customer is needed.
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:glob="http://sap.com/xi/SAPGlobal20/Global">
<soap:Header/>
<soap:Body>
<glob:CustomerByElementsQuery_sync>
<CustomerSelectionByElements>
<SelectionByInternalID>
<InclusionExclusionCode>I</InclusionExclusionCode>
<IntervalBoundaryTypeCode>3</IntervalBoundaryTypeCode>
<LowerBoundaryInternalID>1000000</LowerBoundaryInternalID>
<UpperBoundaryInternalID>1000012</UpperBoundaryInternalID>
</SelectionByInternalID>
<SelectionByInternalID>
<InclusionExclusionCode>E</InclusionExclusionCode>
<IntervalBoundaryTypeCode>1</IntervalBoundaryTypeCode>
<LowerBoundaryInternalID>1000011</LowerBoundaryInternalID>
</SelectionByInternalID>
</CustomerSelectionByElements>
<ProcessingConditions>
<QueryHitsMaximumNumberValue>1</QueryHitsMaximumNumberValue>
<QueryHitsUnlimitedIndicator>false</QueryHitsUnlimitedIndicator>
</ProcessingConditions>
<RequestedElements customerTransmissionRequestCode="2">
<Customer addressInformationTransmissionRequestCode="1"/>
</RequestedElements>
</glob:CustomerByElementsQuery_sync>
</soap:Body>
</soap:Envelope>
* If QueryHitsUnlimitedIndicator is true the request will show an error because I want only one customer but there are more than one for the specified conditions. If you want all customers in the specified conditions, the processing conditions must be:
<ProcessingConditions>
<QueryHitsUnlimitedIndicator>false</QueryHitsUnlimitedIndicator>
</ProcessingConditions>
* Be carefull with timeout and response message size =]
- Example 6: Query the next customer from the previous query.
All responses contains the following tag, that shows how many records have returned, whether there are more records available and the last record node ID:
<ProcessingConditions>
<ReturnedQueryHitsNumberValue>1</ReturnedQueryHitsNumberValue>
<MoreHitsAvailableIndicator>true</MoreHitsAvailableIndicator>
<LastReturnedObjectID>00163E162F981ED5B6FCD7D58739E476</LastReturnedObjectID>
</ProcessingConditions>
Considering this, if you want the next record, in the request, specify the LastReturnedObjectID.
<ProcessingConditions>
<QueryHitsMaximumNumberValue>1</QueryHitsMaximumNumberValue>
<QueryHitsUnlimitedIndicator>false</QueryHitsUnlimitedIndicator>
<LastReturnedObjectID>00163E0924E61EE5B49B609769B5146E</LastReturnedObjectID>
</ProcessingConditions>
It's usefull if you wat to "page" the query results.
MANAGE*IN
The Manage*In webservices are used to create and maintain information and they always have the CheckMaintainBundle and MaintainBundle methods. The CheckMaintainBundle method is equal to the MaintainBundle but not persists the data in C4C, so, can be used to simulate the real request. In this document I'll use the ManageCustomerIn webservice for explanation.
Important request structure tags/attributes:
Most of the nodes have the following attributes/tags:
Attribute to specify the operation. Below, the simplified description is shown:
- 01: Create
- 02: Change
- 03: Delete
- 04: Save (Create if not exists, otherwise, update the record)
- 05: Remove
- 06: No action (check)
- CompleteTransmissionIndicators:
Attributes to specify if the node is complete or not. If you set it to true, all existing nodes that exists in C4C but aren't in the request will be removed from C4C.
- ObjectNodeSenderTechnicalID:
This tag contains a custom ID that represents the node (many nodes have this tag) and is set by the sender. As these webservices accepts many records in the same request (bundle), and considering that if one of them fails then the whole request fails too, this tag is very important to identify which record has failed. The response will return this ID, then you can handle it properly.
- Example 1: Create a customer with address.
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:glob="http://sap.com/xi/SAPGlobal20/Global" xmlns:glob1="http://sap.com/xi/AP/Globalization">
<soap:Header/>
<soap:Body>
<glob:CustomerBundleMaintainRequest_sync_V1>
<BasicMessageHeader></BasicMessageHeader>
<Customer actionCode="01" addressInformationListCompleteTransmissionIndicator="true">
<ObjectNodeSenderTechnicalID>SENDER_CUSTOMER_1</ObjectNodeSenderTechnicalID>
<CategoryCode>2</CategoryCode>
<ProspectIndicator>false</ProspectIndicator>
<CustomerIndicator>true</CustomerIndicator>
<LifeCycleStatusCode>2</LifeCycleStatusCode>
<Organisation>
<CompanyLegalFormCode>14</CompanyLegalFormCode>
<FirstLineName>COMPANY NAME</FirstLineName>
</Organisation>
<ContactAllowedCode>1</ContactAllowedCode>
<AddressInformation actionCode="01">
<ObjectNodeSenderTechnicalID>SENDER_ADDRESS_1</ObjectNodeSenderTechnicalID>
<AddressUsage actionCode="01">
<AddressUsageCode>XXDEFAULT</AddressUsageCode>
<DefaultIndicator>true</DefaultIndicator>
</AddressUsage>
<Address actionCode="01">
<CorrespondenceLanguageCode>PT</CorrespondenceLanguageCode>
<PostalAddress>
<CountryCode>BR</CountryCode>
<RegionCode>PR</RegionCode>
<CountyName>BRASIL</CountyName>
<CityName>Curitiba</CityName>
<DistrictName>CENTRO</DistrictName>
<StreetPostalCode>80000-000</StreetPostalCode>
<StreetName>R TEST</StreetName>
<AdditionalStreetSuffixName/>
<HouseID>225</HouseID>
</PostalAddress>
</Address>
</AddressInformation>
</Customer>
</glob:CustomerBundleMaintainRequest_sync_V1>
</soap:Body>
</soap:Envelope>
- Example 2: Adding a new main address, without modifying the customer and its existing address in C4C.
* The customer information won't change (actionCode="06")
* The address previously created won't be removed (addressInformationListCompleteTransmissionIndicator="false").
* Now it's mandatory to specify the customer key.
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:glob="http://sap.com/xi/SAPGlobal20/Global" xmlns:glob1="http://sap.com/xi/AP/Globalization">
<soap:Header/>
<soap:Body>
<glob:CustomerBundleMaintainRequest_sync_V1>
<BasicMessageHeader></BasicMessageHeader>
<Customer actionCode="06" addressInformationListCompleteTransmissionIndicator="false">
<InternalID>1000058</InternalID>
<AddressInformation actionCode="01">
<ObjectNodeSenderTechnicalID>SENDER_ADDRESS_2</ObjectNodeSenderTechnicalID>
<AddressUsage actionCode="01">
<AddressUsageCode>XXDEFAULT</AddressUsageCode>
<DefaultIndicator>true</DefaultIndicator>
</AddressUsage>
<Address actionCode="01">
<CountryCode>BR</CountryCode>
<RegionCode>PR</RegionCode>
<CountyName>BRASIL</CountyName>
<CityName>Curitiba</CityName>
<DistrictName>CENTRO</DistrictName>
<StreetPostalCode>80000-000</StreetPostalCode>
<StreetName>R TEST 2</StreetName>
<AdditionalStreetSuffixName/>
<HouseID>225</HouseID>
</Address>
</AddressInformation>
</Customer>
</glob:CustomerBundleMaintainRequest_sync_V1>
</soap:Body>
</soap:Envelope>
COMMON ERRORS
In this section I'll describe common error when using webservices. If someone knows some document that explains it better (what are the types, categories etc), I'd be pleased if you post a comment =)
Some of the errors are shown in: "Application and User Management > Input and Output Management > Web Service Message Monitoring".
- A general error in one of the customers in the request to illustrate the importance of the ObjectNodeSenderTechnicalID. The customer with sender ID 'SENDER_CUSTOMER_1' was rejected, but all the others were ok:
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Header/>
<env:Body>
<n0:CustomerBundleMaintainConfirmation_sync_V1 xmlns:n0="http://sap.com/xi/SAPGlobal20/Global" xmlns:prx="urn:sap.com:proxy:KUV:/1SAI/TAE6F3228CC6D723FF1823E:804">
<Log>
<MaximumLogItemSeverityCode>3</MaximumLogItemSeverityCode>
<Item>
<TypeID>286(//APBP/R1/)</TypeID>
<CategoryCode>INC.BOI</CategoryCode>
<SeverityCode>3</SeverityCode>
<ReferenceObjectNodeSenderTechnicalID>SENDER_CUSTOMER_1</ReferenceObjectNodeSenderTechnicalID>
<Note>Business partner 1000058 already exists</Note>
</Item>
</Log>
</n0:CustomerBundleMaintainConfirmation_sync_V1>
</env:Body>
</env:Envelope>
- Some error in the xml structure:
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Header/>
<env:Body>
<env:Fault>
<env:Code>
<env:Value>env:Receiver</env:Value>
</env:Code>
<env:Reason>
<env:Text xml:lang="en">Web service processing error; more details in the web service error log on provider side (UTC timestamp 20160512004624; Transaction ID 00163E162F571EE685FB5E7780150450)</env:Text>
</env:Reason>
<env:Detail/>
</env:Fault>
</env:Body>
</env:Envelope>
- Some issue with the user permissions:
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Header/>
<env:Body>
<env:Fault>
<env:Code>
<env:Value>env:Receiver</env:Value>
</env:Code>
<env:Reason>
<env:Text xml:lang="en">Authorization role missing for service "ServiceInterface http://sap.com/xi/A1S/Global ReadSalesPriceListIn <default> <default>", operation "Operation http://sap.com/xi/A1S/Global Read" (UTC timestamp 20160509191431; Transaction ID 00163E19BB2F1EE685C3483BF5E6CB73)</env:Text>
</env:Reason>
<env:Detail/>
</env:Fault>
</env:Body>
</env:Envelope>
Best regards,
Alexandre Kaminagakura