Listing devices for an application using Resin REST API

Hi,

when I try using the API to detail an application, it works :

curl -i -X GET    
-H "Authorization:Bearer eyJ(...)bIg"    
-H "Content-Type:application/json"  
'https://api.resin.io/v1/application(520176)'

I’m getting a HTTP 200 answer with a body corresponding to my request.

But when I try to list the devices related to this application, I can get only “internal server error (HTTP 500)” or “bad request (HTTP 400)” depending on my syntax :

curl -i -X GET    
-H "Authorization:Bearer eyJ(...)bIg"    
-H "Content-Type:application/json"  
'https://api.resin.io/v1/application(520176)?\$expand=device'

After a few tries, I notice the curl request generated by my chrome extension (Restlet client) is generating single quotes around the endpoint URL which was causing the problem.

After getting a valid answer, it’s not listing any informations about the devices :

{
  "d": [
    {
      "id": 520176,
      "user": {
        "__deferred": {
          "uri": "/resin/user(18630)"
        },
        "__id": 18630
      },
      "application": null,
      "actor": 1564413,
      "app_name": "FleetManagement",
      "git_repository": "tristan_robet/fleetmanagement",
      "commit": "0ce78cbc9483811171047785d93d8a9f10df6b73",
      "device_type": "raspberrypi3",
      "version": 1,
      "should_track_latest_release": true,
      "support_expiry_date": null,
      "__metadata": {
        "uri": "/resin/application(520176)",
        "type": ""
      }
    }
  ]
}

By the way, is there a plan to normalize your API to respect RESTful API good practices ?

For example :

https://api.resin.io/v1/application(520176)?$expand=device

would become :

https://api.resin.io/v1/applications/520176/devices

and

https://api.resin.io/v1/device?$filter=name%20eq%20’[name]’

would become

https://api.resin.io/v1/devices?name=[name]

The structure of your API would be much more visible, easy to discover and memorize, and there would be less problem related to unusual url caracters.

Hey, could it be that stray backslash before the $expand?
I do get expanded device data (this app doesn’t have any devices though):

curl -i -X GET \
  -H "Authorization:Bearer $RESIN_API_TOKEN" \
  -H "Content-Type:application/json" \
  'https://api.resin.io/v1/application(307298)?$expand=device'
{
  "d": [{
    "device": [],
    "id": 307298,
    "user": {
      ...
  }]
}

By the way, is there a plan to normalize your API to respect RESTful API good practices ?

The API v1 is based on the Open Data (OData) format, and adheres to the OData URL conventions laid out in it’s specification. The API v2 will be different, but I don’t know the details there.

Thanks for your answer, but I have exactly the same response with no “\”, I’m supposed to see 2 devices. The “\” was taken from your curl example in the api doc.

Oasis, the guys behind SOAP specs are messing up with REST now ? If they want to document and officialize some conventions, why not, but they should just use the good practices already in place, not invent new ones. They are defining some kind of URL SQL when most requests are much simpler.

Hi @Tristan107, do you mean this in the API docs? https://docs.resin.io/runtime/data-api/#get-all-devices-by-application

I just tried copy pasted that and get back my devices for a given application just fine, so our docs are not at fault here, IMHO:

APP_ID=....
AUTH_TOKEN=....

curl "https://api.resin.io/v1/application(${APP_ID})?\$expand=device"  \
  -H "Content-Type: application/json"  \
  -H "Authorization: Bearer ${AUTH_TOKEN}" | jq .

The original query works as intended as well, just as you mentioned, you get the information of the application. The devices connected to the application are a larger scope - since a device does not tied to an app, it can be moved, it’s natural that it’s not hard-linked to an application, but need to expand on the query to get them.

So all is in our API docs. We should have more info on what each query returns exactly, though to clearly define what to expect.

Hi, sorry I don’t get it what your mean.

What I understand is when you pass the request, in the reponse, you see the devices for a given application. It’s really cool for you, all I want is to have the same kind of reponse, but when I do pass the same request for my application, I don’t see the 2 devices as u can see in the response I’ve copy pasted up there.

So you mean that, if you use the above script exactly, filling in your APP_ID and AUTH_TOKEN, you don’t see any of the devices?

Yes, you can see all this, request and response in my first post.

Sorry, my I wager, that you did not try as mentioned above, the exact same request, as mentioned.

In your original post, indeed, the single quotes were a problem, as you mentioned, because that will change e.g. how the $ sign will be expanded. I’ve tried that and failed, while switching that to double quotes, it works. Just as it works in the exact script mentioned above.

So could you please try that again, or tell us exactly what you are trying at the moment?
If still doesn’t work, might request an API token from you temporarily to check out your very exact call you make, because it would facilitate things a lot if we are sure that we are talking about the same requests.

Sure, take my token, how could I send it to you ?

The double quote/single quote may be confusing because I copied my first wrong request, but I’ve tried every possibilities and you can get only a HTTP 400 or 500 with a bad request, not a HTTP 200 with an incomplete repsonse, right ?

If it’s useful : I’m using git bash on windows with curl and chrome restlet extension.

Here is how it looks when URL encoded in my tool, %5C is for “\” and %24 is for “$”, I’v tried with various number of “\” too, but with no success (starting from one “\” I get a HTTP 200 but with no details on devices) :

When trying with “ARC” chrome extension (advanced rest client), I have the correct full response with devices when I send a non encoded URL(…/application(520176)?$expand=device), but if I press “Encode URL”, the “$” becomes a %24 and your server returns a HTTP 500 internal server error. Is it a correct behavior to refuse encoded URL ?

I think I found the main difference, and it validates our requests to try the format that we’ve shared above (that you did not mention explicitly that you have tried).

The issue is that $ should not be URL-encoded, but sent as it is. Then it works. In Restlet I’ve unchecked the “encode before sending” option and as you see below in the lower right, the device in my test application is listed properly:

(tried the same thing with Python/requests as well, same thing, had to make sure that the query string’s $ values are not URL encoded. The \$ in the curl example meant to keep $ as it is, a single $). Hope this helps to debug your use cas as well.

As for refusing URL encoded variations, I think that is intended by OData as the two forms mean different things in their decoding from the OData perspective, see for example in the OData docs, how the example URLs listed for $filter are escaped: http://www.odata.org/documentation/odata-version-2-0/uri-conventions/#FilterSystemQueryOption

Yes, I figured it out the problem was about the “$” encoding, but thanks for finding the hidden setting in Restlet :slight_smile:

What was really confusing is this request :
https://api.resin.io/v1/application?$filter=app_name%20eq%20’FleetManagement’

Was working well in Restlet without any special setting. But I guess the tool was detecting some parts of the URL was already encoded and was auto-disabling the “Encode before sending” feature.

Thanks again.

Hey @Tristan107 looking at the Restlet settings, it was saying something like if you fill in the URL bar, they don’t do encoding, if you do query parameters it is automatically encoded. Not sure if that part is correct in their docs, as I’ve seen some strange behaviour, but “do or do not encode” is a tricky thing and even trickier if the software is not explicit about it. https://restlet.com/documentation/client/user-guide/perform-requests/build-request#toc_12

Glad it works now, and thanks for bearing with us!