I using Instagram API to get user info
api = InstagramAPI(access_token=access_token)
profile = api.user(user_id="kallaucyahoocojp") # I try to put output data to profile variable here
And I get the below error:
DownloadError: Unable to fetch URL: https://api.instagram.com/v1/users/kallaucyahoocojp.json?access_token=(u'1191812153.f78cd79.d2d99595c79d4c23a7994d85ea0d412c', {u'username': u'kallaucyahoocojp', u'bio': u'\u30c4\u30a4\u30c3\u30bf\u30d5\u30a9\u30ed\u30ef\u30fc\u5897\u52a0\u30b5\u30fc\u30d3\u30b9', u'website': u'http://twitter\u30d5\u30a9\u30ed\u30ef\u30fc.jp', u'profile_picture': u'http://images.ak.instagram.com/profiles/anonymousUser.jpg', u'full_name': u'Kallauc', u'id': u'1191812153'})
Can anybody help me to fix it?
You need to pass the numeric-based user id, rather than the username. For example, instead of passing kallaucyahoocojp, you might pass 1234 if t
Here's how to get the ID if you don't have it:
Search for the instagram user id using this endpoint. In the python api:
api.user_search(q="kallaucyahoocojp", count=100)
Check the results for an exact string match on each user name while iterating through the results (calling .lower() to be sure to ignore potential case issues).
If you don't find the user in the first page of results, call to the next page using the max id returned.
Get the user id object from the returned from the matching users search result, then call your original function again with the numeric id.
A couple of very important notes:
Notice that I called the search function for users with a count of 100. You can pick any number, but contrary to other SO posts, the first user is not always the user you want in a search. The search can and will match partials, and not always according to an exact match first. How do I know? I have production instagram apps. I will qualify and say that usually the results are in the first 2-3 matches. Decide what is cheaper; repeated API calls that bring you closer to the limit, or 1 large bulk call where you are certain to get all the results.
The python Instagram API last I checked does a terrible job returning paging information. You actually get the paging URL which defeats the purpose of the python API itself to get additional pages. Your options are extract the next id parameter from the URL using urlparse or something similar, or fix the API to return the paging data as an object per the json (I've done both). What happens is the API itself is discarding part of the json and only giving you the URL which normally you don't want/need.
In your example, here's the search response:
{
"meta": {
"code": 200
},
"data": [
{
"username": "kallaucyahoocojp",
"bio": "ツイッタフォロワー増加サービス",
"website": "http://twitterフォロワー.jp",
"profile_picture": "http://images.ak.instagram.com/profiles/anonymousUser.jpg",
"full_name": "Kallauc",
"id": "1191812153"
}
]
}
Revising your call:
api = InstagramAPI(access_token=access_token)
profile = api.user(user_id="1191812153")
I should note that you may not need to call the user call if you did a search because you may simply have all the info you need. It will depend on what you are doing of course, so I am giving you the general method to use the rest of the user api.
For extracting profile info using Instagram API, userid is required.
The endpoint for extracting userID:
https://api.instagram.com/v1/users/search?q=[username]&access_token=[HERE]
The endpoint for extracting profile info:
https://api.instagram.com/v1/users/[userid]/?access_token=[HERE]
Note that before extracting information, check the login permissions for your access token.
Related
I'm building a Zapier app for a platform that have dynamic fields. I have an API that returns the list of fields for one of my resource (for example) :
[
{ name: "First Name", key: "first_name", type: "String" },
{ name: "Civility", key: "civility", type: "Multiple" }
]
I build my action's inputFields based on this API :
create: {
[...],
operation: {
inputFields: [
fetchFields()
],
[...]
},
}
The API returns type that are list of values (i.e : Civility), but to get these values I have to make another API call.
For now, what I have done is in my fetchFields function, each time I encounter a type: "Multiple", I do another API call to get the possible values and set it as choices in my input field. However this is expensive and the page on Zapier takes too much time to display the fields.
I tried to use the z.dehydrate feature provided by Zapier but it doesn't work for input choices.
I can't use a dynamic dropdown here as I can't pass the key of the field possible value I'm looking for. For example, to get back the possible values for Civility, I'll need to pass the civility key to my API.
What are the options in this case?
David here, from the Zapier Platform team.
Thanks for writing in! I think what you're doing is possible, but I'm also not 100% that I understand what you're asking.
You can have multiple API calls in the function (which it sounds like you are). In the end, the function should return an array of Field objects (as descried here).
The key thing you might not be aware of is that subsequent steps have access to a partially-filled bundle.inputData, so you can have a first function that gets field options and allows a user to select something, then a second function that runs and pulls in fields based on that choice.
Otherwise, I think a function that does 2 api calls (one to fetch the field types and one to turn them into Zapier field objects) is the best bet.
If this didn't answer your question, feel free to email partners#zapier.com or join the slack org (linked at the bottom of the readme) and we'll try to solve it there.
According to API documentation here https://backendless.com/documentation/data/rest/data_search_and_query.htm , backendless shall provide paging info in response body like this
{
"nextPage":null,
"data":[
{
"updated":null,
"created":"02/05/2014 18:13:40 GMT+0000",
"ownerId":null,
"objectId":"6FAF3CE5-6F55-1B32-FF83-D333252D0300",
"name":"Bob",
"age":20
},
{
"updated":null,
"created":"02/04/2014 19:40:10 GMT+0000",
"ownerId":null,
"objectId":"28325E9F-2DED-D3CA-FFC6-C76911AFBB00",
"name":"Frank",
"age":26
}],
"offset":0,
"totalObjects":2
}
However, when I send request to get data from table like this:
https://api.backendless.com/<version>/data/<table-name>
it returns only collection of objects (which should be in "data") and now paging info.
Adding page requests:
https://api.backendless.com/<version>/data/<table-name>?pageSize=10&offset=10
returns correct data, but still without paging info.
What I'm doing wrong? How can I access paging info?
The docs link you mention is for Backendless version which is being deprecated (there's a warning on the top of the page). Here is a link to the docs for the current version: https://backendless.com/docs/rest/doc.html#data_basic_search
Indeed, in version 4 we got rid of that additional information in the response to simplify the response object in non-REST clients. But still you can easily determine current params since you're specifying them in the request (or they're zeros in case you're not).
I'm using GMail Api and I would like to query users messages if they have a message with header
In-Reply-To: <specificMessageID#service.com>
I haven't been able to figure out how to do this.
I guess method should be messages.list but there are no query like: rfc822msginreplyto:
If there is no such possibility do you think, it is good practice to fetch last 100 users emails and check it manually?
You could list messages with q = rfc822msgid:msgid#example.com and then get the thread of that message to see what the replies are.
Message.list returns a list of Users.messages
Message.list does have a q method.
q string Only return messages matching the specified query. Supports
the same query format as the Gmail search box. For example,
"from:someuser#example.com rfc822msgid: is:unread". Parameter cannot
be used when accessing the api using the gmail.metadata scope
So you can test it by searching in gmail itself if you can get it to work there it should work VIA the api.
In-Reply-To: <XXX#gmail.com>
I tested that and it appears to work.
I am not sure which client library you are using but most of them have an optional parameters option when creating the request that will allow you to add the q parameter.
Update:
Test your query from Gmail Search
The request you send must be accurate you must not add spaces on the end or remove the space after :
In-Reply-To: <dddi#gmail.com>
Example:
https://www.googleapis.com/gmail/v1/users/me/messages?access_token=XXXX&q=In-Reply-To:%20%3Cdddi#gmail.com%3E
Response
{
"messages": [
{
"id": "152377f1efe8d069",
"threadId": "152376d14b187e44"
}
],
"resultSizeEstimate": 1
}
Using try me at the bottom on of the page.
I am using the Gmail API in Google Apps Script (which is basically Javascript), and I need to make as few calls to the API as possible, for efficiency and speed.
I'm using Users.messages: list to list the messages in a user's mailbox, and the response includes an array called messages, and for each message it includes an id and a threadId, like so:
"messages": [
{
"id": "152b93b1111c33e2",
"threadId": "152b922266c33e2"
},
{
"id": "152b93338c98cb3",
"threadId": "152b922266c33e2"
} ...
But I need the response to include more information about each message, so that I don't have to make a separate Users.messages:get call for each message.
The APIs Explorer on the Users.messages: list page says you can use the fields parameter to "specify which fields to include in a partial response."
When I click "Use fields editor" to select the three items I need, it fills the following in to the field:
messages(id,internalDate,payload)
Then when I execute the command, it shows that the GET command should look like this:
https://www.googleapis.com/gmail/v1/users/test#test.com/messages?fields=messages(id%2CinternalDate%2Cpayload)&key={YOUR_API_KEY}
However, the messages array in the results does not include the internalDate or the payload fields. It just includes the message id only, like so:
"messages": [
{
"id": "152b93b1111c33e2"
},
{
"id": "152b93338c98cb3"
} ...
It also does not include the threadId anymore, but it DOES continue to include the threadId if I select that as one of the fields, like so:
messages(id,threadId)
and the URL looks like this...
https://www.googleapis.com/gmail/v1/users/test#test.com/messages?fields=messages(id%2CthreadId)&key={YOUR_API_KEY}
And the result looks exactly like the first result above, where we weren't using the fields parameter.
So I know the fields parameter is actually doing something.
Thinking this might just be a limitation of the APIs Explorer, I tried making the API call in Google Apps script, but it still does not include the fields I need.
You are almost there.
When listing messages, theid and threadId of each message is all you get. You then have to get each message separately.
If you e.g. just want the internalDate of the message, it is in this request it should be specified in the fields parameter.
Request
GET https://www.googleapis.com/gmail/v1/users/me/messages/152b792a91c9c391?fields=internalDate&key={YOUR_API_KEY}
Response
{
"internalDate": "1454778787000"
}
Suppose my model is:
User:
id
nickname
I have a collection /users/
I want the Users to be retrieved by /users/{id} and not /users/${nickname}, because in some more complex cases, there could be no "logical unique constraint".
So the basic JSON payload I could use is for exemple:
{
id: 123,
nickname: 'someUserName'
}
Nothing fancy here.
POST on /users/
As far as I know, an user as an identifier. It is part of the resource representation, so it should be in the payload (?).
Put what if I want to generate the ID myself on the backend, using a DB sequence for exemple?
Then my payload becomes:
{
nickname: 'someUserName'
}
Is this appropriate?
What is supposed to be the output of this POST? Nothing? Just a header referencing the resource location, including the ID?
GET on /users/id
When we get the resource, we load its content as JSON:
{
id: 123,
nickname: 'someUserName'
}
PUT on /users/id
As far as I know, the payload used on this method is supposed to "override" the resource content. If we wanted partial updates, we would have used PATCH.
But what if I do:
PUT /users/123
{
id: 456,
nickname: 'someUserName'
}
Does this mean that we want to update the id of a resource?
Isn't it kind of redundant to use the id in both the URI and the payload?
Actually I don't really know how to handle the id.
I don't know if I am supposed to use the same resource representation in all POST / PUT / DELETE operations.
I don't know if the id should be part of the unique(?) resource representation.
But if the id is not part of the representation, then when I list the users, using GET /users/, if the ids are not returned, then I don't know how the client can get the user ids...
Can someone help me? :)
First of all
It is not REST if you don't use HATEOAS
I hope you understand this, I'll come back to that at the very end.
POST on /users/
It perfectly ok to not use an ID in the POST payload. If an ID is present react with an error message, so developers understand they are doing wrong.
Therefore only the nickname as a payload is perfectly valid if you don't have anything else in your user resource
The output of your server should include three important things:
HEADER: A status code indicating success or failure (usually 201 Created)
HEADER: The location of the newly created resource (just Location: /path/to/resource)
BODY: A representation of the created resource. Give back a complete payload like on a GET!
GET
perfectly valid
PUT
your analysis regarding PUT/PATCH matchs the spec, the new resource should be identical to the payload meaning the user wishes to change the id if it differs. if a payload contains values which shouldn't be changed (like the ID) you have two possibilities:
Ignore the ID in the payload
Return an error
In both cases inform the user about what you did and what went wrong. I prefer to send/get a 400 Bad Request. If a privileged user could change the ID but the particular user can't an 403 Forbidden may be more appropriate.
Also make sure to document your APIs behaviour. You may allow the ID to be omitted in your API. Don't forget to treat IDs given in a POST payload in a consistent way!
Overall questions
REST operates over Resources.
/users/ is an example for an collection of resources
/users/{id} is an example for a single resource
You should always use the exact same representation in each and every response. If for some reason it is more appropriate to give only a snippet of the information add metadata (link) pointing to the full resource representation.
The ID is always present except in the first POST request of an user.
POST implies that the future location of the resource is not known and has to be provided by the server.
This also means that GET /users/ should return the IDs for each resource.
As always in APIs return strict and be forgiving in requests. document your behaviour so users can learn.
HATEOAS
The true beauty of REST comes to daylight if you implement HATEOAS (Hypermedia As The Engine Of Application State). Part of this means that you should sugar your representations with useful tag/link combinations. This way clients never have to construct an url anymore.
An Example using HAL for your user representation would be:
{
"_links:" {
"self": { "href": "http://yourrest/users/123" }
},
"id": "123"
"nickname": "someUserName"
}
A nice wrapup of using HAL was written by Matthew Weier O'Phinney in his blog when he developed a ZF2 REST Module (first entry is completly zf free, only explaining HAL).
I'm interpreting your descriptions as saying that the id is not part of the resource, it's a unique identifier of the resource. In that case, it should not be part of the payload for any operation.
POST /users with payload {"nickname": "somebody"} would create a new resource with a URL returned in the Location header. That URL would presumably look like /users/123 but from the client's point of view there's no reason to expect that. It could look like /something/else/entirely.
GET /users/123 would (assuming that URL was returned by an earlier POST) return the payload {"nickname": "somebody"}.
PUT /users/123 would (with the same assumption as above) replace the resource with the payload you send with the PUT, say {"nickname": "somebody else"}.
If you want the client to be able to name a resource, then you'd also let PUT /users/123 create a new resource with that URL.
I know of no common RESTful way to rename a resource. I suppose a POST with the old URL as part of the query part or the body would make sense.
Now, suppose I'm wrong and you do want id to be part of the resource itself. Then every payload would include it. But from the client's point of view, there should be no assumption that "id": 123 implies that the URL would be /users/123.
Finally, all of this is from a fairly purist point of view. There is value to thinking of URLs as the only real identifier of a resource, but it's not awful to break that rule and have the client use logic to create the URLs.