Solved

REST API request with paramaters (list) based on previous request

  • 14 January 2021
  • 12 replies
  • 204 views

Although I'm following the steps explained on this page (https://legacysupport.timextender.com/hc/en-us/articles/360034695651-Connect-to-a-REST-API), I can't figure out what's going wrong.

Situation: I have a REST API, with two endpoints: one for fetching all locations (locationId) and one for fetching all reviews per location. I need the locationId from the first request, iterate trough all locationId's and request the reviews per location. 
 

First request is working perfectly, REST.json is loaded with all locations. 

For the second request, I've edited the RSD file, with an input parameter and filter (I know, the URL is mentioned twice, don't know which one is correct):


Then I added a dynamic filter:


However, no results. Does anyone know what I'm doing wrong? Can someone point me in the right direction? Thanks in advance!

icon

Best answer by Thomas Lind 14 January 2021, 13:38

View original

12 replies

Userlevel 5
Badge +5

Hi Thye

I recently upgraded the guide, as I found that there is a better method to do what you attempt.

https://legacysupport.timextender.com/hc/en-us/articles/360052383191-Creating-and-using-RSD-files-for-CData-providers#Nested 

The idea is to make one call to get the locationId and then use it in an nested call with an replace statement. The same time I use an enum feature to use pagination as well.

Hi Thomas,

Thanks for your quick reply. First of all; thanks to the comprehensive guide. However, it's a bit overwhelming for me I think. I'm mixing up pagination with parameters, and now you introduce nested calls. Looks like the nested calls variant is more complex. Could you help me out with a sample based on the Post example, where you have two requests and you fill the {PostId} in the second query, based on the first one.
Assuming that I have two RSD's: locations and reviews. The first one contains a locationId, exactly like the PostId in the example. 
1) What should I add to the location RSD? (Should I add something??)
2) What shoud I add to the review RSD?
- input parameter:

<input name="locationId" xs:type="string" other:filter="{locationId}" />

- BaseUrl mapping:

api:set attr="BaseURI" value="https://blablapi.com/{locationId}" />

- map Location in custom parameter:

[locationId] IN (SELECT [locationId] FROM REST.json)

Sorry for the newbe question; like I said: I'm mixing up some things. Hope you point to the fault I'm making.

 

Hi Thomas, 
Any idea what I'm doing wrong? 
Or could you maybe post the two RSD files, used for the Post & Comments request, from your example? The new files, which are available for download, doesn't contain the 'old' example, in which you create the request for Comments ({PostId}) based on a previous request with all the postId's.

Thanks in advance!!

Userlevel 5
Badge +5

You should use my suggested method, but I can see you aren't doing it correctly. If you look at my guide for doing inputs, you need to call it in a different manner.

  <api:script method="GET">
<api:check attr="_input.datein">
<api:set attr="URI" value="http://data.fixer.io/api/[_input.datein]?access_key=522b683569a91b66be6be214027b47bf"/>
</api:check>
<api:call op="jsonproviderGet">
<api:push/>
</api:call>
</api:script>

Hi Thomas,

Thanks for your answer. I'm almost there.

The reason we don't like the nested approach very much, is because we're shifting from SSIS to TX. In SSIS, we created several REST connections, with the fields hardcoded. Editing and managing the fields manually is something we hoped TX could do for us;)

I'm missing one part, could you help me out? The input parameter mapping is working, but it ony fetching the query once, for the first result of the previous query. How can I make sure it iterates over all the results? I've already set my custom paratmeter to (SELECT locationId FROM REST.json).

Userlevel 5
Badge +5

Exactly, I think that was my initial issue as well with the input method.

It might be possible if you mix the If and Page method with your input.
https://legacysupport.timextender.com/hc/en-us/articles/360052383191-Creating-and-using-RSD-files-for-CData-providers#IfandPage

So something like this.

<api:set attr="BaseURI" value="https://blablapi.com/{locationId}" />
<api:set attr="URI" value="[BaseURI]?page=[_input.rows@next]" />

Are you saying that you didn't got it working? 

Is there a way that I can write output to the log? I need to iterate over the values in the locationId parameter, but when I set the custom data filter to locationId IN (SELECT ..), it no longer recognise the value. Is it even possible to pass an array as a parameter?

Badge

Hi Thomas, do you have an example of the complete RSD? As where does the _input.datein come from for example.

  <api:script method="GET"><api:check attr="_input.datein">      <api:set attr="URI" value="http://data.fixer.io/api/[_input.datein]?access_key=522b683569a91b66be6be214027b47bf"/>     </api:check>    <api:call op="jsonproviderGet">      <api:push/>    </api:call>  </api:script>

 

I have the same as Thye has. I have 3 REST API's (json):

  • GET /rest/v2/customers, output contains value of customer_id
  • GET /rest/v2/locations?customer_id=1, output contains value of location_id. No api is available to get all locations at once, can only be done with mandatory parameter customer_id
  • GET /rest/v2/devices?location_id=1, No api is available to get all devices at once, can only be done with mandatory parameter location_id

At the end I want to have all customers with all of their locations and devices of those locations. As a flat table or nested I don't care much. That's the next step for me.

P.S. De quality of the images on https://legacysupport.timextender.com/hc/en-us/articles/360052383191-Creating-and-using-RSD-files-for-CData-providers is too low to read unfortunately :(

This is my code right now with the gorest example api's, but still without any results.:

<api:script xmlns:api="http://apiscript.com/ns?v1" xmlns:xs="http://www.w3.org/2001/XMLSchema">	 <!-- See Column Definitions to specify column behavior and use XPaths to extract column values from JSON. -->	 <api:info title="JSONData" desc="Generated schema file." xmlns:other="http://apiscript.com/ns?v1">		<attr name="id" xs:type="integer" other:xPath="dummy" />		<attr name="title" xs:type="string" other:xPath="dummy" />	 </api:info>	 <api:set attr="UrlBase" value="https://gorest.co.in/public-api" />	 <api:set attr="customerin.DataModel" value="DOCUMENT" />	 <api:set attr="customerin.JSONPath" value="$." />	 <api:set attr="customerin.TemplateUri" value="[urlbase]/users"/>	 <api:set attr="customerin.ElementMapPath#" value="/json/data/id"/>	 <api:set attr="customerin.ElementMapName#" value="id"/>	 <api:set attr="trayin.Header:Name#" value="Accept"/>	 <api:set attr="trayin.Header:Value#" value="application/json"/>	 <api:set attr="trayin.DataModel" value="DOCUMENT"/>	 <api:set attr="trayin.JSONPath" value="$.data"/>	 <api:set attr="trayin.TemplateUri" value="[urlbase]//users/{customer_id}/posts"/>	 <api:set attr="trayin.ElementMapPath#" value="/json/data/title"/>	 <api:set attr="trayin.ElementMapName#" value="title"/>	<api:script method="GET">	 <api:set attr="customerin.URI" value="[customerin.TemplateUri]"/>		<api:call op="jsonproviderGet" in="customerin" out="customerout">			<api:set attr="trayin.URI" value="[trayin.TemplateUri | replace('{customer_id}',[customerout.id])]"/>			<api:call op="jsonproviderGet" in="trayin" out="trayout">				<api:set attr="out.id" value="[customerout.id]"/>				<api:set attr="out.title" value="[trayout.title | allownull()]"/>				<api:push item="out" />			</api:call>		</api:call>	</api:script></api:script>

Hi Thomas, I have followed your example for performing nested loops, and I'm having a bit of trouble getting the nested loop to work properly with the text substitution of an ID value.  If I hard code the ID, it works fine, but for some reason, the ID from the first loop is not being properly read by the nested loop.  Is there any way that an RSD script can output data to a log to review issues?  i feel like I'm flying blind without being able to see where data is being transformed.  I'm sure that there are a lot of people that are wrestling with this process, I've wasted three days trying every possible combination of variables and values and I really need to get this working correctly as I am working with ConcurSAP REST API services.

Userlevel 5
Badge +5

Hi Peter

Yes, you can set up logging.
https://legacysupport.timextender.com/hc/en-us/articles/360001029663-Add-a-CData-data-source#set-up-a-log-for-extra-info

When you have the log file it will show what call it is trying to make.

You need to be sure the replace function gives the correct id and that the call for these are successfully.

Hi Thomas, doing my best to get this looping script to work correctly, but I'm afraid that ti's still an issue despite calling the correct endpoints and using the correct data substitution for the result URI.  Is there an email address that I can show you how I'm doing this call and I will promise to keep it short and to the point.  My relative inexperience (only 2/3 weeks) with TimeXtender is showing.

Userlevel 5
Badge +5

Hi Peter
You can open a support ticket by emailing support@timextender.com

Reply