.. _account-api: ======== Accounts ======== Introduction ============ The *Account API* provides endpoints to handle user account information. The *Account API* is exposed at the following base URLs: * Staging: https://dashboard.staging.snapcraft.io/dev/api * Production: https://dashboard.snapcraft.io/dev/api Response Format --------------- JSON_ will be returned in all responses from the API, including `errors`_. .. _JSON: http://www.json.org 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**: .. sourcecode:: http HTTP/1.1 403 FORBIDDEN Content-Type: application/json { "error_list": [{ "message": "Developer has not signed agreement.", "code": "user-not-ready" }] } **Response**: .. sourcecode:: http 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: .. http:get:: /dev/api/account :reqheader Authorization: macaroon authorization header :>json account-keys: list of associated ``account-key`` objects with the following attributes: ``name``, ``public-key-sha3-384``, ``since`` and ``until`` :>json display-name: the user's full name :>json email: the user's email address :>json id: the user's account ID :>json validation: the user's identity validation status :>json snaps: map of accessible snap-names keyed by ``series`` then ``snap-name`` :>json stores: list of accessible store objects with corresponding roles :>json username: the user's store username :>json account_id: **DEPRECATED** use ``id`` :>json account_keys: **DEPRECATED** use ``account-keys`` :>json displayname: **DEPRECATED** use ``display-name`` :>json namespace: **DEPRECATED** use ``username`` :>json openid_identifier: the user's OpenID identifier (**DEPRECATED** part of ancient workflow scheduled to be removed) :>json short_namespace: **DEPRECATED** use ``username`` :status 200: success :status 400: error :status 500: could not create the account assertion :status 501: account assertions are currently disabled .. 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. .. sourcecode:: http 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": "", "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": "", "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": "", "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. .. sourcecode:: http 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: .. http:patch:: /dev/api/account :reqheader Authorization: macaroon authorization header :>json short_namespace: the user's new store username :status 204: success :status 400: error :status 401: unauthorized :status 403: user has not signed agreement .. important:: In order to set the store username, the request's authorization macaroon must include the ``edit_account`` permission. Refer to the :ref:`macaroon-api` 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. .. http:post:: /dev/api/account/account-key :reqheader Authorization: macaroon authorization header :json account_key: the headers of the resulting `account-key` assertion :status 200: success :status 400: error :status 500: internal failure to create ``account-key`` assertion :status 501: account-key-request assertions are currently disabled 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: .. sourcecode:: json { "error_list": [{ "message": "The account-key-request assertion is not valid.", "code": "invalid-field" }] } A multiple error: .. sourcecode:: json { "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" }] }