Accounts

Introduction

The Account API provides endpoints to handle user account information.

The Account API is exposed at the following base URLs:

Response Format

JSON will be returned in all responses from the API, including errors.

Reference

Obtaining account information

The user needs to sign the Terms Of Service and set the Store username (only if is not already set via previous authentication), before they can read their account information via the API. 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"
  }]
}

Response:

HTTP/1.1 403 FORBIDDEN
Content-Type: application/json

{
  "error_list": [{
    "message": "Developer profile is missing store username.",
    "code": "user-not-ready"
  }]
}

After accepting the ToS (and maybe setting their username), users may access the API for obtaining account information:

GET /dev/api/account
Request Headers
Response JSON Object
  • account-keys – list of associated account-key objects with the following attributes: name, public-key-sha3-384, since and until

  • display-name – the user’s full name

  • email – the user’s email address

  • id – the user’s account ID

  • validation – the user’s identity validation status

  • snaps – map of accessible snap-names keyed by series then snap-name

  • stores – list of accessible store objects with corresponding roles

  • username – the user’s store username

  • account_idDEPRECATED use id

  • account_keysDEPRECATED use account-keys

  • displaynameDEPRECATED use display-name

  • namespaceDEPRECATED use username

  • openid_identifier – the user’s OpenID identifier (DEPRECATED part of ancient workflow scheduled to be removed)

  • short_namespaceDEPRECATED use username

Status Codes

Important

The ID and its corresponding account assertion will be automatically generated on the first access.

The snaps structure list all names currently registered or under review for which the context account is the publisher or one of the collaborators.

GET /dev/api/account HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: ...

HTTP/1.1 200 OK
Content-Type: application/json

{
  "...": "...",
  "snaps": {
    "16": {
      "hello-published": {
        "status": "Approved",
        "price": null,
        "since": "2016-07-04T23:37:52Z",
        "snap-id": "<snap-id>",
        "store": "Global",
        "private": false,
        "icon_url": null,
        "publisher": {
          "id": <...>,
          "display-name": <...>,
          "username": <...>,
          "validation": "unproven"
        },
        "latest_comments": [],
        "latest_revisions": []
      },
      "hello-collaborator": {
        "status": "Approved",
        "price": null,
        "since": "2016-07-04T21:37:52Z",
        "snap-id": "<snap-id>",
        "store": "John Doe Store",
        "private": true,
        "icon_url": "https://dashboard.snapcraft.io/site_media/appmedia/2018/01/hello.png",
        "publisher": {
          "id": <...>,
          "display-name": <...>,
          "username": <...>,
          "validation": "verified"
        },
        "latest_comments": [],
        "latest_revisions": [
          {'revision': 1,
           'since': '2016-10-02T00:00:00Z',
           'version': '1.0',
           'status': 'Published',
           'architectures': ['amd64'],
           'channels': ['edge']},
        ]
      },
      "hello-disputing": {
        "status": "DisputePending",
        "price": null,
        "since": "2017-07-04T23:37:52Z",
        "snap-id": "<snap-id>",
        "store": "Global",
        "private": false,
        "icon_url": null,
        "publisher": {
          "id": <...>,
          "display-name": <...>,
          "username": <...>,
          "validation": "unproven"
        },
        "latest_comments": [
          {'author': {
             "id": <...>,
             "display-name": <...>,
             "username": <...>,
             "validation": "unproven"
           },
           "since": "2017-07-05T00:00:00Z",
           "reason": "Reviewer comment",
           "comment": "Nope!"}
        ],
        "latest_revisions": []
      },
    }
  }
}

latest_comments contains up to 5 comments in the context of an under-review or revoked name context:

  • reason: one of the following identifiers ‘Registrant comment’, ‘Reviewer comment’ or ‘Revoked’

  • since: timestamp when the comment was created (RFC3339)

  • author: reference to the user responsible for the comment (id, username, display-name and validation)

  • comment: the comment text

Comments are ignored once the name is approved, the list will be always empty.

latest_revisions contains up to 5 snap revisions uploaded to the store:

  • revision: unique incremental integer assigned by the store

  • since: timestamp of the snap revision upload (RFC3339)

  • version: user-defined version string

  • status: upload status, one of: ‘Published’, ‘ReviewPending’ and ‘Rejected’

  • architectures: the snap architectures where this revision should be available for installation

  • channels: the snap channels where this revision should be available for installation

Both, latest_comments and latest_revision are ordered in reverse chronological order.

The stores list contains objects representing each store the context account can access.

GET /dev/api/account HTTP/1.1
Host: dashboard.snapcraft.io
Authorization: ...

HTTP/1.1 200 OK
Content-Type: application/json

{
  "...": "...",
  "stores": [
    {
      "name": "Global",
      "id": "ubuntu",
      "roles": ["access"]
    },
    {
      "name": "My Awesome Store",
      "id": "awesome-101",
      "roles": ["access", "review", "admin"]
    },
    {
      "name": "Friend's Store",
      "id": "asking-for-a-friend",
      "roles": ["access", "view"]
    },
  ]
}

The store roles field can a combination of the following items:

  • access: can register snap names, upload and release snap revisions in context store

  • review: can approve uploaded revisions that did not pass automatic review in the context store

  • admin: can edit the settings and edit user roles of the context store

  • view: can view the all snaps registered to the context store (not only the ones directly associated with the context account)

Updating account information

Users may also set their store username:

PATCH /dev/api/account
Request Headers
Response JSON Object
  • short_namespace – the user’s new store username

Status Codes

Important

In order to set the store username, the request’s authorization macaroon must include the edit_account permission. Refer to the Macaroons for information on how to request a macaroon with the right permissions.

Note

At present, the store username may only be set using this API if it was not already set.

Register an account key

Register an OpenPGP key to be used to certify other assertions in the store. For example, this may be used by developers to sign snap-build assertions.

POST /dev/api/account/account-key
Request Headers
Request JSON Object
  • account_key_request (string) – a self-signed account-key-request assertion

Response JSON Object
  • account_key – the headers of the resulting account-key assertion

Status Codes

Errors

The Account 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 not errors.

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:

  • assertion-creation-failed: the request asked for an assertion to be created, but this failed.

  • bad-request: there is a problem in the structure of the request.

  • feature-disabled: the request cannot be fulfilled because the feature is currently disabled on the server side.

  • internal-server-error: some unexpected problem server side.

  • 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 contains an account-key-request assertion which does not match the user’s account).

  • macaroon-permission-required: the macaroon authorization is missing in the received request or not enough for it to be fulfilled.

  • missing-field: the request received must include a field which was not present.

  • 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 account-key-request assertion is not valid.",
     "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"
  }]
}