Snaps¶
Introduction¶
The Snaps API provides a series of endpoints supporting common actions during the lifetime of a snap package.
The Snaps API is exposed at the following base URLs:
Production: https://dashboard.snapcraft.io/dev/api
Response Format¶
JSON will be returned in all responses from the API, including Errors.
Reference¶
Register a snap name¶
- POST /dev/api/register-name/¶
- Request Headers
Authorization – macaroon authorization header with the
package_register
permission
- Query Parameters
dry_run – (optional) when set, validate the requested snap name but don’t register it
- Request JSON Object
snap_name (string) – name of the snap package
is_private (boolean) – (optional, defaults to
false
) whether the name should be considered private or notstore (string) – (optional, defaults to the global store) the ID of the store to register this snap in
- Response JSON Object
snap_id (string) – the unique
snap_id
associated with this snap (null
whendry_run
query parameter is set)snap_name (string) – matches the requested snap name
- Status Codes
200 OK – success (when
dry_run
query parameter is set)201 Created – success
400 Bad Request – error
401 Unauthorized – authentication required
403 Forbidden – authorization failed
409 Conflict – name already owned by the user, name already registered by someone else, or name reserved
429 Too Many Requests – when names are tried to be registered too quickly
503 Service Unavailable – registration failed
Important
In order to register a snap name the request’s authentication macaroon needs
to include the package_register
permission. Refer to the
Macaroons API for information on how to request a macaroon with
the right permissions.
Note
The is_private
parameter is used to indicate the privacy setting for the
initial push. This setting can be changed at any later time.
The dry_run
query parameter is used to test if the name is valid and
currently available. It does not register the name, so the name may not be
available on a subsequent call.
Usage¶
Before pushing a snap package, the developer needs to register the snap name. To do so, an authenticated request has to be issued as follows:
Request:
POST /dev/api/register-name/ HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: Macaroon root=..., discharge=...
Content-Type: application/json
{
"snap_name": "foo"
}
Response:
HTTP/1.1 201 CREATED
Content-Type: application/json
{
"snap_id": "some-snap-id",
"snap_name": "foo"
}
The developer can state whether the snap is going to be marked as private on
first upload by setting the is_private
field to true
. Example:
Request:
POST /dev/api/register-name/ HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: Macaroon root=..., discharge=...
Content-Type: application/json
{
"is_private": true,
"snap_name": "foo"
}
Response:
HTTP/1.1 201 CREATED
Content-Type: application/json
{
"snap_id": "some-snap-id",
"snap_name": "foo"
}
A snap name can also be registered against a specific store. The developer must have upload permissions on the target store. To check which stores the developer can access, please refer to the Accounts API. If no store is given, the global store is used as default.
Request:
POST /dev/api/register-name/ HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: Macaroon root=..., discharge=...
Content-Type: application/json
{
"store": "the-store-id",
"snap_name": "foo"
}
Response:
HTTP/1.1 201 CREATED
Content-Type: application/json
{
"snap_id": "some-snap-id",
"snap_name": "foo"
}
It’s possible to just trigger validation for a snap name without actually
registering it by setting the dry_run
flag as a query string parameter:
Request:
POST /dev/api/register-name/?dry_run=1 HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: Macaroon root=..., discharge=...
Content-Type: application/json
{
"snap_name": "foo"
}
Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"snap_id": null,
"snap_name": "foo"
}
Errors¶
All error responses are JSON-encoded and contain a dictionary with information
about what went wrong. Due to backwards compatible reasons, the dictionary has
many keys, but only the error_list
key should be used from now on. The rest
of the keys are deprecated. Below a list of the most common error responses.
If the macaroon used for authentication does not contain the
package_register
permission an error response will be returned.
Response:
HTTP/1.1 403 FORBIDDEN
Content-Type: application/json
{
"error_list": [
{
"message": "Permission 'package_register' is required as a macaroon caveat.",
"code": "macaroon-permission-required",
"extra": {
"permission": "package_register"
}
}
]
}
The developer needs to sign the Developer Programme Agreement before pushing snaps. Failing to do so will result in an error response:
Response:
HTTP/1.1 403 FORBIDDEN
Content-Type: application/json
{
"error_list": [
{
"message": "Developer has not signed agreement.",
"code": "user-not-ready",
"extra": {
"url": "https://dashboard.staging.snapcraft.io/dev/agreements/new/",
"api": "https://dashboard.staging.snapcraft.io/dev/api/agreement/"
}
}
]
}
The developer must have a store username set before registering snap names. Failing to do so will result in an error response as follows:
Response:
HTTP/1.1 403 FORBIDDEN
Content-Type: application/json
{
"error_list": [
{
"message": "Developer profile is missing the store username.",
"code": "user-not-ready",
"extra": {
"url": "https://dashboard.staging.snapcraft.io/dev/account/"
}
}
]
}
If the request contains invalid data, an error response will be returned detailing the problem(s). For example, if the provided snap name is not valid, the following error response is returned:
Response:
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json
{
"error_list": [
{
"message": "The name 'some name' is not valid: it should only have ASCII lowercase letters, numbers, and hyphens, and must have at least one letter.",
"code": "invalid",
"extra": {
"field": "snap_name",
"snap_name": "some name"
}
}
]
}
If the requested name is already registered by another publisher, the error
response will contain extra metadata such as the suggested_snap_name
and
register_name_url
.
Response:
HTTP/1.1 409 CONFLICT
Content-Type: application/json
{
"error_list": [
{
"message": "The snap name 'some-name' is already registered.",
"code": "already_registered",
"extra": {
"register_name_url": "https://dashboard.snapcraft.io/register-snap/?name=some-name",
"field": "snap_name",
"suggested_snap_name": "your-username-some-name",
"snap_name": "some-name"
}
}
]
}
If the requested name is reserved (common and well-known names are reserved),
the error response will also contain extra metadata such as the
suggested_snap_name
and register_name_url
.
Response:
HTTP/1.1 409 CONFLICT
Content-Type: application/json
{
"error_list": [
{
"message": "The snap name 'reserved' is reserved.",
"code": "reserved_name",
"extra": {
"register_name_url": "https://dashboard.snapcraft.io/register-snap/?name=reserved",
"field": "snap_name",
"suggested_snap_name": "your-username-reserved",
"snap_name": "reserved"
}
}
]
}
But if the requesting user has already filed a claim for a reserved or already registered snap name, which is still waiting for review, the error response is:
Response:
HTTP/1.1 409 CONFLICT
Content-Type: application/json
{
"error_list": [
{
"message": "You already registered a claim for the snap name 'some-name'.",
"code": "already_claimed",
"extra": {
"field": "snap_name",
"snap_name": "some-name"
}
}
]
}
Or maybe the requesting user already owns the name, in which case the error response will be:
Response:
HTTP/1.1 409 CONFLICT
Content-Type: application/json
{
"error_list": [
{
"message": "You already own the snap name 'some-name'.",
"code": "already_owned",
"extra": {
"field": "snap_name",
"snap_name": "some-name"
}
}
]
}
If the requested snap name was previously owned by the requesting user and that name was revoked at some point in the past, the following response is returned:
Response:
HTTP/1.1 409 CONFLICT
Content-Type: application/json
{
"error_list": [
{
"message": "You previously owned 'some-name' but it was revoked.",
"code": "revoked_name",
"extra": {
"field": "snap_name",
"snap_name": "some-name"
}
}
]
}
If many names are tried to be registered too quickly, the following error will
be returned with the extra metadata retry_after
field (also defined in the
Retry-After
response header) containing the amount of time to wait in
seconds before the next attempt:
Response:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 117
{
"error_list": [
{
"message": "You can register up to 100 snap names every 10 minutes. You must wait 2 minutes before the next snap name registration.",
"code": "register_window",
"extra": {
"snap_name": "some-name-101",
"allowed_count": 100,
"retry_after_label": "2 minutes",
"window_seconds": 600,
"retry_after": 117,
"window_label": "10 minutes"
}
}
],
}
In some cases the submitted data is valid, but the request might fail to complete. In such cases a response like the following will be returned:
Response:
HTTP/1.1 503 SERVICE UNAVAILABLE
Content-Type: application/json
{
"error_list": [
{
"message": "Failed to register",
"code": "failed-to-register"
}
]
}
Register a snap name dispute¶
If the attempt to register a snap name (with or without dry_run
) results in
a 409 response with error code reserved_name
or already_registered
, the
caller can offer the end user to file a snap name dispute, that will be
resolved by a human doing snap name dispute reviews.
To file a snap name dispute, a request has to be made as follows:
- POST /dev/api/register-name-dispute/¶
- Request Headers
Authorization – macaroon authorization header
- Request JSON Object
snap_name (string) – name of the snap name being disputed
comment (string) – a complete explanation from the requesting user about their rights to the snap name being disputed
is_private (boolean) – (optional, defaults to
false
) whether the name should be considered private or notstore (string) – (optional, defaults to the global store) the ID of the store to register this snap in, once the dispute is solved
- Response JSON Object
snap_name (string) – the snap name being disputed
- Status Codes
201 Created – success
400 Bad Request – name is available, so a dispute cannot be filed for it
401 Unauthorized – authentication required
403 Forbidden – authorization failed
409 Conflict – name already owned or already disputed by the requesting user
503 Service Unavailable – registration failed
Important
In order to register a snap name dispute the request’s authentication
macaroon needs to include the package_register
permission. Refer to the
Macaroons API for information on how to request a macaroon with
the right permissions.
Usage¶
If the request is valid, a snap name dispute can be successfully filed by issuing a POST request as shown in the following example. The result will include the disputed snap name, and a status URL (pointing to the Dashboard web UI) where the requesting user can check the status of the dispute.
Request:
POST /dev/api/register-name-dispute/ HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: Macaroon root=..., discharge=...
Content-Type: application/json
{
"snap_name": "some-name",
"comment": "Please I need the name and I am nice"
}
Response:
HTTP/1.1 201 CREATED
Content-Type: application/json
{
"status_url": "https://dashboard.snapcraft.io/register-snap-feedback/some-name/",
"snap_name": "some-name"
}
The fields snap_name
and comment
are required. If some of
those fields are not sent, an error response will be returned as follows:
Response:
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json
{
"error_list": [
{
"message": "Required field is missing.",
"code": "missing-field",
"extra": {
"field": "comment"
}
}
]
}
If the snap_name
sent is neither reserved nor taken by someone else, an
error response is returned as follows:
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json
{
"error_list": [
{
"message": "The name 'other-name' is not available for disputing.",
"code": "name-not-available-for-dispute",
"extra": {
"snap_name": "other-name"
}
}
]
}
If the requesting user already owns or has filed a claimed for the
snap_name
being sent for dispute, error responses with codes
already_owned
or already_claimed
, respectively, will be returned just
like in the Register a snap name API.
Assert a build for a snap¶
Process and store a snap-build assertion. Currently snap-build is not enforced before publishing an upload.
- POST /dev/api/snaps/(snap_id)/builds¶
- Request Headers
Authorization – macaroon authorization header
- Parameters
snap_id – the
snap_id
of the snap
- Request JSON Object
assertion (string) – UTF-8 signed assertion blob
- Response JSON Object
success (boolean) – whether the build assertion was saved successfully
- Status Codes
200 OK – success
400 Bad Request – error
401 Unauthorized – authentication required
403 Forbidden – authorization failed
Usage¶
To submit a build assertion of their package, a developer posts a request like the following:
Request:
POST /dev/api/snaps/some_snap_id/builds HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: Macaroon root=..., discharge=...
Content-Type: application/json
{
"assertion": "utf-8 signed assertion blob"
}
Note
The assertion blob is simply the snap-build assert data as assembled and signed by developers.
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"headers": {
"authority-id": "",
"grade": "",
"sign-key-sha3-384": "",
"snap-id": "",
"snap-sha3-384": "",
"snap-size": "",
"timestamp": "",
"revision": "",
"type": "snap-build"
}
}
If the macaroon used for authentication does not contain the package_upload
permission or is restricted to a set of snap packages that doesn’t include
this package, an error response will be returned
Response:
HTTP/1.1 403 FORBIDDEN
Content-Type: application/problem+json
{
"type": "devportal:v1:macaroon-permission-required",
"title": "Macaroon missing required permission.",
"detail": "Permission is required: package_upload",
"status": 403,
"permission": "package_upload"
}
The developer needs to sign the Developer Programme Agreement before they can assert builds. Failing to do so will result in an error response
Response:
HTTP/1.1 403 FORBIDDEN
Content-Type: text/plain
Developer has not signed agreement.
The developer needs to have defined their namespace in their user profile before they can assert builds. Failing to do so will result in an error response
Response:
HTTP/1.1 403 FORBIDDEN
Content-Type: text/plain
Developer profile is missing short namespace.
In the event that the request is missing fields, an error response will be returned detailing the problem
Response:
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json
{
"success": false,
"errors": [{"name": ["This field is required."]}]
}
If the content of assertion has any invalid information, an error response will be returned
Response:
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json
{
"success": false,
"errors": [{"name": ["Not a valid snap-build assertion."]}]
}
Push a snap build to the Store¶
- POST /dev/api/snap-push/¶
- Request Headers
Authorization – macaroon based authorization header
- Request JSON Object
name (string) – name of the snap package
updown_id (string) –
updown_id
obtained when uploading the build binarybuilt_at (string) – (optional) date and time at which the build was started
channels (list) – (optional) list of channels to release the snap to once uploaded
only_if_newer (boolean) – (optional) only release the snap to the specified channels if it is newer than the current release
- Response JSON Object
success (boolean) – true if the request was acknowledged properly
status_url (string) – (deprecated) URL to poll for status changes (for old-style processing)
status_details_url (string) – URL to poll for current server side status changes
- Status Codes
202 Accepted – accepted
400 Bad Request – error
401 Unauthorized – authentication required
403 Forbidden – authorization failed
404 Not Found – not found
Important
In order to push a snap the request’s authentication macaroon needs to
include the package_upload
permission. Refer to the Macaroons
API for information on how to request a macaroon with the right permissions.
Usage¶
To submit a new version of their snap package, a developer pushes it to the Store
Request:
POST /dev/api/snap-push/ HTTP/1.1
Host: dashboard.snapcraft.io
Content-Type: application/json
{
"name": "foo",
"updown_id": "some-updown-id"
}
Response:
HTTP/1.1 202 ACCEPTED
Content-Type: application/json; charset=utf-8
{
"success": true,
"status_url": "https://dashboard.snapcraft.io/<some upload id>"
}
Note
Receiving a 202 response means the Store has acknowledged the submission and will proceed to analyze the snap package for errors before it’s fully accepted.
If the macaroon used for authentication does not contain the package_upload
permission or is restricted to a set of snap packages that doesn’t include
this package, an error response will be returned
Response:
HTTP/1.1 403 FORBIDDEN
Content-Type: application/problem+json
{
"type": "devportal:v1:macaroon-permission-required",
"title": "Macaroon missing required permission.",
"detail": "Permission is required: package_upload",
"status": 403,
"permission": "package_upload"
}
If a push is attempted for a package that has not had its name registered beforehand, an error like this will be returned
Response:
HTTP/1.1 404 NOT FOUND
The developer needs to sign the Developer Programme Agreement before they can push snap packages. Failing to do so will result in an error response
Response:
HTTP/1.1 403 FORBIDDEN
Content-Type: text/plain
Developer has not signed agreement.
The developer needs to have defined their namespace in their user profile before they can push snap packages. Failing to do so will result in an error response
Response:
HTTP/1.1 403 FORBIDDEN
Content-Type: text/plain
Developer profile is missing short namespace.
In the event that the request contained invalid data, an error response will be returned detailing the problem
Response:
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json
{
"success": false,
"errors": [{"name": ["This field is required."]}]
}
Release a snap build to a channel¶
- POST /dev/api/snap-release/¶
- Request Headers
Authorization – macaroon authorization header
- Request JSON Object
name (string) – name of the snap package
revision (int) – revision to release
channels (list) – list of channels to release the build to; these will be added to whatever current channels the build is already released (if any). This will be matched against the macaroon in the authorization header using fnmatch
progressive (dict) – (optional) a dictionary with keys
paused
andpercentage
to make this release a progressive release (see below for further info)
- Response JSON Object
success (boolean) – whether the build was released successfully
channel_map (list) – (optional) a list of all the channels and which versions/revisions are released on each (see below for further info)
opened_channels (list) – (optional) names of the channels that got their first release on the current call
- Status Codes
200 OK – success
400 Bad Request – error
401 Unauthorized – authentication required
403 Forbidden – authorization failed
404 Not Found – not found
409 Conflict – the build or the snap are not ready to release
503 Service Unavailable – release failed
Important
In order to release a snap the request’s authentication macaroon needs to
include the package_upload
permission. Refer to the Macaroons
API for information on how to request a macaroon with the right permissions.
About channel_map¶
If present, this field will be a list of channel names with more information for each. The list is ordered according to the channel priority hierarchy (e.g.: stable, candidate, beta, edge).
Every item in the list is a dict, with at least channel
and info
in it. There are three kind of items.
when the channel doesn’t have any release:
{'channel': 'stable', 'info': 'none'}
when the channel has a release:
{'channel': 'candidate', 'info': 'specific', 'version': '2.7', 'revision': 1}
when the channel doesn’t have any release, but as a superior channel does, it would use that revision if requested:
{'channel': 'beta', 'info': 'tracking'}
About progressive releases¶
If the progressive
field is defined, the release will be done
progressively, in the sense that a percentage of devices will receive the
revision being released.
The field progressive
should be a dictionary with the following keys:
paused
a boolean indicating whether the release is active or not.percentage
a number between 0 and 100, specifies the percentage of devices receiving this release.
Releasing a revision with a progressive percentage of 100 and releasing it without a progressive percentage are not equivalent. This behaviour is slightly surprising, but it’s a consequence of the fact that not all devices can ever get a progressive revision, since a device may only participate in a progressive release if we have a way to consistently identify it.
In order to perform a non-progressive release, either omit including this
field, or send the field with all keys with value null
.
The current status of a progressive release is reported by the releases V2 API
and the channel-map V2 API endpoints in the
progressive
response object, with the following fields:
paused
same as described above.percentage
same as described above.current-percentage
a number between 0 and 100, specifying the percentage of devices that have reported this revision installed on this channel over the total number of devices that have installed any revision on the same channel. This field is only populated in the channel-map V2 API response.
Usage¶
When a developer is ready to make their snap package available to the world, they can release it like:
Request:
POST /dev/api/snap-release/ HTTP/1.1
Host: dashboard.snapcraft.io
Content-Type: application/json
{
"name": "foo",
"revision": "1",
"channels": ["candidate"]
}
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"channel_map": [
{"channel": "stable", "info": "none"},
{"channel": "candidate", "version": "0.1", "info": "specific", "revision": 1},
{"channel": "beta", "info": "tracking"},
{"channel": "edge", "info": "tracking"}
],
"channel_map_tree": {
"latest": {
"16": {
"all": [
{"channel": "stable", "info": "none"},
{"channel": "candidate", "version": "0.1", "info": "specific", "revision": 1},
{"channel": "beta", "info": "tracking"},
{"channel": "edge", "info": "tracking"}
]
}
}
},
"opened_channels": ["candidate"],
"success": true
}
The publisher can choose to make the release available only to a subset of devices in the field, for example to 20% of the devices. This is called a progressive release and can be done with the following API request:
Request:
POST /dev/api/snap-release/ HTTP/1.1
Host: dashboard.snapcraft.io
Content-Type: application/json
{
"name": "foo",
"revision": 1,
"channels": ["beta"],
"progressive": {
"percentage": 20,
"paused": false
}
}
Errors¶
If the macaroon used for authentication does not contain the package_upload
permission or is restricted to a set of snap packages that doesn’t include
this package, an error response will be returned:
Response:
HTTP/1.1 403 FORBIDDEN
Content-Type: application/json
{
"type": "devportal:v1:macaroon-permission-required",
"title": "Macaroon missing required permission.",
"status": 403,
"error_list": [
{
"extra": {
"permission": "package_release"
},
"message": "Permission \"package_release\" is required as a macaroon caveat.",
"code": "macaroon-permission-required"
}
],
"detail": "Permission \"package_release\" is required as a macaroon caveat.",
"code": "macaroon-permission-required",
"permission": "package_release"
}
If a release is requested for a package that has not had its name registered beforehand, an error like this will be returned:
Response:
HTTP/1.1 404 NOT FOUND
Content-Type: application/json
{
"error_list": [
{
"extra": {
"field": "name",
"value": "foo"
},
"message": "Snap not found for name=foo",
"code": "resource-not-found"
}
]
}
Or if the revision being requested to be released does not exist, a similar error is returned:
Response:
HTTP/1.1 404 NOT FOUND
Content-Type: application/json
{
"error_list": [
{
"extra": {
"field": "revision",
"value": 2
},
"message": "Upload not found for the requested snap with revision=2",
"code": "resource-not-found"
}
]
}
The developer needs to sign the Developer Programme Agreement before they can release snap packages. Failing to do so will result in an error response:
Response:
HTTP/1.1 403 FORBIDDEN
Content-Type: application/json
{
"errors": "Developer has not signed agreement.",
"error_list": [
{
"extra": {
"api": "https://dashboard.snapcraft.io/dev/api/agreement/",
"url": "https://dashboard.snapcraft.io/dev/agreements/new/"
},
"message": "Developer has not signed agreement.",
"code": "user-not-ready"
}
],
"success": false
}
The developer needs to have defined their namespace in their user profile before they can release snap packages. Failing to do so will result in an error response:
Response:
HTTP/1.1 403 FORBIDDEN
Content-Type: application/json
{
"errors": "Developer profile is missing the store username.",
"error_list": [
{
"extra": {
"url": "https://dashboard.snapcraft.io/dev/account/"
},
"message": "Developer profile is missing the store username.",
"code": "user-not-ready"
}
],
"success": false
}
In the event that the request contained invalid data, an error response will be returned detailing the problem:
Response:
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json
{
"errors": {
"revision": [
"The 'revision' field is required."
]
},
"error_list": [
{
"extra": {
"field": "revision"
},
"message": "The 'revision' field is required.",
"code": "missing-field"
}
],
"success": false
}
Another example of invalid data is when the caller sends an invalid channel:
Response:
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json
{
"errors": "Track does not exist: 1.0",
"error_list": [
{
"extra": {
"field": "channels",
"value": [
"1.0/beta"
]
},
"message": "Track does not exist: 1.0",
"code": "invalid-field"
}
],
"success": false
}
In some cases the submitted data is valid, but the request might fail to complete. In such cases a response like the following will be returned:
Response:
HTTP/1.1 503 SERVICE UNAVAILABLE
Content-Type: application/json
{
"errors": "SnapRevs update failed.",
"error_list": [
{
"message": "SnapRevs update failed.",
"code": "resource-not-ready"
}
],
"success": false
}
When doing a progressive release, the correctness of the progressive parameters is enforced. For example, the percentage must be a number between 0 and 100:
Response:
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json
{
"error_list": [
{
"code": "invalid-field",
"extra": {
"field": "progressive-percentage",
"value": "20"
},
"message": "Progressive \"percentage\" must be between 0 and 100."
}
],
"errors": "Progressive \"percentage\" must be between 0 and 100.",
"success": false
}
The paused flag must be a boolean:
Response:
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json
{
"error_list": [
{
"code": "invalid-field",
"extra": {
"field": "progressive-paused",
"value": null
},
"message": "Progressive flag \"paused\" must be a boolean."
}
],
"errors": "Progressive flag \"paused\" must be a boolean.",
"success": false
}
And lastly, if the progressive parameter is given, it must be a dictionary:
Response:
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json
{
"error_list": [
{
"code": "invalid-field",
"extra": {
"field": "progressive",
"value": {}
},
"message": "The parameter \"progressive\" must be a dict with keys: paused, percentage."
}
],
"errors": "The parameter \"progressive\" must be a dict with keys: paused, percentage.",
"success": false
}
Obtaining information about a snap¶
This API endpoint allows publishers or collaborators to obtain an overview-set of information about their snaps by simply passing its`name`.
This endpoint is intended to be an quicker alternative to the current process of resolving name to snap_id via the Accounts response, then hit the metadata endpoint for textual fields and the binary-metadata for associated icon and screenshots. This endpoint allows clients to get all they need in a single request.
- GET /dev/api/snaps/info/(name)¶
- Request Headers
Authorization – macaroon authorization header
- Response JSON Object
snap_id – unique snap identifier
snap_name – name of the snap
series – series where this snap is available
store – store the snap was registered to
publisher – snap publisher reference object, see more details in About publisher
status – whether the snap is currently available in any channel (‘published’ or ‘unpublished’)
channel_maps_list – map of {arch: channel_map} where this snap is currently released, see more details in About channel_map
aliases – remote aliases granted to this snap
private – whether this is snap is private or not
title – single-line text displayed as title in the snap page
summary – single-line summary
description – multi-line description
keywords – list of proposed keywords to facilitate search
license – SPDX 1.1 license expression for this snaps
media – list of images associated with this snap, see more details in About media
contact – upstream project contact URL
website – upstream project website URL
blacklist_countries – list of country codes (ISO ALPHA-2) in which the snap distribution is forbidden
whitelist_countries – list of country codes (ISO ALPHA-2) in which the snap is exclusively allowed to be distributed
video_urls – list of third-part video URLs associated for this snap
public_metrics_enabled – whether public metrics are enabled for this snap or not
public_metrics_blacklist – list of public metric names not available for consumption
unlisted – whether this snap should be part of search results or not
categories – categories list for the snap, (see Snap categories for more details)
update_metadata_on_release – boolean, if set to True, automatically update metadata on subsequent releases to default_track, and stable channel. If set to False (or Null), only update the metadata via website.
origin – DEPRECATED use
publisher["username"]
publisher_name – DEPRECATED use
publisher["display-name"]
company_name – DEPRECATED it is not part of any workflow and will be soon removed.
icon_url – DEPRECATED use
media
screenshot_urls – DEPRECATED use
media
- Status Codes
200 OK – success
401 Unauthorized – authentication required
404 Not Found – snap not found or not authorized
503 Service Unavailable – internal server error
Important
In order to fetch snap metrics the request’s authentication macaroon needs
to include the package_access
permission. See Macaroons API
for information on how to request a macaroon with the right permissions.
About publisher
¶
A reference to a snap publisher
is a canonical object across the entire API as:
{
"id": "ap8oZPhPCkgEZAGTyU7lRCR0NtNeMyRh",
"username": "cprov",
"display-name": "Celso Providelo",
"validation": "unproven"
}
The id
property is the user identifier, mostly used as a reference in
documents exchanged with devices.
The username
is the user unique store username, normally inherited from
the SSO account, it’s an ascii-only single-word sequence used to visually
disambiguate references to the publisher in the UI.
The display-name
is the capitalized, multiple-words and free-form
(unicode, emoji, etc) users define as a textual label for themselves.
It’s normally inherited from the SSO account (First and Last names).
The validation
fields represents the identity validation status of the
context account in the Store. At the moment, it is either unproven or
verified, where verified means the user identity (display-name, username
and contact information) is legitimate. For practical purposes, anything other
than unproven should be considered, at least, as a verified identity.
About media
¶
The media
field is always an array containing zero or more images
associated with a particular snap:
[
{"type": "icon", "width": 256, "height": 256, "url": "https://..."},
{"type": "banner", "width": 720, "height": 240, "url": "https://..."},
{"type": "screenshot", "width": 800, "height": 600, "url": "https://..."},
{"type": "screenshot", "width": 800, "height": 600, "url": "https://..."},
]
The images are referred by type
(icon, banner or screenshot)
and url
(store URL serving the corresponding image content).
The width
and height
fields may be omitted for some media (eg. media
that was uploaded before we started tracking widths and heights, or media
types for which we do not measure width and height, such as SVG.)
Snap currently can only have a single icon, a single banner and multiple screenshots.
Fetch metrics for snaps¶
- POST /dev/api/snaps/metrics¶
- Request Headers
Authorization – macaroon authorization header
- Request JSON Object
filters (list) – list of metric filters, see About metric filters
- Response JSON Object
metrics (list) – list of metrics, see The metrics response
- Status Codes
200 OK – success
400 Bad Request – error
401 Unauthorized – authentication required
403 Forbidden – authorization failed
503 Service Unavailable – internal server error
Important
In order to fetch snap metrics the request’s authentication macaroon needs to
include the package_metrics
permission. See Macaroons API for
information on how to request a macaroon with the right permissions.
About metric filters¶
The metrics endpoint allows clients to POST as many distinct metric
filters
as needed to retrieve all required metrics at once:
{
"filters": [
{"snap_id": "<SNAP-ID>", "metric_name": "installed_base_by_channel",
"start": "2016-12-18", "end": "2017-12-17"}
{"snap_id": "<SNAP-ID>", "metric_name": "installed_base_by_country",
"start": "2016-12-18", "end": "2017-12-17"}
...
]
}
Clients can retrieve multiple metrics for any snap they have write access to, with distinct intervals for each metric within a single request.
For performance purposes, each individual interval may not be longer than 1 year.
The following metrics are available:
daily_device_change: contains the 3 series representing the number of “new”, “continued” and “lost” devices with the given snap installed compared to the previous day.
installed_base_by_channel: contains one series per channel representing the number of devices with the given snap installed, channels with no data across the entire interval are omitted.
installed_base_by_country: contains one series per country representing the number of devices with the given snap installed.
installed_base_by_operating_system: contains one series per operating_system representing the number of devices with the given snap installed.
installed_base_by_version: contains one series per version representing the number of devices withe the given snap installed.
weekly_device_change: similar to the ‘daily_device_change’ metric but operates on a 7 day window. i.e. “new” contains the number of devices that were seen during the last 7 days but not in the previous 7 day and so on for “continued” and “lost”.
weekly_installed_base_by_channel: similar to the ‘installed_base_by_channel’ metric but operates in a 7 day window.
weekly_installed_base_by_country: similar to the ‘installed_base_by_country’ metric but operates in a 7 day window.
weekly_installed_base_by_operating_system: similar to the ‘installed_base_by_operating_system’ metric but operates in a 7 day window.
weekly_installed_base_by_version: similar to the ‘installed_base_by_version’ metric but operates in a 7 day window.
The metrics response¶
Each given filter will result in a corresponding metrics
entry in the
following format:
{
"metrics": [
{
"status": "OK|FAIL|NO_DATA",
"snap_id": "<SNAP-ID>",
"metric_name": "<METRIC_NAME>",
"buckets": ["<DAY-1>", ..., "<DAY-N>"],
"series": [
{
"name":"<SERIES_NAME>",
"values": [<SAMPLE-1>, ..., <SAMPLE-N>]
[, "currently_released": true|false]
},
...
]
},
...
]
}
The <SNAP_ID> and <METRIC_NAME> values are taken from the filters passed to the API in the request.
The status
field may be FAIL if there are internal problems building this
particular metric or NO_DATA if there were no samples in the given interval,
in both cases the data should be discarded by clients. Otherwise, it is OK
and the data is good to be used.
The buckets
array contains the daily steps for the given
[start
, end
] inclusive interval. It does not provide samples more
granular than daily.
Finally, the series
field contains all available timeseries in the context
of the requested metric. The series values
vector (Y axis) is built
against the metric buckets
vector (X axis). In _by_channel
series, an
extra field "currently_released": true|false
indicates whether the channel
referenced by name
is currently open in the snap’s channel map. For example,
closed channels and nonexistent channels reported by clients are marked as
"currently_released": false
.
Usage¶
Any publisher or collaborator can fetch metrics from their snaps.
First step would be to build a macaroon authorization, please follow the
instructions in Macaroons and make sure it contains package_upload
permission
The snap_ids can be obtained via the publisher WebUI or via the Accounts.
Request:
POST /dev/api/snaps/metrics HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: ...
Content-Type: application/json
{
"filters": [
{"snap_id": "wKFeK2U7Y2CB53vRJwg9MeR9bqfPvtZK",
"metric_name": "installed_base_by_channel",
"start": "2017-12-16", "end": "2017-12-17"}
]
}
Response:
In this case, only channels stable
and beta
are open,
while candidate
redirects clients to stable
.
Also, clients might report old or even nonexistent channels.
These channels are marked as "currently_released": false
.
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"metrics": [
{
"status": "OK",
"snap_id": "wKFeK2U7Y2CB53vRJwg9MeR9bqfPvtZK",
"metric_name": "installed_base_by_channel",
"buckets": ["2017-12-16"],
"series": [
{"values": [124], "name": "stable", "currently_released": true},
{"values": [270], "name": "beta", "currently_released": true},
{"values": [74], "name": "candidate", "currently_released": false},
{"values": [147], "name": "bogus", "currently_released": false}
]
}
]
}
If the macaroon used for authentication does not contain the package_upload
permission or is restricted to a set of snap packages that doesn’t include
this package, an error response will be returned
Response:
HTTP/1.1 403 FORBIDDEN
Content-Type: application/problem+json
{
"error_list": [
{
"message": "Not authorized to access the following snap_ids: <SNAP-ID>",
"code": "macaroon-permission-required"
}
],
}
In the event that the request contained invalid filters, an error response will be returned detailing the problem
Response:
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json
{
"error_list": [
{
"message": "Filter missing required keys at index 0: end",
"code": "invalid"
}
],
}
List all revisions of a snap¶
- GET /dev/api/snaps/(snap_id)/history[?arch=<arch>&page=1&size=500]¶
- Request Headers
Authorization – macaroon authorization header
- Query Parameters
arch – (optional) when set, retrieve only revisions for this architecture
- Response JSON Array of Objects
revision (int) – the revision of the build
version (string) – the version of the build
timestamp (string) – the date and time when the build was uploaded
series (list) – list of series the build was pushed to
arch (list) – list of architectures supported by the build
channels (list) – list of channels the build was released to
current_channels (list) – list of channels where this revision is currently available
- Status Codes
200 OK – success
400 Bad Request – error
401 Unauthorized – authentication required
404 Not Found – not found
The results can be optionally filtered by architecture via the corresponding query-string parameter arch.
The results are also paginated, with a default (and maximum) size of 500 entries. Clients can request smaller page sizes and further pages via query-string parameters size and page (1-indexed).
Important
There are no particular permissions required in the macaroon for retrieving revision history. Refer to the Macaroons API for information on how to request a macaroon with the right permissions.
Note
The user must be the owner or a contributor of the requested package; returns 404 Not Found
otherwise.
Usage¶
List all revisions of the snap with id some_snap_id:
Request:
GET /dev/api/snaps/some_snap_id/history HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: Macaroon root=..., discharge=...
Content-Type: application/json
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
[
{
"series": [
"16"
],
"channels": [
"beta"
],
"version": "1.1-amd64",
"timestamp": "2016-10-05T00:33:58.209",
"current_channels": [
"beta",
"edge"
],
"arch": "amd64",
"revision": 4
},
{
"series": [
"16"
],
"channels": [
"edge"
],
"version": "1.0-i386",
"timestamp": "2016-10-03T20:33:58.162",
"current_channels": [
"edge"
],
"arch": "i386",
"revision": 3
},
{
"series": [
"16"
],
"channels": [
"stable",
],
"version": "1.0-amd64",
"timestamp": "2016-10-01T10:33:58.021",
"current_channels": [
"stable",
"candidate"
],
"arch": "amd64",
"revision": 2
}
]
Filter revisions by architecture:
Request:
GET /dev/api/snaps/some_snap_id/history?arch=i386 HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: Macaroon root=..., discharge=...
Content-Type: application/json
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
[
{
"series": [
"16"
],
"channels": [
"edge"
],
"version": "1.0-i386",
"timestamp": "2016-10-03T20:33:58.162",
"current_channels": [
"edge"
],
"arch": "i386",
"revision": 3
}
]
Retrieve the publishing state of a snap¶
Retrieves the channel map tree of a snap for all related tracks and architectures. Includes the default track, if set.
- GET /dev/api/snaps/(snap_id)/state¶
- Request Headers
Authorization – macaroon authorization header
- Response JSON Object
channel_map_tree – a tree where the first layer are the different tracks, the second layer is the series, and the third series are the different architectures for the snap; each leaf of the tree (for the given track/series/architecture combination) is the corresponding channel map (refer to About channel_map for more info)
default_track – the default track set for the context snap, included only if there is a default track for it.
- Query Parameters
architecture – (optional) when set, filter results for this architecture only
- Status Codes
200 OK – success
400 Bad Request – error
401 Unauthorized – authentication required
404 Not Found – not found
Important
The request’s authentication macaroon needs to include the
package_access
permission. See Macaroons API for
information on how to request a macaroon with the right permissions.
The user must be the owner or a contributor of the requested package.
Usage¶
Retrieve the channel map for all tracks and architectures of the snap with id some_snap_id:
Request:
GET /dev/api/snaps/some_snap_id/state HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: Macaroon root=..., discharge=...
Content-Type: application/json
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"channel_map_tree": {
"latest": {
"16": {
"amd64": [
{
"revision": 4,
"version": "1.0",
"channel": "stable",
"info": "specific"
},
{
"revision": 4,
"version": "1.0",
"channel": "candidate",
"info": "specific"
},
{
"channel": "beta",
"info": "tracking"
},
{
"revision": 1,
"version": "1.0",
"channel": "edge",
"info": "specific"
}
]
}
},
"2.0": {
"16": {
"amd64": [
{
"channel": "stable",
"info": "none"
},
{
"revision": 3,
"version": "1.0",
"channel": "candidate",
"info": "specific"
},
{
"revision": 3,
"version": "1.0",
"channel": "beta",
"info": "specific"
},
{
"channel": "edge",
"info": "tracking"
}
]
}
}
},
"default_track": "2.0"
}
Filter by architecture:
Request:
GET /dev/api/snaps/some_snap_id/state?architecture=i386 HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: Macaroon root=..., discharge=...
Content-Type: application/json
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"channel_map_tree": {
"latest": {
"16": {
"i386": [
{
"info": "none",
"channel": "stable"
},
{
"info": "none",
"channel": "candidate"
},
{
"info": "none",
"channel": "beta"
},
{
"version": "8.1",
"info": "specific",
"channel": "edge",
"revision": 290
}
]
}
}
}
}
Retrieve the publishing status of a snap¶
[DEPRECATED] Please refer to the /state documentation above.
Retrieves the channel map of a snap for all related architectures.
- GET /dev/api/snaps/(snap_id)/status¶
- Request Headers
Authorization – macaroon authorization header
- Response JSON Object
object – map of {arch: channel_map} for each architecture related to the context snap: refer to About channel_map
- Query Parameters
arch – (optional) when set, retrieve the channel map for this architecture only
- Status Codes
200 OK – success
400 Bad Request – error
401 Unauthorized – authentication required
404 Not Found – not found
Important
There are no particular permissions required in the macaroon for retrieving the snap status. Refer to the Macaroons API for information on how to request a macaroon with the right permissions.
Note
The user must be the owner or a contributor of the requested package.
Usage¶
Retrieve the channel map for all architectures of the snap with id some_snap_id:
Request:
GET /dev/api/snaps/some_snap_id/status HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: Macaroon root=..., discharge=...
Content-Type: application/json
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"i386": [
{
"info": "none",
"channel": "stable"
},
{
"info": "none",
"channel": "candidate"
},
{
"info": "none",
"channel": "beta"
},
{
"info": "specific",
"version": "1.0-i386",
"channel": "edge",
"revision": 3
}
],
"amd64": [
{
"info": "specific",
"version": "1.0-amd64",
"channel": "stable",
"revision": 2
},
{
"info": "tracking",
"channel": "candidate"
},
{
"info": "specific",
"version": "1.1-amd64",
"channel": "beta",
"revision": 4
},
{
"info": "tracking",
"channel": "edge"
}
]
}
Filter by architecture:
Request:
GET /dev/api/snaps/some_snap_id/status?arch=amd64 HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: Macaroon root=..., discharge=...
Content-Type: application/json
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"amd64": [
{
"info": "specific",
"version": "1.0-amd64",
"channel": "stable",
"revision": 2
},
{
"info": "tracking",
"channel": "candidate"
},
{
"info": "specific",
"version": "1.1-amd64",
"channel": "beta",
"revision": 4
},
{
"info": "tracking",
"channel": "edge"
}
]
}
Managing snap metadata¶
The metadata endpoint allows clients to fetch and update textual attributes of a snap.
- GET /dev/api/snaps/(snap_id)/metadata¶
- Request Headers
Authorization – macaroon authorization header
- Response JSON Object
blacklist_countries – list of country codes (ISO ALPHA-2) in which the snap distribution is forbidden
categories – categories information for the snap, (see Snap categories for more details)
contact – upstream project contact URL
description – multi-line description
default_track – the default track set for the snap (null if none is set)
keywords – list of proposed keywords to facilitate search
license – SPDX 1.1 license expression for this snaps
private – whether this is snap is private or not
public_metrics_blacklist – list of public metric names not available for consumption
public_metrics_enabled – whether public metrics are enabled for this snap or not
summary – single-line summary
title – single-line text displayed as title in the snap page
unlisted – whether this snap should be part of search results or not
website – upstream project website URL
whitelist_countries – list of country codes (ISO ALPHA-2) in which the snap is exclusively allowed to be distributed
update_metadata_on_release – boolean, if set to True, automatically update metadata on subsequent releases to default_track, and stable channel. If set to False (or Null), only update the metadata via website.
- Status Codes
200 OK – success
401 Unauthorized – authentication required
404 Not Found – not found or not allowed
POST-ing to metadata allows clients to update attributes after checking for conflicts.
- POST /dev/api/snaps/(snap_id)/metadata[?conflict_on_update=false]¶
- Request Headers
Authorization – macaroon authorization header
- Request JSON Object
. – any combination of the fields mentioned above that should be updated
- Status Codes
200 OK – success
401 Unauthorized – authentication required
404 Not Found – not found or not allowed
409 Conflict – conflict identified, metadata not updated
Note
The optional conflict_on_update modifier can be set to true to flag the updated fields to be checked for conflicts on future updates. If omitted, a false value is assumed.
Whereas PUT-ing to metadata forces updates, ignoring any conflicts with fields previously updated via webui.
- PUT /dev/api/snaps/(snap_id)/metadata[?conflict_on_update=false]¶
- Request Headers
Authorization – macaroon authorization header
- Request JSON Object
. – any combination of the fields mentioned above that should be updated
- Status Codes
200 OK – success
401 Unauthorized – authentication required
404 Not Found – not found or not allowed
The binary-metadata endpoint allows fetching and updating binary attributes of a snap (icon and screenshots).
- GET /dev/api/snaps/(snap_id)/binary-metadata¶
- Request Headers
Authorization – macaroon authorization header
- Response JSON Array of Objects
type – whether it’s an icon, screenshot or banner
filename – the original filename
url – the url where the file is served
hash – the SHA-256 hex-digest of the file
- Status Codes
200 OK – success
401 Unauthorized – authentication required
404 Not Found – not found or not allowed
POST-ing to binary-metadata involves a specially-crafted multipart payload, where the info part is a JSON-encoded array of objects describing the subsequent parts, as in:
{
"info": [
{"key": "the_icon", "type": "icon", "filename": "my_icon.png", "hash": "<SHA-256>"},
{"key": "ss_1", "type": "screenshot", "filename": "ss_1.png", "hash": "<SHA-256>"},
{"key": "ss_2", "type": "screenshot", "filename": "ss_2.png", "hash": "<SHA-256>"},
]
}
Similarly to the textual endpoint, POST-ing to binary-metadata will submit the proposed files to a conflict check against files uploaded via webui (based on the “hash” attribute in info) before updating the snap information. It is an additive operation, i.e. existing icon or screenshots will not get removed as long as they are still referenced in the info structure.
- POST /dev/api/snaps/(snap_id)/binary-metadata[?conflict_on_update=false]¶
- Request Headers
Authorization – macaroon authorization header
- Form Parameters
info – JSON-encoded array of objects describing the next parts
<key> – binary metadata as described in info (form-encoded)
<...> – additional files
- Status Codes
200 OK – success
400 Bad Request – malformed payload
401 Unauthorized – authentication required
404 Not Found – snap not found or not allowed
409 Conflict – one or more files conflicts with existing data, binary-metadata not updated
415 Unsupported Media Type – unsupported media type
422 Unprocessable Entity – invalid resolution, invalid aspect ratio, too many items or file size too big
PUT-ing to binary-metadata will first remove all files related to the snap not mentioned in the info structure and then add the proposed ones.
- PUT /dev/api/snaps/(snap_id)/binary-metadata[?conflict_on_update=false]¶
- Request Headers
Authorization – macaroon authorization header
- Form Parameters
info – JSON-encoded array of objects describing the next parts
<key> – binary metadata as described in info (form-encoded)
<...> – additional files
- Status Codes
200 OK – success
400 Bad Request – malformed payload
401 Unauthorized – authentication required
404 Not Found – snap not found or not allowed
415 Unsupported Media Type – unsupported media type
422 Unprocessable Entity – invalid resolution, invalid aspect ratio, too many items or file size too big
Important
In order to fetch or update snap metadata the request’s authentication
macaroon needs to include the package_upload
permission. See
Macaroons API for information on how to request a macaroon with
the right permissions.
Usage¶
Any publisher or collaborator can fetch or update metadata from their snaps.
First step would be to build a macaroon authorization, please follow the instructions in Macaroons and make sure it contains the package_upload permission.
The snap_id can be obtained via the publisher WebUI or via the Accounts.
Updating summary (textual metadata):
POST /dev/api/snaps/(snap_id)/metadata HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: ...
Content-Type: application/json
{
"summary": "Updated summary",
}
Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"blacklist_countries": [],
"description": "Some description",
"license": "GPL-3.0",
"title": "the_title",
"whitelist_countries": [],
"summary": "Updated summary",
"contact": "http://example.com/hello",
"website": "http://example.com"
"keywords": []
}
Updating summary (textual metadata) and flag the field for conflict check:
POST /dev/api/snaps/(snap_id)/metadata?conflict_on_update=true HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: ...
Content-Type: application/json
{
"summary": "Updated summary",
}
Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"blacklist_countries": [],
"description": "Some description",
"license": "GPL-3.0",
"title": "the_title",
"whitelist_countries": [],
"summary": "Updated summary",
"contact": "http://example.com/hello",
"website": "http://example.com"
"keywords": []
}
Future updates to the summary field through the API will check the value for possible conflicts.
Updating icon (binary metadata):
POST /dev/api/snaps/(snap_id)/binary-metadata HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: ...
Content-Type: multipart/form-data; boundary=c6472a1ed83b44fbb697beab700ca8b3
--c6472a1ed83b44fbb697beab700ca8b3
Content-Disposition: form-data; name="info"
{"info": [{"key": "icon", "type": "icon", "filename": "icon.png", "hash": "<SHA-256>"}]}
--c6472a1ed83b44fbb697beab700ca8b3
Content-Disposition: form-data; name="icon"; filename="icon.png"
<binary content>
--c6472a1ed83b44fbb697beab700ca8b3--
Response:
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"hash": "<SHA-256>",
"type": "icon",
"filename": "icon.png",
"url": "http://dashboard.snapcraft.io/site_media/appmedia/2018/01/icon.png"
}
]
If the macaroon used for authentication does not contain the package_upload
permission or is restricted to a set of snap packages that doesn’t include
this package, an error response will be returned.
Response:
HTTP/1.1 403 FORBIDDEN
Content-Type: application/json
{
"error_list": [
{
"message": "Permission is required: package_upload",
"code": "macaroon-permission-required"
}
]
}
In the event that the request contained invalid fields, an error response will be returned detailing the problem.
Response:
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json
{
"error_list": [
{
"message": "Invalid field: zoing",
"code": "invalid-request"
}
]
}
Snap categories¶
The metadata categories
field is a dict containing the following:
locked
: whether categories are locked from modification by snap publishersitems
: a list of dicts having:name
: the name of the categorysince
: an ISO 8601 timestamp of when this category was assignedfeatured
: whether this category is set by store curators
Categories can be added to a snap by POST-ing categories names to the metadata endpoint.
Request:
POST /dev/api/snaps/(snap_id)/metadata HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: ...
Content-Type: application/json
{
"categories": ["utilities", "developers"]
}
Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"title": "the_title",
"summary": "Updated summary",
"contact": "http://example.com/hello",
"website": "http://example.com",
"categories": {
"locked": false,
"items": [
{"name": "developers", "since": "2016-10-05T00:33:58.209", "featured": false},
{"name": "utilities", "since": "2016-10-05T00:33:58.209", "featured": false}
]
}
}
Existing categories assignments can be cleared by POST-ing an empty list.
POST /dev/api/snaps/(snap_id)/metadata HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: ...
Content-Type: application/json
{
"categories": []
}
Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"title": "the_title",
"summary": "Updated summary",
"contact": "http://example.com/hello",
"website": "http://example.com",
"categories": {
"locked": false,
"items": []
}
}
Supervise the status of a build¶
The response from a successful hit to the Push endpoint includes a status_details_url
(see Push a snap build to the Store for more details).
The status_details_url
will return proper information about the processing of the build happening server side.
- GET /dev/api/snaps/(snap_id)/builds/(updown_id)/status¶
- Response JSON Object
processed (boolean) – true if the server side processing already finished (if false, please wait a few seconds and hit the
status_details_url
again).can_release (boolean) – true if all finished OK server side, so the client can proceed to release (see Release a snap build to a channel for more info).
code (string) – a short (but representative) string indicating concisely in which stage the server side processing is (see below for the list)
url (string) – (optional) present if the user can continue the procedure, realize some action and/or retrieve some information through the web site.
errors (list) – (optional) present only if the build processing ended in an error state, this list of error messages will help the user to fix the build (see below for format).
revision (int) – (optional) the revision of the pushed build, present only if the build binary structure was OK and a revision was assigned to it.
- Status Codes
200 OK – success
404 Not Found – not found
The code
informing in which stage the processing is can be any of the following:
being_processed
: the processing still didn’t finishprocessing_error
: there was an error processing the buildneed_manual_review
: a manual review is needed for the push to be approvedready_to_release
: free to go
The errors
field (if present) will be a list of dictionaries, each dict containing…
a
code
element, which is a short string to indicate unambiguously the type of error, and can be used by the client to present a special message or take an specific action; note that it also can benull
if the error type is generic.a
message
element, which is a short descriptive message for the error.
Close a channel for a snap package¶
- POST /dev/api/snaps/(snap_id)/close¶
- Request Headers
Authorization – macaroon authorization header
- Request JSON Object
channels (list) – list of channels to close
- Response JSON Object
channel_maps (object) – channel_map for each architecture related to the context snap.
closed_channels (list) – list of channels currently closed for the context snap.
- Status Codes
200 OK – success
400 Bad Request – error
401 Unauthorized – authentication required
403 Forbidden – authorization failed
404 Not Found – not found
Important
In order to close a channel the request’s authentication macaroon needs to
include the package_upload
permission. Refer to the Macaroons
API for information on how to request a macaroon with the right permissions.
Errors¶
The Snaps API uses conventional HTTP response codes to indicate success or failure of an API request.
In general, codes in the 2xx range indicate success, codes in the 4xx range indicate an error that resulted from the provided information (e.g. a required parameter was missing) and codes in the 5xx range indicate an error with our servers.
Here is detailed the format for API responses that end in error.
This applies to all the 4xx responses, but also to some 5xx ones (if possible, the client should be prepared to handle 5xx responses with no informational body). Note that this structure format does not apply to 2xx and 3xx responses, as those are note errors.
Important
Not all API endpoints are migrated yet to this new error format
Format¶
An error response body will contain the following field:
error_list
: a list of one or several items (never empty), each item described by…message
: a text in English describing the error that happened, ready to show to the user.code
: a short (but representative) string indicating concisely the error; it’s aimed for clients to take specific actions and react to the problem. See below for the list of existing codes.
Additionally and for backwards compatibility reasons, some other fields may be present as well, but are considered deprecated and will be removed in the near future.
No status or success indication is returned inside the response body, the client should react properly to the received HTTP return code according to its well established semantics.
Codes¶
These are the codes used in the response and their meanings:
already_claimed
: the requested snap name is already claimed.already_owned
: the user already owns the requested snap name.already_registered
: the requested snap name is already registered by someone else.assertion-creation-failed
: the assertion associated with the requested action could not be created.bad-request
: there is a problem in the structure of the request.internal-server-error
: some unexpected problem server side; this will be the code in all 5xx cases.failed-to-register
: the snap name registration failed because the snap-declaration assertion couldn’t be created.invalid
: the snap name is not valid: it should only have ASCII lowercase letters, numbers, and hyphens, and must have at least one letter; furthermore, it should not start nor end with a hyphen, it should not have two hyphens in a row, and it should have no more than 40 characters in total.invalid_choice
: current selected choice is not one of the available choices.invalid-field
: the field received in the request has format problems (e.g.: must be a number and it’s not) or value problems (e.g.: it specified a channel “foo” but that is an invalid channel for this Store).macaroon-permission-required
: the macaroon authorization is missing in the received request or not enough for it to be fulfilled.media-file-size-too-big
: the uploaded media is too big.media-invalid-aspect-ratio
: the uploaded media has an invalid aspect ratio.media-invalid-resolution
: the uploaded media has an invalid resolution.media-modified
: the media item was unexpectedly modified during validation. This should never occur.media-too-many-items
: the uploaded media type has too many items, please remove or update an existing.media-unsupported-type
: the uploaded media is in a format that is not supported.missing-field
: the request received must include a field which was not present.name-not-available-for-dispute
: the given snap name cannot be disputed because is already available.name-not-registered
: the given snap name needs to be registered before an upload attempt is made.register_window
: the user has reached their quota for registering names, they cannot register any more snap names temporarily.required
: the field in the request can’t be empty or null.reserved_name
: the requested snap name is reserved, a snap name dispute must be filed to get access to the name.resource-forbidden
: the resources in question cannot be accessed by the request authorization.resource-not-found
: one or more fields are included to specify a resource, but it is not found in the Store.resource-not-ready
: the request actions on a resource that is not ready yet for that purpose; normally something else would need to be done first on the resource before this request can be repeated.revoked_name
: the requested snap name was already owned by the user but is currently revoked.user-not-ready
: the user is not ready to issue the received request; normally some actions would need to be done in the user account before repeating the request.
Examples¶
A simple error:
{
"error_list": [{
"message": "The field 'expiration' must be an integer",
"code": "invalid-field"
}]
}
A multiple error:
{
"error_list": [{
"message": "The 'foo' field is required",
"code": "missing-field"
}, {
"message": "The 'bar' field is required",
"code": "missing-field"
}, {
"message": "The 'baz' field must not be empty",
"code": "invalid-field"
}]
}