How to properly iterate through paginated results in Clockify? - clockify

The clockify API is unclear (to me) about how to iterate through results.
For example, https://clockify.github.io/clockify_api_docs/#operation--workspaces--workspaceId--timeEntries--get says
Each request is limited to 10 time entries. To get the other 10 (and the next 10 and so on), you'll have to include the page parameter and increment it with each request (eg. https://api.clockify.me/api/workspaces/{workspaceId}/timeEntries/?page=1)
Data returned from this endpoint is merely an array of timeEntries (bonus for being simple!). Reading beyond the last page returns an empty array (status=200).
So, the question is: Does clockify intend that clients read until an empty array, or am I missing something?

This is the existing behaviour I am afraid.
Hopefully, there will be "CurrentPage", "PageLength", "TotalPages" or at least "TotalRecords" in the RESPONSE body someday.
EDIT:
According to the support response their developers are working on adding TotalRecords node to let us know how many items we can expect.

Related

How to list all parameters available to query via API?

As a end-point user of an API, how can I list all parameters available to pass the query? In my case (stats about Age of Empires 2 matches), the website describing the API has a list with some of them but it seems there are more available.
To provide more context, I'm extracting the following information:
GET("https://aoe2.net/api/matches?game=aoe2de&count=1000&since=1632744000&map_type=12")
but for some reason the last condition, map_type=12 does nothing (output is the same as without it). I'm after the list of parameters available, so I can extract what I want.
PD: this post is closely related but does not focus on API. Perhaps this makes a difference, as the second answer there seems to suggest.
It is not possible to find out all available (undocumented) query parameters for a query, unless the API explicitly provides such a method or you can find out how the API server processes the query.
For instance, if the API server code is open source, you could find out from the code how the query is processed. Provided that you find the code also.
The answers in the post you linked are similarly valid for an API site as well as for one that provides content for a web browser (a web server can be both).
Under the hood, there is not necessarily any difference between an API server or a server that provides web content (html) in terms of how queries are handled.
As for the parameters seemingly without an effect, it seems that the API in question does not validate the query parameters, i.e., you can put arbitrary parameters in the query and the server will simply ignore parameters that it is not specifically programmed to use.
The documentation on their website is all any of us have to go by https://aoe2.net/#api
You can't just add your own parameters to the URL and expect it to return a value back as they have to have coded it to work that way.
Your best bet is to just extract as much data as you can by increasing the count parameter, then loop through the JSON response and extract the map_type from there.
JavaScript example:
<script>
json=[{"match_id":"1953364","lobby_id":null,"game_type":0},
{"match_id":"1961217","lobby_id":null,"game_type":0},
{"match_id":"1962068","lobby_id":null,"game_type":1},
{"match_id":"1962821","lobby_id":null,"game_type":0},
{"match_id":"1963814","lobby_id":null,"game_type":0},
{"match_id":"1963807","lobby_id":null,"game_type":0},
{"match_id":"1963908","lobby_id":null,"game_type":0},
{"match_id":"1963716","lobby_id":null,"game_type":0},
{"match_id":"1964491","lobby_id":null,"game_type":0},
{"match_id":"1964535","lobby_id":null,"game_type":12},];
for(var i = 0; i < json.length; i++) {
var obj = json[i];
if(obj.game_type==12){
//do something with game_type 12 json object
console.log(obj);
}
}
</script>

Google Calendar - SyncToken is missing in API response

I don't see nextSyncToken in the response. I followed the doc(https://developers.google.com/calendar/api/guides/sync) and paginated using nextPageToken but I couldn't see the nextSyncToken on the last page.
API Used: GET /calendars/primary/events?maxResults=10&singleEvents=true&pageToken=********
I don't know whether if I miss anything here. Could anyone help me with this?
I have seen from the response link on the other answer comment that you are using orderBy on the request.
This is why the nextSyncToken is not showing up.
As mentioned on the documentation on Events: list -> Parameters -> syncToken:
Token obtained from the nextSyncToken field returned on the last page of results from the previous list request. It makes the result of this list request contain only entries that have changed since then. All events deleted since the previous list request will always be in the result set and it is not allowed to set showDeleted to False.
There are several query parameters that cannot be specified together with nextSyncToken to ensure consistency of the client state.
These are:
iCalUID
orderBy
privateExtendedProperty
q
sharedExtendedProperty
timeMin
timeMax
updatedMin
If the syncToken expires, the server will respond with a 410 GONE response code and the client should clear its storage and perform a full synchronization without any syncToken.
Learn more about incremental synchronization.
Optional. The default is to return all entries.
You should remove the orderBy from the request to get the syncToken
Could you please provide the response from gcalendar API? It's hard to say more without detail information. I event don't know which language are you using.
Try to use a vendor library to sort that out:
a) https://packagist.org/packages/google/apiclient (for PHP)
b) https://www.npmjs.com/package/google-calendar (for JavaScript)
and/or
Try to use alternative endpoint: GET https://www.googleapis.com/calendar/v3/calendars/calendarId/events.

Microsoft Graph API delta query for channelMessages never returns a deltaLink

I'm trying to use delta query to get teams channel messages updates according this documentation: HERE
This is the request url:
https://graph.microsoft.com/beta/teams/<teamId>/channels/<channelId>/messages/delta
However, calling the returned nextLinks one after another never returns a deltaLink. There're too many pages of results and it causes my app to be throttled before ever getting a deltaLink from it.
In other delta query endpoints, $top is supported to limit the number of results returned. Usually I'm able to get a deltaLink after calling the nextLinks once or twice. But $top doesn't seem to have an effect in the channel messages endpoint.
So I tried appending another queryString ?odata.maxpagesize=10 to the request instead, and it seemed to work a week ago. I was able to get the deltaLink after 2 pages. But it looks like Microsoft might have changed the API and this workaround no longer works.
I also tried adding Prefer: odata.maxpagesize=10 in my request header according to this documentation: HERE
But the nextLink this generates is too long and it gives me this error instead:
HTTP Error 414. The request URL is too long.
Has anyone been able to use this delta for channel messages? Or have I done something wrong?

Proper REST response for empty table?

Let's say you want to get list of users by calling GET to api/users, but currently the table was truncated so there are no users. What is the proper response for this scenario: 404 or 204?
I'd say, neither.
Why not 404 (Not Found) ?
The 404 status code should be reserved for situations, in which a resource is not found. In this case, your resource is a collection of users. This collection exists but it's currently empty. Personally, I'd be very confused as an author of a client for your application if I got a 200 one day and a 404 the next day just because someone happened to remove a couple of users. What am I supposed to do? Is my URL wrong? Did someone change the API and neglect to leave a redirection.
Why not 204 (No Content) ?
Here's an excerpt from the description of the 204 status code by w3c
The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation.
While this may seem reasonable in this case, I think it would also confuse clients. A 204 is supposed to indicate that some operation was executed successfully and no data needs to be returned. This is perfect as a response to a DELETE request or perhaps firing some script that does not need to return data. In case of api/users, you usually expect to receive a representation of your collection of users. Sending a response body one time and not sending it the other time is inconsistent and potentially misleading.
Why I'd use a 200 (OK)
For reasons mentioned above (consistency), I would return a representation of an empty collection. Let's assume you're using XML. A normal response body for a non-empty collection of users could look like this:
<users>
<user>
<id>1</id>
<name>Tom</name>
</user>
<user>
<id>2</id>
<name>IMB</name>
</user>
</users>
and if the list is empty, you could just respond with something like this (while still using a 200):
<users/>
Either way, a client receives a response body that follows a certain, well-known format. There's no unnecessary confusion and status code checking. Also, no status code definition is violated. Everybody's happy.
You can do the same with JSON or HTML or whatever format you're using.
I'd answer one of two codes depending on runtime situation:
404 (Not Found)
This answer is pretty correct if you have no table. Not just empty table but NO USER TABLE. It confirms exact idea - no resource. Further options are to provide more details WHY your table is absent, there is couple of more detailed codes but 404 is pretty good to refer to situation where you really have no table.
200 (OK)
All cases where you have table but it is empty or your request processor filtered out all results. This means 'your request is correct, everything is OK but you do not match any data just because either we have no data or we have no data which matches your request. This should be different from security denial answer. I also vote to return 200 in situation where you have some data and in general you are allowed to access table but have no access to all data which match your request (data was filtered out because of object level security but in general you are allowed to request).
If you are expecting list of user object, the best solution is returning an empty list ([]) with 200 OK than using a 404 or a 204 response.
definitely returns 200.
404 means resource not found. But the resource exists. And also, if the response has 404 status. How can you know users list empty or filled?
'/users' if is empty should return '200'.
'/users/1' if the id is not found. should return 404.
It must 200 OK with empty list.
Why: Empty table means the table exists but does not have any records.
404 Not Found means requested end point does not exist.

ASP.NET MVC 2 EditModel include Id? Securing Id is not tampered with

I am looking for some best practices when is comes to creating EditMoels and updating data in an ASP.NET MVC app. Lets say I have a Url like so /Post/Edit?Id=25
I am ensuring the user has permissions to edit the specific post by Id on the Get request and the same for my Post in the controller. I am using the ValidateAntiForgeryToken.
Questions: Should I include the Id property in my EditModel? If so, Should I encrypt it?
The problem is I can use FireBug to edit the Id hiddedinput and edit a different post as long as I have permission to do so. This is not horrible, but seems wrong.
Any help would be great!
There are several ways to prevent this.
The first - don't send sensitive data to the client at all. Keep the post id in session variables, so the user can never edit it. This may or may not be an option depending on your architecture.
The next approach is to convert the direct reference to an indirect one. For example, instead of sending postids = {23452, 57232, 91031} to the client to render a drop-down list, you should send an opaque list {1,2,3}. The server alone knows that 1 means 23452, 2 means 57232 and so on. This way, the user can't modify any parameter you don't want him to.
The last approach is including some kind of hash value that adds as an integrity check. For example, suppose you have 3 hidden fields in a html page - {userId=13223, postId=923, role=author}. You first sort the field names and then concatenate the values to get a string like postId=923&userId=13223&role=author. Then, append a server secret to this string, and hash (SHA-1 or MD5) the entire string. For eg. SHA-1('postId=923&userId=13223&role=author&MySuperSecretKey'). Finally add this hashed value as a hidden parameter. You may also want to add another hidden field called ProtectedParameters=userId,postId,role.
When the next request is made, redo the entire process. If the hash differs, balk the process.
Security wise, I have listed the options in decreasing order. At the same time, its probably in the increasing order of convenience. You have to pick the right mix for your application.
I don't think you should worry with that, if the user does what you said, i suppose that you'll know who edited what, so if he edits the wrong post, doing as you said, you can always remove his edition rights...
If you can't thrist your users, don't let them edit anything...

Resources