Permalink
Fetching contributors…
Cannot retrieve contributors at this time
395 lines (291 sloc) 12.5 KB
---
parent: apiv3
title: overview
---
# Overview <%= edit_link %>
<%= partial 'partials/toc' %>
## Authorization
To access any API v3 resource an `access_token` is necessary. Get one using <%= link_to 'OAuth 2.0 Authorization', '/authorization' %>.
## Schema
All API access is over HTTPS, and accessed from the `<%= settings.api_domain %>`
domain. All data is sent and received as JSON.
A list of all the example requests in this documentation as a [Postman](http://www.getpostman.com/)
collection can be found <%= link_to 'here', "/assets/misc/#{flavor}_postman_collection.json" %>.
<pre class="terminal">
curl -XGET https://<%= settings.api_domain %>/categories/999999999 \
-H 'Accept: application/vnd.<%= settings.site_name %>+json; version=<%= t("version.v3") %>' \
-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
[]
</pre>
Blank fields are included as `null` instead of being omitted.
All timestamps are returned in [ISO 8601](http://en.wikipedia.org/wiki/ISO_8601) format:
YYYY-MM-DDTHH:MM:SSZ
## Linked Resources
When you see <mark>Linked resources: some_resource</mark> 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
<pre class="terminal">
<code>GET /foos/42?embed=bars</code>
</pre>
<%= render_code '{
"foo": {
"id": 42,
"bars": [
{
"id": 1,
"baz": 42
}
]
}
}', 'javascript' %>
###### Case: embed_ids
<pre class="terminal">
<code>GET /foos/42?embed_ids=bars</code>
</pre>
<%= render_code '{
"foo": {
"id": 42,
"bars": [1,2,3,4]
}
}', 'javascript' %>
###### Case: include
<pre class="terminal">
<code>GET /foos?include=bars</code>
</pre>
<%= render_code '{
"foos": [
{
"id": 42,
"bars": [1,4]
},
{
"id": 43,
"bars": [3,4]
}
],
"bars": [
{
"id": 1,
"baz": 42
},
{
"id": 3,
"baz": 42
}
]
}', 'javascript' %>
## 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.
<pre class="terminal">
$ curl https://<%= settings.api_domain %>/categories?page=2&per=10 \
-H 'Accept: application/vnd.<%= settings.site_name %>+json; version=<%= t("version.v3") %>' \
-H 'Authorization: Bearer your_access_token_here'
</pre>
When there are other pages the response will contain the [Link](http://tools.ietf.org/html/rfc5988) header.
~~~
Link
<https://<%= settings.api_domain %>/categories?page=508&per=4>; rel="last",
<https://<%= settings.api_domain %>/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:
<pre class="terminal">
$ curl -i https://<%= settings.api_domain %>/categories/1440 \
-H 'Accept: application/vnd.<%= settings.site_name %>+json; version=<%= t("version.v3") %>' \
-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
</pre>
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](http://en.wikipedia.org/wiki/Unix_time).
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.
~~~ javascript
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:
<pre class="terminal">
$ curl -i https://<%= settings.api_domain %>/categories/1440 \
-H 'Accept: application/vnd.<%= settings.site_name %>+json; version=<%= t("version.v3") %>' \
-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.<%= settings.domain %>/api/v3/#rate-limiting for details."
}
</pre>
### Daily limit
Besides the above limit, there is also a daily limit which at the time of this writting
it is set to **<%= t('docs.apiv3.daily_limit') %>** 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](#rate-limiting). It only saves on bandwidth.
###### Case: Request without `If-None-Match` header
<pre class="terminal">
$ curl -i https://<%= settings.api_domain %>/categories/1440 \
-H 'Accept: application/vnd.<%= settings.site_name %>+json; version=<%= t("version.v3") %>' \
-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
</pre>
###### Case: Request with `If-None-Match` header
<pre class="terminal">
$ curl -i https://<%= settings.api_domain %>/categories/1440 \
-H 'If-None-Match: "644b5b0155e6404a9cc4bd9d8b1ae730"' \
-H 'Accept: application/vnd.<%= settings.site_name %>+json; version=<%= t("version.v3") %>' \
-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
</pre>
## 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](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3).
## 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](http://semver.org/).
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:
<pre class="terminal">
$ curl -i https://<%= settings.api_domain %>/categories/1440 \
-H 'Accept: application/vnd.<%= settings.site_name %>+json; version=3.1' \
-H 'Authorization: Bearer your_access_token_here'
</pre>
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.
<%= render_code '{
"errors": [
{
"code": "RecordNotFound",
"messages": [
"Couldn\'t find Sku with \'id\'=452056"
]
}
]
}', 'javascript' %>
##### 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](http://jsonapi.org/format/#fetching-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:
<%= render_recording :fieldsets_product_with_shop %>
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).
<%= render_recording :fieldsets_product_with_shop_and_root_fields %>
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`.
<%= render_recording :fieldsets_product_with_shop_and_association_fields %>
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`
<%= render_recording :fieldsets_product_with_shop_and_exclude_fields %>
> ##### Note
> Combining `fields` & `fields_except` in the same resource (root or association) will exclude fields after the inclusion has been applied.