Overview Edit the file on GitHub
Table of Contents
- Authorization
- Schema
- Linked Resources
- Pagination
- Rate Limiting
- Conditional Requests
- HTTP Redirects
- Versioning
- Error Handling
- Sparse fieldsets
Authorization
To access any API v3 resource an access_token
is necessary. Get one using OAuth 2.0 Authorization.
Schema
All API access is over HTTPS, and accessed from the api.skroutz.gr
domain. All data is sent and received as JSON.
A list of all the example requests in this documentation as a Postman collection can be found here.
curl -XGET https://api.skroutz.gr/categories/999999999 \ -H 'Accept: application/vnd.skroutz+json; version=3.1' \ -H 'Authorization: Bearer your_access_token_here' HTTP/1.1 404 NOT FOUND Server: nginx Content-Type: application/json; charset=utf-8 Vary: Accept-Encoding Status: 200 OK X-UA-Compatible: IE=Edge,chrome=1 Cache-Control: max-age=0, private, must-revalidate X-Request-Id: 1475076950 X-Runtime: 0.011315 X-DNS-Prefetch-Control: off X-App: benjy Transfer-Encoding: chunked Date: Tue, 24 Sep 2013 10:49:50 GMT X-Varnish: 1475076950 Age: 0 Via: 1.1 varnish X-Origin: varnish2 X-Cache: MISS []
Blank fields are included as null
instead of being omitted.
All timestamps are returned in ISO 8601 format:
YYYY-MM-DDTHH:MM:SSZ
Linked Resources
When you see Linked resources: some_resource in any of our resources it means you may choose to include/embed it as follows:
Example
Resource Foo has "Linked resources: bar"
Case: embed
GET /foos/42?embed=bars
{
"foo": {
"id": 42,
"bars": [
{
"id": 1,
"baz": 42
}
]
}
}
Case: embed_ids
GET /foos/42?embed_ids=bars
{
"foo": {
"id": 42,
"bars": [1,2,3,4]
}
}
Case: include
GET /foos?include=bars
{
"foos": [
{
"id": 42,
"bars": [1,4]
},
{
"id": 43,
"bars": [3,4]
}
],
"bars": [
{
"id": 1,
"baz": 42
},
{
"id": 3,
"baz": 42
}
]
}
Pagination
Requests that return multiple items will be paginated to 25 items by
default. You can specify further pages with the page
parameter. You can also
set a custom page size to 10 with the per
parameter.
$ curl https://api.skroutz.gr/categories?page=2&per=10 \ -H 'Accept: application/vnd.skroutz+json; version=3.1' \ -H 'Authorization: Bearer your_access_token_here'
When there are other pages the response will contain the Link header.
Link
<https://api.skroutz.gr/categories?page=508&per=4>; rel="last",
<https://api.skroutz.gr/categories?page=3&per=4>; rel="next"
Note that page numbering is 1-based and that ommiting the page
parameter will return the first page.
Rate Limiting
You can make up to a certain amount of requests for each OAuth token associated with your application.
We currently allow up to 100 requests per minute.
You can check the returned HTTP headers of any API request to see your current rate limit status:
$ curl -i https://api.skroutz.gr/categories/1440 \ -H 'Accept: application/vnd.skroutz+json; version=3.1' \ -H 'Authorization: Bearer your_access_token_here' HTTP/1.1 200 OK Date: Mon, 01 Jul 2013 17:27:06 GMT Status: 200 OK X-RateLimit-Limit: 100 X-RateLimit-Remaining: 99 X-RateLimit-Reset: 1465285680
The headers tell you everything you need to know about your current rate limit status:
X-RateLimit-Limit
- The maximum number of requests that the consumer is permitted to make per minute.
X-RateLimit-Remaining
- The number of requests remaining in the current rate limit window.
X-RateLimit-Reset
- The time at which the current rate limit window resets in UTC epoch seconds.
If you need the time in a different format, any modern programming language can get the job done. For example, if you open up the console on your web browser, you can easily get the reset time as a JavaScript Date object.
new Date(1372700873 * 1000)
// => Mon Jul 01 2013 13:47:53 GMT-0400 (EDT)
Once you go over the rate limit you will receive an error response:
$ curl -i https://api.skroutz.gr/categories/1440 \ -H 'Accept: application/vnd.skroutz+json; version=3.1' \ -H 'Authorization: Bearer your_access_token_here' HTTP/1.1 403 Forbidden Date: Tue, 20 Aug 2013 14:50:41 GMT Status: 403 Forbidden X-RateLimit-Limit: 60 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1377013266 { "message": "API rate limit exceeded. See http://developer.skroutz.gr/api/v3/#rate-limiting for details." }
Daily limit
Besides the above limit, there is also a daily limit which at the time of this writting
it is set to 1000 calls.
If this limit is exceeded, all oauth2 tokens associated with that client will be expired and
the creation of new ones will be disabled until the beginning of the following day.
Conditional Requests
Most responses return ETag
headers. You can use the value of the ETag
header to make subsequent requests to those resources using the
If-None-Match
header.If the resource has not changed, the server will return a 304 Not Modified
.
Note
Making a conditional request and receiving a
304
HTTP response still counts against your Rate Limit. It only saves on bandwidth.
Case: Request without If-None-Match
header
$ curl -i https://api.skroutz.gr/categories/1440 \ -H 'Accept: application/vnd.skroutz+json; version=3.1' \ -H 'Authorization: Bearer your_access_token_here' HTTP/1.1 200 OK Cache-Control: private, max-age=60 ETag: "644b5b0155e6404a9cc4bd9d8b1ae730" Status: 200 OK Vary: Accept, Authorization, Cookie X-RateLimit-Limit: 100 X-RateLimit-Remaining: 99 X-RateLimit-Reset: 1372700873
Case: Request with If-None-Match
header
$ curl -i https://api.skroutz.gr/categories/1440 \ -H 'If-None-Match: "644b5b0155e6404a9cc4bd9d8b1ae730"' \ -H 'Accept: application/vnd.skroutz+json; version=3.1' \ -H 'Authorization: Bearer your_access_token_here' HTTP/1.1 304 Not Modified Cache-Control: private, max-age=60 ETag: "644b5b0155e6404a9cc4bd9d8b1ae730" Status: 304 Not Modified Vary: Accept, Authorization, Cookie X-RateLimit-Limit: 100 X-RateLimit-Remaining: 98 X-RateLimit-Reset: 1372700873
HTTP Redirects
API v3 uses HTTP redirection where appropriate. Clients should assume that any
request may result in a redirection. Receiving an HTTP redirection is not an
error and clients should follow that redirect. Redirect responses will have a
Location
header field which contains the URI of the resource to which the
client should repeat the request.
- 301
- Permanent redirection. The URI you used to make the request has been
superseded by the one specified in the
Location
header field. This and all future requests to this resource should be directed to the new URI. - 302, 307
- Temporary redirection. The request should be repeated verbatim to the URI
specified in the
Location
header field but clients should continue to use the original URI for future requests.
Other redirection status codes may be used in accordance with the HTTP 1.1 spec.
Versioning
The version
argument in the accept
header can include a minor version.
Below is how an example version (3.1.2) is broken down in our version scheme:
Major | Minor | Patch |
---|---|---|
3 | 1 | 2 |
Major versions are reserved for big architectural changes, minor versions are bumped
when incompatible changes are introduced and patch versions are added for backwards-compatible fixes.
Note
We do not follow semantic versioning.
Patch versions are implictly included and as such they should not be passed in the API (they will be silently ignored).
This means that by passing 3.1
in the API, we always get the latest bug fixes
and improvements found in the 3.1.X
series.
Example call using minor versions:
$ curl -i https://api.skroutz.gr/categories/1440 \ -H 'Accept: application/vnd.skroutz+json; version=3.1' \ -H 'Authorization: Bearer your_access_token_here'
In order to ensure backwards compatibility, we enforce the following invariants:
- When version is unspecified, return the latest API version
- When minor version is unspecified, return the oldest API version
- When minor version is specified
- Return the matched API version
- If no match is found, return the previous API version
Each row from the table tell us the version requested and the checkmark on the columns tell us the version returned.
API | v3.0.X | v3.1.X | v3.3.X |
---|---|---|---|
- | ✓ | ||
version=3 |
✓ | ||
version=3.0 |
✓ | ||
version=3.1 |
✓ | ||
version=3.2 |
✓ | ||
version=3.3 |
✓ | ||
version=3.4 |
✓ |
Error Handling
The way to check for errors is to look at the HTTP status code. If the code is in 4xx
or 5xx
range
you can look at the body to find more info.
Below is an example error. The format is kept the same across our API.
{
"errors": [
{
"code": "RecordNotFound",
"messages": [
"Couldn't find Sku with 'id'=452056"
]
}
]
}
Status Code: 400
Bad request. This error indicates that a required parameter is missing or incorrect.
Status Code: 401
Unauthorized. Either you didn't send send OAuth2 credentials, or the ones you sent were invalid.
Status Code: 404
Not Found. Resource does not exist.
Status Code: 422
Unprocessable Entity. This error indicates that the creation / update of a resource failed validation.
Status Code: 500
Internal Server Error. Something is broken and we are notified.
Status Code: 501
Not Implemented. The requested action is not implemented.
Sparse fieldsets
Sparse fieldsets are a way for clients to request specific json fields from the server response.
The response is reduced, saving bandwidth and CPU time on both ends. Everybody wins, so use them when you get the chance!
We follow the JSON API Sparse Fieldsets format, using root
as a special value to denote the main resource (top object) returned by the server.
Here is an example response from a product with an embedded shop:
GET https://api.skroutz.gr/products/25809770?embed=shop
View ResponseStatus: 200
{
"product": {
"id": 25809770,
"name": "ALCATEL One Touch 1016G Grey EU",
"sku_id": 10001441,
"shop_id": 1153,
"category_id": 40,
"availability": "Άμεση παραλαβή / Παράδοση 1 έως 3 ημέρες",
"click_url": "https://www.skroutz.gr/products/show/25809770?client_id=SbhE4wYENGn8ulFiBaXhDw%3D%3D&from=api",
"shop_uid": "4909",
"expenses": null,
"web_uri": "https://www.skroutz.gr/products/show/25809770",
"sizes": [
],
"price": 16.12,
"immediate_pickup": true,
"shop": {
"id": 1153,
"name": "Mobilephones",
"link": "http://www.mobile-phones.gr",
"phone": "2321062262",
"image_url": "https://c.scdn.gr/ds/shops/logos/1153/mid_20151119143428_88de70de.png",
"thumbshot_url": "https://b.scdn.gr/ds/shops/screenshots/1153/09762fb7-1bb7-4831-8606-c9922fb3fc74.png",
"reviews_count": 26,
"latest_reviews_count": 4,
"review_score": 5.0,
"payment_methods": {
"credit_card": false,
"paypal": false,
"bank": false,
"spot_cash": true,
"installments": ""
},
"shipping": {
"free": false,
"free_from": null,
"free_from_info": null,
"min_price": "5"
},
"web_uri": "https://www.skroutz.gr/m/1153/Mobilephones",
"extra_info": {
"time_on_platform": "3+ χρόνια",
"orders_per_week": "50+"
},
"top_positive_reasons": [
]
}
}
}
Let's say we only wanted id
& name
from the product.
We can use ?fields[root]=id,name
to get just those two fields (along with the association).
GET https://api.skroutz.gr/products/25809770?embed=shop&fields[root]=id,name
View ResponseStatus: 200
{
"product": {
"id": 25809770,
"name": "ALCATEL One Touch 1016G Grey EU",
"shop": {
"id": 1153,
"name": "Mobilephones",
"link": "http://www.mobile-phones.gr",
"phone": "2321062262",
"image_url": "https://c.scdn.gr/ds/shops/logos/1153/mid_20151119143428_88de70de.png",
"thumbshot_url": "https://b.scdn.gr/ds/shops/screenshots/1153/09762fb7-1bb7-4831-8606-c9922fb3fc74.png",
"reviews_count": 26,
"latest_reviews_count": 4,
"review_score": 5.0,
"payment_methods": {
"credit_card": false,
"paypal": false,
"bank": false,
"spot_cash": true,
"installments": ""
},
"shipping": {
"free": false,
"free_from": null,
"free_from_info": null,
"min_price": "5",
"shipping_cost_enabled": false
},
"web_uri": "https://www.skroutz.gr/m/1153/Mobilephones",
"extra_info": {
"time_on_platform": "3+ χρόνια",
"orders_per_week": "50+"
},
"top_positive_reasons": [
]
}
}
}
If we want to filter fields from the association, we can use the association name we used in the embed/include parameter (which is shop
in this example).
So in order to fetch the review_score
only from the shop
we can use the following parameters fields[root]=id,name&fields[shop]=review_score
.
GET https://api.skroutz.gr/products/25809770?embed=shop&fields[root]=id,name&fields[shop]=review_score
View ResponseStatus: 200
{
"product": {
"id": 25809770,
"name": "ALCATEL One Touch 1016G Grey EU",
"shop": {
"review_score": 5.0
}
}
}
Up until now, we only specified the fields we wanted, but we can go the opposite way as well and exclude fields instead.
Here's how we could fetch just the id
& name
from the shop
embedded resource, while excluding sizes
from products: fields_except[root]=sizes&fields[shop]=id,name
GET https://api.skroutz.gr/products/25809770?embed=shop&fields_except[root]=sizes&fields[shop]=id,name
View ResponseStatus: 200
{
"product": {
"id": 25809770,
"name": "ALCATEL One Touch 1016G Grey EU",
"sku_id": 10001441,
"shop_id": 1153,
"category_id": 40,
"availability": "Άμεση παραλαβή / Παράδοση 1 έως 3 ημέρες",
"click_url": "https://www.skroutz.gr/products/show/25809770?client_id=SbhE4wYENGn8ulFiBaXhDw%3D%3D&from=api",
"shop_uid": "4909",
"expenses": null,
"web_uri": "https://www.skroutz.gr/products/show/25809770",
"price": 16.12,
"immediate_pickup": true,
"shop": {
"id": 1153,
"name": "Mobilephones"
}
}
}
Note
Combining
fields
&fields_except
in the same resource (root or association) will exclude fields after the inclusion has been applied.