- 6.1 Resource Creation (POST)
- 6.2 Resource Updates (PUT, PATCH, Custom method)
- 6.3 Resource Deletes (DELETE) - Response status codes
- 6.4 Resource Retrieval (GET, OPTIONS) - Response status codes
- 6.5 Collection Resource Retrieval (GET, OPTIONS) - Examples - Response status codes
POST
requests MUST NOT include the entity Id to create, either in
the URI or body.
POST
requests MUST be made to collection resource URIs.
For Example: POST /v1/orders/{orderId}
is bad. Instead,
prefer: POST /v1/orders
If a client-provided unique identifier is needed, a key
field MAY
be provided for querying.
A POST creates a new entity within a collection resource. If the client creating the resource knows the ID, use a PUT instead.
The contract specified in an API for a POST request SHOULD be complete representations that mirror the response of a GET to the same resource minus the id field and fields for auditing, links, etc.
If a client-provided unique identifier is needed on a resource, a key field MAY be accepted by the API on POST that can be used for querying by the client.
A POST
creates a new entity within a collection resource. If the
client creating the resource knows the ID, use a PUT
instead.
If the key field is accepted by an API, POST requests containing a key field MUST prevent duplicate resources created with the same key field value.
POST requests MAY use fields other than key to constrain resource creation.
Request:
POST /v1/items Expand source
{
"_links": {
"productConfiguration": { "href": "https://configuration.products.cimpress.io/configurations/asdasdafasdfa" }
},
"key": "{merchantItemId}"
"sku": "VIP-44517",
"quantity": "10",
.....
}
Response:
201 Created Expand source
Location: https://items.commerce.cimpress.io/v1/items/4990a90a-acb5-416b-b3a3-69a71fb4c138
{
"_links": {
"productConfiguration": { "href": "https://configuration.products.cimpress.io/configurations/asdfasdf132asdfa"}
},
"id": "4990a90a-acb5-416b-b3a3-69a71fb4c138",
"key": "{merchantItemId}"
"createdBy": "asdafsdf",
"createdAt": "{ISO-8601}",
"modifiedBy": "asdafsdf",
"modifiedAt": "{ISO-8601}",
"sku": "VIP-44517",
"quantity": "10",
.....
}
POST
responses **SHOULD **return an HTTP 201 Created or an HTTP 202
Accepted response code, with a Location
header providing the URI for
the new entity.
If an operation can be completed synchronously, an HTTP 201 **SHOULD **be returned, the response body SHOULD contain the entirety of the created entity.
If the operation cannot be completed synchronously, an HTTP 202 SHOULD be returned, the response body SHOULD contain a link to the created entity.
RFC-7231 explicitly specifies the result of a POST SHOULD be an HTTP 201 Created with the Location header. Returning the created entity makes life much easier for your calling client if they need any information off of the entity, or if they want to provide the new entity to a user. It also reduces round-trip time from the API which is a significant concern for a global company.
APIs creating resources MUST return HTTP status codes that are most appropriate for the response.
APIs creating resources MUST return a standardized exception payload when returning a 4XX-series or 5XX-series response.
The most common status codes for this operation are below:
Status Code | When to use |
---|---|
201 - Created | Use when a new resource is created from either POST or PUT. You should also provide a Location header with the URI to the created resource. The body should include the resource created with a self link. |
202 - Accepted | Use when the response cannot be processed synchronously. The body should provide a URL for the client to retrieve any output of the request at in the future. |
400 - Invalid Request | Use when the content of the request cannot be parsed or are syntactically invalid. |
422 - Unprocessable Entity | Use when the contract in the request is valid and parsable, but the values contained within are semantically invalid. |
Request:
POST /v1/items Expand source
{
"_links": {
"productConfiguration": { "href": "https://configuration.products.cimpress.io/configurations/asdasdafasdfa" }
},
"key": "fooBarBaz"
"sku": "VIP-44517",
"quantity": "10",
.....
}
Response:
201 Created Expand source
Location: https://items.commerce.cimpress.io/v1/items/4990a90a-acb5-416b-b3a3-69a71fb4c138
{
"_links": {
"productConfiguration": { "href": "https://configuration.products.cimpress.io/configurations/asdfasdf132asdfa"}
},
"id": "4990a90a-acb5-416b-b3a3-69a71fb4c138",
"key": "fooBarBaz"
"createdBy": "asdafsdf",
"createdAt": "{ISO-8601}",
"modifiedBy": "asdafsdf",
"modifiedAt": "{ISO-8601}",
"sku": "VIP-44517",
"quantity": "10",
.....
}
POST /v1/items Expand source
{
"_links": {
"productConfiguration": { "href": "https://configuration.products.cimpress.io/configurations/qazwsxedcedcrfv" }
},
"key": "fooBarBaz"
"sku": "VIP-65782",
"quantity": "83"
}
Response
409 Precondition Failed Expand source
{
"status": 409,
"type": "https://errors.cimpress.io/items/duplicateItem",
"title": "duplicateItem",
"detail": "The item with key 'fooBarBaz' already exists.",
"instance": "urn:a8ebded3-3050-4e35-b439-71a6f01cee46"
"key": "fooBarBaz",
}
Resource updates MUST be idempotent. That is, identical requests sent multiple times MUST result in identical resource state. This property ensures deterministic behavior under at-least-once guarantees of request processing.
APIs for mutable resources MUST employ optimistic concurrency control to prevent lost updates when making changes to existing data concurrently.
APIs for mutable resources MUST support conditional requests as
defined in
RFC 7232.
These API's MUST use ETag
and If-Match
as the primary method of
concurrency control. The server MUST respond with 412 when the
ETag
from the request doesn't match the current one for that resource.
APIs SHOULD use PATCH
for partial updates to resources.
PATCH
request MUST support the conditional requests and
the If-Match
header as described in section 6.2.1.
PATCH
SHOULD replace collection properties with entire contents
from request. Use a custom method to update a collection in a more
sophisticated way.
The most simple PATCH operation is any subset of fields of the entity being updated.
PATCH /v1/items/{id} Expand source
If-Match: {ETag value}
{
"status": "shipped",
"quantity": "10",
"price": "4.25"
}
As the API evolves in a backwards compatible way, new fields may be added that existing clients are not aware of. If a new client gives a new field a value, existing clients may be at risk of setting it to null just by not sending it in their requests. In general prefer PATCH over PUT.
A PUT
request **MAY **be used when updating an entire resource at once
from the body of the request.
PUT
request URLs MUST uniquely identify a single resource that is
being updated.
PUT
requests SHOULD return an HTTP 200 OK response with the the
entire updated entity in the response body. If it is not possible to
return the entire resource in a timely fashion, an HTTP 202 Accepted
SHOULD be returned.
PUT
requests for mutable resources MUST send an If-Match
header
as described in section 6.2.1.
PUT
requests MUST be idempotent. That is, identical requests sent
multiple times MUST result in identical resource state. This
property ensures deterministic behavior under at-least-once guarantees
of request processing.
PUT /v1/items/{id} Expand source
If-Match: {ETag value}
{
"_links": {
"productConfiguration": { "href": "https://configuration.products.cimpress.io/configurations/asdasd-afasdfa"}
},
"id": "4990a90a-acb5-416b-b3a3-69a71fb4c138"
"sku": "VIP-44517",
"quantity": "10",
.....
}
APIs MAY use POST
with a custom method for partial updates to
resources.
Custom update methods **SHOULD **be exposed by POST operations using a
":"
and the name of the update. For example, an update to an item
status which requires a custom update format should be a
to POST /v1/items/{itemId}:updateItemStatus
A custom method POST
request MUST support the conditional requests
and the If-Match
header described in section 6.2.1.
Updates to a collection resource MUST be performed in a similar manner to a single resource.
POST /v1/items/{itemId}:updateItemStatus Expand source
If-Match: {ETag value}
{
"statuses": {
"shipped": {
"quantity": "10"
},
"production": {
"quantity": "10"
}
}
}
POST Resource Collection /v1/fulfiller/{id}/locations:addRemoveLocations Expand source
If-Match: {ETag value}
{
"addLocations": [
{ "key": "foo" },
{ "key": "bar" }
],
"removeLocations": [
{ "key": "bazz" },
{ "key": "boo" }
]
}
APIs updating resources MUST return HTTP status codes that are most appropriate for the response.
APIs updating resources MUST return a standardized exception payload when returning a 4XX-series or 5XX-series response.
The most common status codes for this operation are below:
Status Code | When to use |
---|---|
200 - OK | Use for any successful synchronous request. |
202 - Accepted | Use sparingly, and only when the response cannot be processed synchronously. The body should provide a URL for the client to retrieve any output of the request at in the future. |
400 - Invalid Request | Use when the content of the request cannot be parsed or are syntactically invalid. |
404 - Not Found | Use when the targeted resource could not be found. |
412 - Precondition Failed | When PUTing or PATCHing a resource, and the If-Match value you provide is not the most recent Etag, this indicates a conflict with multiple updates on the same resource |
422 - Unprocessable Entity | Use when the contract in the request is valid and parsable, but the values contained within are semantically invalid. |
APIs **SHOULD **use the DELETE
verb to remove individual resources,
and follow
the RFC7231 guidelines
on return values:
If a DELETE method is successfully applied, the origin server SHOULD
send a 202 (Accepted) status code if the action will likely succeed
but has not yet been enacted, a 204 (No Content) status code if the
action has been enacted and no further information is to be supplied,
or a 200 (OK) status code if the action has been enacted and the
response message includes a representation describing the status.
APIs SHOULD NOT return the data that was deleted.
If you’re returning the resource in the state it was before it was deleted, you’re explicitly returning an out of date response. Instead, prefer to return either nothing (204 No Content) or a data model indicating that the deletion was successful if the client would require additional information.
APIs for resources which can be deleted **MUST **support conditional
requests as defined
in RFC 7232.
These API's **MUST **use ETag
and If-Match
as the primary method of
concurrency control as described in section 6.2.1.
APIs deleting resources MUST return HTTP status codes that are most appropriate for the response.
APIs deleting resources MUST return a standardized exception payload when returning a 4XX-series or 5XX-series response.
The most common status codes for this operation are below:
Status Code | When to use |
---|---|
200 - OK | Use when a DELETE request was successful and the client may require further information. |
202 - Accepted | Use when a DELETE request will be performed asynchronously. |
204 - No Content | Use when a DELETE request was successfully applied and no further information is available or useful to caller. |
404 - Not Found | Use when the targeted resource could not be found. |
412 - Precondition Failed | If an If-Match is sent in the request, returned if the current Etag doesn't match. |
APIs SHOULD use GET
to retrieve or search for resources.
GET
requests MUST NOT mutate resources.
APIs MUST support OPTIONS
HTTP requests so that you can be called
from UIs that use
CORS.
UIs use a pattern called
preflight requests
to determine if they can access particular information for a user.
Preflight requests rely upon the OPTIONS
HTTP method being supported.
If you don't support it, no UI will ever be able to call your API.
APIs retrieving resources MUST return HTTP status codes that are most appropriate for the response.
APIs retrieving resources MUST return a standardized exception payload when returning a 4XX-series or 5XX-series response.
The most common status codes for this operation are below:
Status Code | When to use |
---|---|
200 - OK | Use for any successful synchronous request. |
404 - Not Found | The resource could not be found. |
Collection resources MUST be not be returned as a raw array. The response format should be an object as defined by the HAL+JSON specification.
The following common top-level fields MUST be returned on a collection APIs:
_embedded
- Object containing at least one relation calleditem
as dictated by HAL+JSON and RFC-6573
Responses containing no
results MUST return
a 200 - OK result
with the _embedded
item
relation set to an empty array in favor of
a 404 - Not Found
Collection resources SHOULD support filtering of the resources using query parameters.
For developers unfamiliar with the HAL+JSON specification, its handling of arrays is likely to be surprising. Here is a modified example from the specification.
Because a HAL+JSON response hangs on the keys "_links" and "_embedded", the top-level value cannot be an array. (Where would the keys and values go?) For that reason, arrays are considered to be embedding themselves.
This practice is to provide consistency and flexibility for service evolution. The wrapping object allows fields to be added in the future as needed (paging, etc...).
GET /v1/pets?ownerId=c040ec5f-8d83-4b14-9c15-62e873b20bba Expand source
GET /v1/pets?ownerId=465dde9d-39cf-4c5b-8008-bf62b0b45b95
{
"_links": {
"self": { "href": "https://pets.doghouse.cimpress.io/v1/pets?ownerId=c040ec5f-8d83-4b14-9c15-62e873b20bba"}
},
"_embedded": {
"item": [
{
"_links": {
"self": { "href": "https://pets.doghouse.cimpress.io/v1/pets/4990a90a-acb5-416b-b3a3-69a71fb4c138" },
"vaccinations": { "href": "https://pets.doghouse.cimpress.io/v1/pets/4990a90a-acb5-416b-b3a3-69a71fb4c138/vaccinations" },
"owner": { "href": "https://people.house.cimpress.io/v1/people/c040ec5f-8d83-4b14-9c15-62e873b20bba" }
},
"id": "4990a90a-acb5-416b-b3a3-69a71fb4c138",
"type": "cat",
"name": "Mr. Fuzzles"
},
{
"_links": {
"self": { "href": "https://pets.doghouse.cimpress.io/v1/pets/5990a90a-acb5-416b-b3a3-69a71fb4c138" },
"vaccinations": { "href": "https://pets.doghouse.cimpress.io/v1/pets/5990a90a-acb5-416b-b3a3-69a71fb4c138/vaccinations" },
"owner": { "href": "https://people.house.cimpress.io/v1/people/c040ec5f-8d83-4b14-9c15-62e873b20bba" }
},
"id": "5990a90a-acb5-416b-b3a3-69a71fb4c138",
"type": "dog",
"name": "Smokey"
}
]
}
}
APIs retrieving resources MUST return HTTP status codes that are most appropriate for the response.
APIs retrieving resources MUST return a standardized exception payload when returning a 4XX-series or 5XX-series response.
The most common status codes for this operation are below:
Status Code | When to use |
---|---|
200 - OK | Use for any successful synchronous request. Empty collections should use this status instead of 404. |
404 - Not Found | The resource could not be found. There is no collection resource versus the collection resource is empty. |
Unbounded collection resources, such as search results, MUST be
paged via limit
and offset
query string parameters.
The following common top-level fields MUST be returned on a paginated API:
offset
- String, reference pointer to the end of this page in the search results. Should be passed asoffset=<last offset>
as a query parameter of the request to get the next set of results. May be a number, but can also be a hash or b64 value._embedded
- Object containing at least one relation calleditem
as dictated by HAL+JSON
Additionally, paginated APIs MAY return:
count
- Number. The actual number of results returned inresults
.total
- Number. The total number of results matching the query.
If a collection resource is not paginated, then responses MUST be bounded.
If you have no limits on your response, it opens you up to accidental (and intended) denial-of-service attacks, as well as the possibility of accidentally sending huge result sets to your clients and causing extreme load on any downstream systems.
Null fields are included below for completeness, but are not required in the API response for efficiency.
GET /v1/pets?type=cat Expand source
GET /v1/pets?type=cat
{
"_links": {
"self": { "href": "https://pets.doghouse.cimpress.io/v1/pets?type=cat"},
"first": { "href": "https://pets.doghouse.cimpress.io/v1/pets?type=cat"},
"prev": null,
"next": { "href": "https://pets.doghouse.cimpress.io/v1/pets?type=cat &offset=asdfavaweawe"},
"last": null
},
"offset": "asdfavaweawe",
"count": 10,
"total": null,
"_embedded": {
"item": [
{
"_links": {
"self": { "href": "https://pets.doghouse.cimpress.io/v1/pets/4990a90a-acb5-416b-b3a3-69a71fb4c138" },
"vaccinations": { "href": "https://pets.doghouse.cimpress.io/v1/pets/4990a90a-acb5-416b-b3a3-69a71fb4c138/vaccinations" },
"owner": { "href": "https://people.house.cimpress.io/v1/people/c040ec5f-8d83-4b14-9c15-62e873b20bba" }
},
"id": "4990a90a-acb5-416b-b3a3-69a71fb4c138",
"type": "cat",
"name": "Mr. Fuzzles"
},
{
"_links": {
"self": { "href": "https://pets.doghouse.cimpress.io/v1/pets/2d696aa4-683a-419a-9329-21245380f848" },
"vaccinations": { "href": "https://pets.doghouse.cimpress.io/v1/pets/2d696aa4-683a-419a-9329-21245380f848/vaccinations" },
"owner": { "href": "https://people.house.cimpress.io/v1/people/ed822444-2978-4d7a-b4ea-8e863e520df0" }
},
"id": "2d696aa4-683a-419a-9329-21245380f848",
"type": "cat",
"name": "Felix"
},
...
]
},
...
}
Collection resources which support sorting MUST be done using the
sort
query string parameter.
Users SHOULD be able to specify ascending or descending order by
adding :asc
or :desc
to one or multiple fields.
Example with implicit asc
sorting order documented by the API for the
field createdAt
:
https://orders.commerce.cimpress.io/v1/orders?merchantId=vistaprint&sort=createdAt
Example with explicit sorting order:
https://orders.commerce.cimpress.io/v1/orders?merchantId=vistaprint&sort=createdAt:desc
Example with explicit sorting order for multiple fields:
https://orders.commerce.cimpress.io/v1/orders?merchantId=vistaprint&sort=createdAt:desc&sort=createdBy:asc
The API MUST support specifying a query parameter multiple times if
it supports sorting by multiple fields (such as
sort=category&sort=merchant
)