# API Introduction

CloudAPI exposes a REST API over HTTPS. You can work with the REST API by either calling it directly via tooling you already know about (such as curl, et al), or by using the CloudAPI CLIs and SDKs from Joyent. The node-triton CloudAPI SDK & CLI is available as an npm module, which you can install with:

```
npm install triton
```

Alternatively, there is the more stable and feature-complete node-smartdc:

```
npm install smartdc
```

Although node-triton has fewer features -- for now -- it will continue to receive the most development effort and future support. node-smartdc is in maintenance.

The rest of this document will show all APIs in terms of both the raw HTTP specification, the CLI commands, and sometimes the node-smartdc SDK.

### Issuing Requests <a href="#issuing-requests" id="issuing-requests"></a>

All HTTP calls to CloudAPI must be made over TLS, and requests must carry at least two headers (in addition to standard HTTP headers): `Authorization` and `Api-Version`. The details are explained below. In addition to these headers, any requests requiring content must be sent in an acceptable scheme to CloudAPI. Details are also below.

#### Content-Type <a href="#content-type" id="content-type"></a>

For requests requiring content, you can send parameters encoded with `application/json`, `application/x-www-form-urlencoded` or `multipart/form-data`. Joyent recommends `application/json`. The value of the `Accept` header determines the encoding of content returned in responses. CloudAPI supports `application/json` response encodings only.

For example, all of the following are valid calls:

Query String (on the uri):

```
POST /my/keys?name=rsa&key=... HTTP/1.1
Host: joyent.com
Authorization: ...
Content-Length: 0
```

Form encoded in the body:

```
POST /my/keys HTTP/1.1
Host: joyent.com
Authorization: ...
Content-Type: application/x-www-form-urlencoded
Content-Length: 123

name=rsa&key=...
```

JSON in the body:

```
POST /my/keys HTTP/1.1
Host: joyent.com
Authorization: ...
Content-Type: application/json
Content-Length: 123

{"name":"rsa","key":"..."}
```

#### Authorization <a href="#authorization" id="authorization"></a>

All API calls to CloudAPI require an Authorization header, which supports multiple ["schemes"](http://tools.ietf.org/html/rfc2617). Currently CloudAPI supports only one Authentication mechanism due to PCI compliance restrictions:

* HTTP Signature Authentication Scheme. This Scheme is outlined in [Appendix B](https://apidocs.joyent.com/cloudapi/#appendix-b-http-signature-authentication).

In order to leverage HTTP Signature Authentication, only RSA signing mechanisms are supported, and your keyId must be equal to the path returned from a [ListKeys](https://apidocs.joyent.com/cloudapi/#ListKeys) API call. For example, if your Triton login is `demo`, and you've uploaded an RSA SSH key with the name `foo`, an Authorization header would look like:

```
Authorization: Signature keyId=/demo/keys/foo,algorithm="rsa-sha256" ${Base64(sign($Date))}
```

The default value to sign for CloudAPI requests is simply the value of the HTTP `Date` header. For more information on the Date header value, see [RFC 2616](http://tools.ietf.org/html/rfc2616#section-14.18). All requests to CloudAPI using the Signature authentication scheme *must* send a Date header. Note that clock skew will be enforced to within 300 seconds (positive or negative) from the value sent.

Full support for the HTTP Signature Authentication scheme is provided in both CloudAPI SDKs; an additional reference implementation for Node.js is available in the npm `http-signature` module, which you can install with:

```
npm install http-signature
```

#### Using cURL with CloudAPI <a href="#using-curl-with-cloudapi" id="using-curl-with-cloudapi"></a>

Since [cURL](http://curl.haxx.se/) is commonly used to script requests to web services, here's a simple Bash function you can use to wrap cURL when communicating with CloudAPI:

```
function cloudapi() {
    local now=$(date -u '+%a, %d %h %Y %H:%M:%S GMT')
    local signature=$(echo -n "$now" | openssl dgst -sha256 -sign ~/.ssh/id_rsa | openssl enc -e -a | tr -d '\n')
    local url="$SDC_URL$1"
    shift

    curl -s -k -i \
        -H 'Accept: application/json' \
        -H "accept-version: ~8" \
        -H "Date: $now" \
        -H "Authorization: Signature keyId=\"/$SDC_ACCOUNT/keys/id_rsa\",algorithm=\"rsa-sha256\" $signature" \
        "$@" "$url"
    echo
}
```

You may need to alter the path to your SSH key in the above function, as well as the path its public-key is saved under in Triton.

With that function, you could just do:

```
cloudapi /my/machines
```

### CloudAPI HTTP Responses <a href="#cloudapi-http-responses" id="cloudapi-http-responses"></a>

CloudAPI returns all response objects as `application/json` encoded HTTP bodies. In addition to the JSON body, all responses have the following headers:

| **Header**    | **Description**                                         |
| ------------- | ------------------------------------------------------- |
| Date          | When the response was sent (RFC 1123 format)            |
| Api-Version   | The exact version of the CloudAPI server you spoke with |
| Request-Id    | A unique id for this request; you should log this       |
| Response-Time | How long the server took to process your request (ms)   |

If there is content, you can expect:

| **Header**     | **Description**                                             |
| -------------- | ----------------------------------------------------------- |
| Content-Length | How much content, in bytes                                  |
| Content-Type   | Formatting of the response (almost always application/json) |
| Content-MD5    | An MD5 checksum of the response; you should check this      |

#### HTTP Status Codes <a href="#http-status-codes" id="http-status-codes"></a>

Your client should check for each of the following status codes from any API request:

| **Code** | **Description**          | **Details**                                                                    |
| -------- | ------------------------ | ------------------------------------------------------------------------------ |
| 400      | Bad Request              | Invalid HTTP Request                                                           |
| 401      | Unauthorized             | Either no Authorization header was sent, or invalid credentials were used      |
| 403      | Forbidden                | No permissions to the specified resource                                       |
| 404      | Not Found                | Resource was not found                                                         |
| 405      | Method Not Allowed       | Method not supported for the given resource                                    |
| 406      | Not Acceptable           | Try sending a different Accept header                                          |
| 409      | Conflict                 | Most likely invalid or missing parameters                                      |
| 413      | Request Entity Too Large | You sent too much data                                                         |
| 415      | Unsupported Media Type   | Request was encoded in a format CloudAPI does not understand                   |
| 420      | Slow Down                | You're sending too many requests too quickly                                   |
| 449      | Retry With               | Invalid Version header; try with a different Api-Version string                |
| 500      | Internal Error           | An unexpected error occurred; see returned message for more details.           |
| 503      | Service Unavailable      | Either there's no capacity in this datacenter, or it's in a maintenance window |

#### Error Responses <a href="#error-responses" id="error-responses"></a>

In the event of an error, CloudAPI will return a standard JSON error response object in the body with the scheme:

```
{
  "code": "CODE",
  "message": "human readable string"
}
```

Where the code element is one of:

| **Code**           | **Description**                                       |
| ------------------ | ----------------------------------------------------- |
| BadRequest         | You sent bad HTTP                                     |
| InternalError      | Something went wrong in Triton                        |
| InUseError         | The object is in use and cannot be operated on        |
| InvalidArgument    | You sent bad arguments or a bad value for an argument |
| InvalidCredentials | Authentication failed                                 |
| InvalidHeader      | You sent a bad HTTP header                            |
| InvalidVersion     | You sent a bad Api-Version string                     |
| MissingParameter   | You didn't send a required parameter                  |
| NotAuthorized      | You don't have access to the requested resource       |
| RequestThrottled   | You were throttled                                    |
| RequestTooLarge    | You sent too much request data                        |
| RequestMoved       | HTTP Redirect                                         |
| ResourceNotFound   | What you asked for wasn't found                       |
| UnknownError       | Something completely unexpected happened!             |

Clients are expected to check HTTP status code first, and if it's in the 4xx range, they can leverage the codes above.<br>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.mnx.io/cloudapi/api-introduction.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
