Buckets

A bucket is the parent object of collections and groups.

A bucket is a mapping with the following attributes:

  • data: (optional) attributes of the bucket object
    • id: the bucket object id
    • last_modified: the timestamp of the last modification
  • permissions: the ACLs for the bucket object

Creating a bucket

POST /buckets
Synopsis:Creates a new bucket. If id is not provided, it is automatically generated.

Requires authentication

Example Request

$ echo '{"data": {"id": "blog"}}' | http POST http://localhost:8888/v1/buckets --auth="bob:p4ssw0rd" --verbose
POST /v1/buckets HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
Authorization: Basic Ym9iOg==
Connection: keep-alive
Content-Length: 25
Content-Type: application/json; charset=utf-8
Host: localhost:8888
User-Agent: HTTPie/0.8.0

{
    "data": {
        "id": "blog"
    }
}

Example Response

HTTP/1.1 201 Created
Access-Control-Expose-Headers: Backoff, Retry-After, Alert, Content-Length
Content-Length: 155
Content-Type: application/json; charset=UTF-8
Date: Thu, 10 Sep 2015 08:34:32 GMT
Server: waitress

{
    "data": {
        "id": "blog",
        "last_modified": 1441874072429
    },
    "permissions": {
        "write": [
            "account:bob"
        ]
    }
}

A bucket also accept arbitrary attributes. For example, you may want to store some application settings there.

If the If-Match: "<timestamp>" request header is provided as described in the section about timestamps, and if the list has changed meanwhile, a 412 Precondition Failed error is returned.

If the If-None-Match: * request header is provided, and if the provided data contains an id field, and if there is already an existing object with this id, a 412 Precondition Failed error is returned.

Important

If the posted object has an id field, it will be taken into account.

However, if a object already exists with the same id, a 200 OK response is returned with the existing object in body (instead of 201 Created). See https://github.com/Kinto/kinto/issues/140

Validation

If the posted values are invalid (e.g. field value is not an integer) an error response is returned with 400 Bad Request.

See details on error responses.

Permissions

In the JSON request payloads, an optional permissions attribute can be provided.

The current user id is always added among the write principals.

See Permissions request payload.

HTTP Status Codes

  • 200 OK: This object already exists, the one stored on the database is returned
  • 201 Created: The object was created
  • 400 Bad Request: The request body is invalid
  • 401 Unauthorized: The request is missing authentication headers
  • 403 Forbidden: The user is not allowed to perform the operation, or the resource is not accessible
  • 406 Not Acceptable: The client doesn’t accept supported responses Content-Type
  • 412 Precondition Failed: List has changed since value in If-Match header
  • 415 Unsupported Media Type: The client request was not sent with a correct Content-Type

Replacing a bucket

PUT /buckets/(bucket_id)
Synopsis:Creates or replaces a bucket with a specific ID.

Requires authentication

If the bucket exists but you don’t have the write permission, you will get a 403 Forbidden http response.

Example request

$ http put http://localhost:8888/v1/buckets/blog --auth="bob:p4ssw0rd"
PUT /v1/buckets/blog HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
Authorization: Basic Ym9iOg==
Connection: keep-alive
Content-Length: 0
Host: localhost:8888
User-Agent: HTTPie/0.9.2

Example response

HTTP/1.1 200 OK
Access-Control-Expose-Headers: Backoff, Retry-After, Alert
Content-Length: 155
Content-Type: application/json; charset=UTF-8
Date: Thu, 18 Jun 2015 15:19:10 GMT
Server: waitress

{
    "data": {
        "id": "blog",
        "last_modified": 1434640750988
    },
    "permissions": {
        "write": [
            "account:bob"
        ]
    }
}

Validation and conflicts behaviour is similar to creating objects (POST).

If the If-Match: "<timestamp>" request header is provided as described in the section about timestamps, and if the object has changed meanwhile, a 412 Precondition Failed error is returned.

If the If-None-Match: * request header is provided and if there is already an existing object with this id, a 412 Precondition Failed error is returned.

Permissions

In the JSON request payloads, at least one of data and permissions must be provided. Permissions can thus be replaced independently from data.

In the case of creation, if only permissions is provided, an empty object is created.

The current user id is always added among the write principals.

See Permissions request payload.

HTTP Status Code

  • 201 Created: The object was created
  • 200 OK: The object was replaced
  • 400 Bad Request: The request body is invalid
  • 401 Unauthorized: The request is missing authentication headers
  • 403 Forbidden: The user is not allowed to perform the operation, or the resource is not accessible
  • 406 Not Acceptable: The client doesn’t accept supported responses Content-Type.
  • 412 Precondition Failed: Record was changed or deleted since value in If-Match header.
  • 415 Unsupported Media Type: The client request was not sent with a correct Content-Type.

Retrieve an existing bucket

GET /buckets/(bucket_id)
Synopsis:Returns a specific bucket by its ID.

Requires authentication

Example request

$ http get http://localhost:8888/v1/buckets/blog --auth="bob:p4ssw0rd" --verbose
GET /v1/buckets/blog HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
Authorization: Basic Ym9iOg==
Connection: keep-alive
Content-Length: 13
Content-Type: application/json
Host: localhost:8888
User-Agent: HTTPie/0.9.2

Example response

HTTP/1.1 200 OK
Access-Control-Expose-Headers: Backoff, Retry-After, Alert, Last-Modified, ETag
Content-Length: 155
Content-Type: application/json; charset=UTF-8
Date: Thu, 18 Jun 2015 15:25:19 GMT
Etag: "1434641119102"
Last-Modified: Thu, 18 Jun 2015 15:25:19 GMT
Server: waitress

{
    "data": {
        "id": "blog",
        "last_modified": 1434640750988
    },
    "permissions": {
        "write": [
            "account:bob"
        ]
    }
}

If the If-None-Match: "<timestamp>" request header is provided, and if the object has not changed meanwhile, a 304 Not Modified is returned.

HTTP Status Codes

  • 200 OK: The request was processed
  • 304 Not Modified: Object did not change since value in If-None-Match header
  • 400 Bad Request: The request header is invalid
  • 401 Unauthorized: The request is missing authentication headers
  • 403 Forbidden: The user is not allowed to perform the operation, or the resource is not accessible
  • 404 Not Found: The object does not exist or was deleted
  • 406 Not Acceptable: The client doesn’t accept supported responses Content-Type
  • 412 Precondition Failed: Object changed since value in If-Match header

Updating an existing bucket

PATCH /buckets/(bucket_id)
Synopsis:Modifies an existing bucket.

Requires authentication

If the object is missing (or already deleted), a 404 Not Found is returned only if the user has write access to the object parent, otherwise a 403 Forbidden is returned to avoid leaking information about non-accessible objects. The consumer might decide to ignore it.

If the If-Match: "<timestamp>" request header is provided as described in the section about timestamps, and if the object has changed meanwhile, a 412 Precondition Failed error is returned.

Note

last_modified is updated to the current server timestamp, only if a field value was changed.

Attributes merge

The provided values are merged with the existing object. For example:

  • {"a":"b"} + {"a":"c"}{"a":"c"}
  • {"a":"b"} + {"b":"c"}{"a":"b", "b":"c"}
  • {"a":"b"} + {"a":null}{"a":null} : attributes can’t be removed with patch
  • {"a": {"b":"c"}} + {"a":{"d":"e"}}{"a":{"d":"e"}} : sub-objects are replaced, not merged

JSON merge is currently supported using Content-Type: application/merge-patch+json. This provides support to merging sub-objects and removing attibutes. For example:

  • {"a":"b"} + {"a":null}{}
  • {"a": {"b":"c"}} + {"a":{"d":"e"}}{"a":{"b":"c", "d":"e"}}
  • {} + {"a":{"b":{"c":null}}}{"a":{"b":{}}}

Light response body

If a Response-Behavior request header is set to light, only the fields whose value was changed are returned. If set to diff, only the fields whose value became different than the one provided are returned.

JSON Patch Operations

JSON-Patch is a way to define a sequence of operations to be applied on a JSON object.

It’s possible to use JSON-Patch by sending the request header Content-Type: application/json-patch+json.

When using this request header, the body should contain a list of operations, for example:

[
    { "op": "test", "path": "data/a", "value": "foo" },
    { "op": "remove", "path": "/data/a" },
    { "op": "add", "path": "/data/b", "value": [ "foo", "bar" ] },
    { "op": "replace", "path": "/data/b", "value": 42 },
    { "op": "move", "from": "/data/a", "path": "/data/c" },
    { "op": "copy", "from": "/data/b", "path": "/data/d" }
]

For more information about each operation, please refer to JSON-Patch Specification.

This is very useful when altering permissions since there is no need to get the current value before adding some principal to the list.

Permissions

When permissions are modified, the same behaviour used for the body is expected. But notice thought that there are some permissions specific behaviours, such as:

  1. The current user id is always added among the write principals.
  2. Value is not used on permission JSON Patch operations and can be omitted.
[
    { "op": "test", "path": "/permissions/read/fxa:alice" },
    { "op": "add", "path": "/permissions/read/system.Everyone" },
    { "op": "remove", "path": "/permissions/read/fxa:bob" }
]
  1. On JSON Merge operations, null values can be used to remove all principals from a specific permission level. As a consequence, using null for permissions on other types of patch operations is considered a no-op.

For more information on permissions, see Permissions request payload.

HTTP Status Codes

  • 200 OK: The object was modified
  • 400 Bad Request: The request body is invalid, or a read-only field was modified
  • 401 Unauthorized: The request is missing authentication headers
  • 403 Forbidden: The user is not allowed to perform the operation, or the resource is not accessible
  • 404 Not Found: The object does not exist or was deleted
  • 406 Not Acceptable: The client doesn’t accept supported responses Content-Type.
  • 412 Precondition Failed: Record changed since value in If-Match header
  • 415 Unsupported Media Type: The client request was not sent with a correct Content-Type.

Deleting a bucket

DELETE /buckets/(bucket_id)
Synopsis:Deletes a specific bucket and everything under it.

Requires authentication

Example request

$ http delete http://localhost:8888/v1/buckets/blog --auth="bob:p4ssw0rd" --verbose
DELETE /v1/buckets/blog HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Authorization: Basic Ym9iOg==
Connection: keep-alive
Content-Length: 0
Host: localhost:8888
User-Agent: HTTPie/0.9.2

Example response

HTTP/1.1 200 OK
Access-Control-Expose-Headers: Backoff, Retry-After, Alert
Content-Length: 67
Content-Type: application/json; charset=UTF-8
Date: Thu, 18 Jun 2015 15:29:42 GMT
Server: waitress

{
    "data": {
        "deleted": true,
        "id": "blog",
        "last_modified": 1434641382954
    }
}

If the object is missing (or already deleted), a 404 Not Found is returned only if the user has write access to the object parent, otherwise a 403 Forbidden is returned to avoid leaking information about non-accessible objects. The consumer might decide to ignore it.

If the If-Match request header is provided, and if the object has changed meanwhile, a 412 Precondition Failed error is returned.

Note

Once deleted, an object will appear in the list when polling for changes, with a deleted status (delete=true) and will have most of its fields empty.

HTTP Status Codes

  • 200 OK: The object was deleted
  • 401 Unauthorized: The request is missing authentication headers
  • 403 Forbidden: The user is not allowed to perform the operation, or the resource is not accessible
  • 404 Not Found: The object does not exist or was already deleted
  • 406 Not Acceptable: The client doesn’t accept supported responses Content-Type.
  • 412 Precondition Failed: Record changed since value in If-Match header

Retrieving all buckets

GET /buckets
Synopsis:Returns the list of accessible buckets

Requires authentication

Example Request

$ http get http://localhost:8888/v1/buckets --auth="bob:p4ssw0rd" --verbose
GET /v1/buckets HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Authorization: Basic Ym9iOg==
Connection: keep-alive
Host: localhost:8888
User-Agent: HTTPie/0.8.0

Example Response

HTTP/1.1 200 OK
Access-Control-Expose-Headers: Backoff, Retry-After, Alert, Content-Length, Next-Page, Total-Records, Last-Modified, ETag
Content-Length: 54
Content-Type: application/json; charset=UTF-8
Date: Thu, 10 Sep 2015 08:37:32 GMT
Etag: "1441874072429"
Last-Modified: Thu, 10 Sep 2015 08:34:32 GMT
Server: waitress
Total-Records: 1

{
    "data": [
        {
            "id": "blog",
            "last_modified": 1441874072429
        }
    ]
}

A Total-Records response header indicates the total number of objects of the list (not the response, since it can be paginated).

A Last-Modified response header provides a human-readable (rounded to second) of the current collection timestamp.

For cache and concurrency control, an ETag response header gives the value that consumers can provide in subsequent requests using If-Match and If-None-Match headers (see section about timestamps).

List of available URL parameters

Filtering, sorting, partial responses and paginating can all be combined together.

  • ?_sort=-last_modified&_limit=100&_fields=title

HTTP Status Codes

  • 200 OK: The request was processed
  • 304 Not Modified: List has not changed since value in If-None-Match header
  • 400 Bad Request: The request querystring is invalid
  • 401 Unauthorized: The request is missing authentication headers
  • 403 Forbidden: The user is not allowed to perform the operation, or the resource is not accessible
  • 406 Not Acceptable: The client doesn’t accept supported responses Content-Type
  • 412 Precondition Failed: List has changed since value in If-Match header

Delete all buckets

DELETE /buckets
Synopsis:Delete every writable buckets for this user

Requires authentication

Example Request

$ http delete http://localhost:8888/v1/buckets --auth="bob:p4ssw0rd" --verbose
DELETE /v1/buckets HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Authorization: Basic YWxpY2U6
Connection: keep-alive
Content-Length: 0
Host: localhost:8888
User-Agent: HTTPie/0.9.2

Example Response

HTTP/1.1 200 OK
Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff
Content-Length: 101
Content-Type: application/json; charset=UTF-8
Date: Fri, 26 Feb 2016 14:12:22 GMT
Server: waitress

{
    "data": [
        {
            "deleted": true,
            "id": "e64db3f9-6a60-1acf-fc3a-7d1ba7e823aa",
            "last_modified": 1456495942515
        }
    ]
}

It supports the same filtering, sorting and pagination capabilities as GET.

If the number of records to be deleted exceeds to pagination limit, a response header Next-Page will be provided.

If the If-Match: "<timestamp>" request header is provided, and if the list has changed meanwhile, a 412 Precondition Failed error is returned.

HTTP Status Codes

  • 200 OK: The objects were deleted
  • 401 Unauthorized: The request is missing authentication headers
  • 403 Forbidden: The user is not allowed to perform the operation, or the resource is not accessible
  • 405 Method Not Allowed: This endpoint is not available
  • 406 Not Acceptable: The client doesn’t accept supported responses Content-Type
  • 412 Precondition Failed: The list has changed since value in If-Match header

Personal bucket «default»

When the built-in plugin kinto.plugins.default_bucket is enabled in configuration, a bucket default is available.

As explained in the section about collections, the default bucket implicitly creates the collections objects on their first use.

GET /buckets/default
Synopsis:Returns the current user personnal bucket.

Requires authentication

Example Request

$ http get http://localhost:8888/v1/buckets/default -v --auth='bob:p4ssw0rd'
GET /v1/buckets/default HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Authorization: Basic Ym9iOg==
Connection: keep-alive
Host: localhost:8888
User-Agent: HTTPie/0.8.0

Example Response

HTTP/1.1 200 OK
Access-Control-Expose-Headers: Content-Length, Expires, Alert, Retry-After, Last-Modified, ETag, Pragma, Cache-Control, Backoff
Content-Length: 187
Content-Type: application/json; charset=UTF-8
Date: Wed, 28 Oct 2015 16:29:00 GMT
Etag: "1446049740955"
Last-Modified: Wed, 28 Oct 2015 16:29:00 GMT
Server: waitress

{
    "data": {
        "id": "b8f3fa97-3e0a-00ae-7f07-ce8ce05ce0e5",
        "last_modified": 1446049740955
    },
    "permissions": {
        "write": [
            "account:bob"
        ]
    }
}

For convenience, the actual default bucket id is provided in the root URL of Kinto:

GET /
Synopsis:Obtain current user personnal bucket in root URL.

Requires authentication

Example Request

$ http get http://localhost:8888/v1/ -v --follow --auth='bob:p4ssw0rd'

Example Response

HTTP/1.1 200 OK
Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff
Content-Length: 400
Content-Type: application/json; charset=UTF-8
Date: Wed, 28 Oct 2015 16:52:49 GMT
Server: waitress

{
    "hello": "kinto",
    "version": "1.7.0.dev0"
    "url": "http://localhost:8888/v1/",
    "documentation": "https://kinto.readthedocs.io/",
    "settings": {
        "batch_max_requests": 25,
    },
    "user": {
        "id": "account:bob",
        "bucket": "b8f3fa97-3e0a-00ae-7f07-ce8ce05ce0e5",
    }
}