============= General Notes ============= Introduction ------------ API endpoint ------------ Given a server running the CloudSigma API it will be available on the following base URL e.g.:: https://{loc}.cloudsigma.com/api/2.0/ Where {loc} is a subdomain for a specific location. In the rest of the documentation the URL's will be given relative to that base. Currently the following CloudSigma location endpoints are available: +---------------------------+-----------------------------------------+ | Location | API endpoint | +===========================+=========================================+ | Zurich, Switzerland | ``https://zrh.cloudsigma.com/api/2.0/`` | +---------------------------+-----------------------------------------+ | Las Vegas, United States | ``https://lvs.cloudsigma.com/api/2.0/`` | +---------------------------+-----------------------------------------+ API Versions ------------ The API version is embedded into the URL. The currently active one is '2.0', e.g. :: https://lvs.cloudsigma.com/api/2.0/ General URL Format ------------------ API URLs have the following general format:: https://{api_endpoint}/api/{api_version}/{resource}/{object_id}/action/?{get_request_parameters} Here is a list of the possible URL formats relative to the base url (https://{api_endpoint}/api/{api_version}): **/{resource}/** These URLs usually point to a list of resources like */servers/* or */drives/*. It may also point to a single resource object such as */profile/*. **/{resource}/{object_id}/** These URLs point to a single resource from a list of resources, for example a single server URL can be: */servers/6e5ceaaa-0cf8-417a-bf47-53e56d4fcaaa/* **/{resource}/{object_id}/action/?do={action_name}** Some objects have actions. The name of the action is specified in the 'do=' GET parameter. For example a server object has a start action which is called on the following URL: */servers/6e5ceaaa-0cf8-417a-bf47-53e56d4fcaaa/action/?do=start* Authentication -------------- The API supports the following authentication methods : * HTTP Basic * HTTP Digest * Cookie based authentication for web/browser based clients. HTTP Basic Auth --------------- HTTP Basic Authentication is done with the *Authorization* header. The value of the header is ``Basic base64_encode({user email}:{password})``. For example a user with email *user.email@domain.tld* with password *pass123* results in a value of *user.email@domain.tld:pass123*, which when encoded in Base64 would result in the following header:: Authorization: Basic dXNlci5lbWFpbEBkb21haW4udGxkOnBhc3MxMjM= See :rfc:`2617#section-2` for more detailed discussion of HTTP Basic Authentication. Digest Access Authentication ---------------------------- In order to use digest authentication, clients should make the request without any authentication, which will result in a ``401 Unauthorized`` response. The response will contain a challenge in the ``WWW-Authenticate`` header which looks like:: WWW-Authenticate: Digest nonce="1363185031.81:FCF2:443b657bfd1a7340a0841c704d93a579", realm="users", algorithm="MD5", opaque="d7d89a75f4f6e3044626c6c251456e6b401401e7", qop="auth" Three hashes (we call them HA1 and HA2 and RESPONSE in the example) need to be calculated to generate the ``response`` to the challenge and authenticate. The API uses md5 hashing algorithm (*algorithm="MD5"*) and "auth" quality of protection (*qup="auth"*):: HA1 = MD5({username}:{realm}:{password}) HA2 = MD5({method}:{uri}) RESPONSE = MD5(HA1:{nonce}:{nc}:{cnonce}:{qop}:HA2) The values for *realm*, *nonce*, and *qop* are given in the challenge header ``WWW-Authenticate``. The client has to provide the *username*, *password*, *cnonce*, and *nc*. *cnonce* or client nonce is a random value generated by the client and *nc* or nonce counter is a hexadecimal counter which should be incremented with each subsequent request. The client should send an ``Authorization`` header which contains all the values from the ``WWW-Authenticate`` response header, together with the following values *username*, *uri*, *cnonce*, *nc*, and *response*, which contains the calculated ``RESPONSE`` hash. In the example above a user with an email *user.email@domain.tld*, and with password *pass123* may send the following ``Authorization`` header in the next request:: Authorization: Digest username="user.email@domain.tld", realm="users", nonce="1363188235.48:54A3:135f43a8227a1ca54c91da95b0111802", uri="/api/2.0/servers/", cnonce="MDI4Nzcx", nc=00000001, qop=auth, response="06238b01fabaeea8d7923c502a037bb5", opaque="5f0604df80b0c2d09330e802ed47ba5288e5440c", algorithm="MD5" For more information on Digest access authentication see :rfc:`2617#section-3` or the wikipedia article on `Digest Access Authentication `_. Cookie-based Authentication --------------------------- Browser-based clients can use cookie authentication. The authentication is token in stored in the ``sessionid`` cookie. All requests except *GET* and *OPTIONS* require also a **CSRF token**. The CSRF token is needed to prevent `Cross-site Request Forgery `_. It is specified as a custom header ``X-CSRFToken`` on each request. The value for the CSRF token is set by the server in the ``csrftoken`` cookie. To obtain a ``sessionid`` and ``csrftoken`` cookies, make a login request with a *POST* to ``/api/2.0/accounts/action/?do=login`` with an object containing "username" and "password" fields with the corresponding username and password values: .. sourcecode:: http POST /api/2.0/accounts/action/?do=login HTTP/1.1 Content-Type:application/json {"username": "user.email@domain.tld", "password":"pass123"} The response will contain the two cookies:: Set-Cookie: csrftoken=J24Zr4nEcxZcHtdoaNG02WiWoA0qXFg5; expires=Tue, 11-Mar-2014 15:47:14 GMT; Max-Age=31449600; Path=/ Set-Cookie: sessionid=c38919b96789c3a12c6c204676d63308; expires=Tue, 26-Mar-2013 15:47:14 GMT; httponly; Max-Age=1209600; Path=/ All subsequent requests should contain both ``sessionid`` and ``csrftoken`` in the ``Cookie`` header and ``csrftoken`` in the ``X-CSRFToken`` header:: Cookie: sessionid=c38919b96789c3a12c6c204676d63308; csrftoken=J24Zr4nEcxZcHtdoaNG02WiWoA0qXFg5 X-CSRFToken: J24Zr4nEcxZcHtdoaNG02WiWoA0qXFg5 To logout (invalidate current ``sessionid`` and ``csrftoken``), one needs to send a *POST* to ``/api/2.0/accounts/action/?do=login`` with an empty object: .. sourcecode:: http POST /api/2.0/accounts/action/?do=logout HTTP/1.1 Content-Type:application/json {} Data Format (Content Types) --------------------------- The API supports both the JSON and XML data formats. By default JSON is used. The request format is specified using the Content-Type header and is required for operations that have a request body. The response format can be specified in requests using the Accept header. The response contains a Content-Type header specifying the data format returned. The following table summarizes the request and response headers concerning data format: +---------------+----------------+----------------+ | Header name | Specified in | Specified in | | | Request | Response | +===============+================+================+ | Content-Type | applies to | applies to | | | request body | response body | +---------------+----------------+----------------+ | Accept | applies to | not applicable | | | response body | | +---------------+----------------+----------------+ The values which can be used for data format headers are: +----------+---------------------------------+ | Encoding | Header value | +==========+=================================+ | JSON | ``application/json`` or ``*/*`` | +----------+---------------------------------+ | XML | ``application/xml`` | +----------+---------------------------------+ You can also use a URI parameter **?format=json** or **?format=xml** to specify the content type of the response, when sending a **GET** request. This is useful for querying the API manually (via web browser) and should not be used when sending requests programmatically. In case both the Content-Type and URI parameter are used, the URI parameter has precedence. In case there are conflicting URI parameters, the last specified parameter takes precedence. In case of both ``application/json`` and ``application/xml`` are specified in an ``Accept`` header, JSON is returned. If the ``Accept`` header contains both ``*/*`` and ``application/xml`` or ``application/json``, the ``*/*`` is ignored and the more specific content type is used. Content Compression ------------------- Response body data may be compressed with gzip compression in order to minimize the amount of data being transferred over the wire. To request response body compression use the Accept-Encoding header on the request. The response will contain a Content-Encoding header specifying the gzip compression algorithm. +----------+------------------+-------+ | Type | Header | Value | +==========+==================+=======+ | Request | Accept-Encoding | gzip | +----------+------------------+-------+ | Response | Content-Encoding | gzip | +----------+------------------+-------+ Request Methods ---------------- The API uses different HTTP request methods for different types of operations. In order to list the available HTTP request methods on a URL use an **OPTIONS** method request on it. **Example**: Request: .. sourcecode:: http OPTIONS /2.0/servers/ HTTP/1.1 Response: .. sourcecode:: http HTTP/1.0 200 OK GET,PUT,DELETE,POST The following table specifies that meanings of HTTP methods, which can be used by API clients: :GET: Retrieve a resource or a list of resources. :PUT: Update an existing resource. **PUT** implies an idempotent action (a request, which when repeated with the same arguments will always yield the same result). :POST: Create a resources, or do an action on an object (like do start action on a server). **POST** is used for non-idempotent request (requests, which may have different results if repeated multiple times, even if the input data is the same). :DELETE: Delete a resource. :OPTIONS: Get a comma separated list of the supported HTTP methods on a URL. Response Status Codes ----------------------- The API uses the standard HTTP status code classes, where a code from 200 to 299 signifies success. Request errors have status codes between 400 and 499, and server side errors have codes between 500 and 599. The following status codes are returned by the API: **Success Status Codes**: :200: *OK*. Successful request. :201: *Object Created*. This request is used for calls which create new objects, such as create drive or create server. The Location response header contains the URI of the newly created object. :202: *Accepted*. This header is used for long-running or asynchronous operations such as starting a server or cloning a drive. The header also implies that the request the request may not succeed and may be canceled :204: *No Content*. The request was successful an there is no content in response body. This status is used for successful DELETE requests. Clients should be aware to not parse the body as it is empty and is not a valid JSON or XML document. API errors usally contain a body which describes the error. Check the :doc:`errors` section for explanation of the error message format. **Request Error Status Codes**: :400: *Bad Request*. This status means that there is an error in the request. The request error may be data format error (non-valid JSON or XML) or an invalid value. :401: *Unauthorized*. The provided credentials are incorrect or missing. This response status is normal part of digest authentication in which case, the response will contain WWW-Authenticate header with an authentication challenge. :402: *Payment Required*. This error means there are not enough funds in the account to complete action. It occurs when trying to buy subscription without having enough funds in the account, or when trying to start a server without having enough funds for burst usage of 5 days. :403: *Forbidden*. The provided credentials are correct but the user is not permitted to complete the action. This status is used for either "permission" or "operation not allowed" error. :404: *Not Found*. The requested object does not exist. This error occurs when requesting non-existing resource. The resource may have never been created, or it may be deleted. :405: *Method Not Allowed*. This error occurs, when using incorrect HTTP method on an URL. For example DELETE requests are not allowed on /profile/ URL, and will return a *405* status. :406: *Not Acceptable*. This error occurs when the content type requested through the ``Accept`` header is not supported by the API. The content types supported by the API are ``application/json``, ``application/xml``, and ``*/*``, which defaults to ``application/json``. If the ``Accept`` header of the request does not contain any of this content types, a ``406`` status will be returned. **System Error Status Code** :500: *Internal Server Error*. This status means a system error has occurred. Please contact support if you encounter such an error. :503: *Service Unavailable*. This status means that the system temporarily cannot fulfil request. This status is returned for concurrent updates, when the client makes multiple concurrent requests which try to update the same values, or when the system is out of capacity. Rate Limits ----------- The API server needs to impose call-rate limits to protect the infrastructure from being maliciously overloaded. We can also think of different rated of GET, PUT, POST and DELETE methods as usually these will vary widely in the load impacted on the system. +------------+------------+------------+ | Verb | URI RegEx | Limit | +============+============+============+ | **POST** | .* | 100 / min | +------------+------------+------------+ | **POST** | ^/servers/ | 500 / day | +------------+------------+------------+ | **PUT** | .* | 100 / min | +------------+------------+------------+ | **GET** | .* | 100 / min | +------------+------------+------------+ | **DELETE** | .* | 1000 / min | +------------+------------+------------+ *Note: these limits may change in future* .. _permitted-characters: Permitted characters -------------------- The API accepts Unicode characters, with the recommended charset being UTF-8. The only special case is ``\0``, which terminates the string.