## ReST API usage

This document describes usage of the Nuage Virtualized Services Directory (VSD) northbound ReST API. Topics covered include:

- HTTP Headers
- Managing Objects
- Push Channel
- Server Response Codes
- HTTP Headers

The Nuage VSD ReST API request uses HTTP headers for various purposes like authentication, filtering, ordering, pagination etc. HTTP headers are used instead of query parameters for several reasons, mostly because it keeps the resource URI clean, short and easy to read. Use of HTTP headers also allows the server to reply with useful metadata, like the current page number and the total number of objects, without affecting the JSON or XML objects that is sent to clients.

## Request Headers

### Content-type

The server response will be formatted in JSON. Content-Type is a required header field for HTTP POST and PUT as mentioned below to either create or modify an entity:

GET /whatever HTTP/1.1 Content-Type: application/json

### Authorization (required)

Each API call must be authenticated, so the Authorization header must be sent with each request:

GET /whatever HTTP/1.1 Authorization: $AUTHORIZATION_STRING

$AUTHORIZATION_STRING is defined below.

### X-Nuage-Organization (required)

For all API calls, this Nuage custom HTTP header is used to indicate the associated enterprise (CSP — the data center administrative enterprise — is also a standard enterprise) for the request:

GET /whatever HTTP/1.1 X-Nuage-Organization: $ENTERPRISE_NAME

### X-Nuage-Page (optional)

For a GET request, this header allows the client to ask for a given page number as all object lists are paginated:

GET /whatever HTTP/1.1 X-Nuage-Page: $PAGE_NUMBER

### X-Nuage-Filter (optional)

For a GET request, this allows the client to ask for a filtered list of objects:

GET /whatever HTTP/1.1 X-Nuage-Filter: $FILTER

The filter can be either plain text, or a predicate. How predicates work later is explained later.

### X-Nuage-OrderBy (optional)

This optional header instructs the server on how to order the results:

GET /whatever HTTP/1.1 X-Nuage-OrderBy: $ORDERING

Ordering follows the basic SQL Order By statement. For example, the X-Nuage-OrderBy: name DESC, login ASC header will result in entities ordered first by descending name, then by ascending login.

## Response Headers

### X-Nuage-Count

X-Nuage-Count indicates the total count of objects requested.

### X-Nuage-Page

X-Nuage-Page indicates the actual page number just received.

### X-Nuage-PageSize

X-Nuage-PageSize indicates the internal page size. The page size can be configured on the server. By default, it is 50 objects.

### X-Nuage-Filter

X-Nuage-Filter is an echo of the filter in the request, if any

### X-Nuage-FilterType

X-Nuage-FilterType indicates how the server has interpreted your filter. Return values are plain or predicate.

### X-Nuage-OrderBy

X-Nuage-OrderBy indicates how the objects in the reply are ordered.

## Authentication

There is no "authentication" in the sense of a strong server-side session, the VSD uses an API key that serves as an authenticated password for all subsequent calls.

This section describes how to get and use an API key.

### Getting the API key

To obtain and API key, the first step is to make a /me API call. This API call returns information about the account being used.

GET /me HTTP/1.1 X-Nuage-Organization: my company Content-Type: application/json Authorization: $AUTHORIZATION_STRING

The authorization string for the /me API MUST be formatted like the following:

$AUTHORIZATION_STRING = Basic base64($LOGIN:$PASSWORD)

Note that with Basic authentication, the password is not encrypted before transfer. This is part of the HTTP standard for Basic authentication, and is also required in order to support an LDAP internal authentication mechanism. However, all communication is over a secure channel (SSL/TLS).

NOTE: Many web browsers display Basic authentication requests and error responses in dialog boxes. Depending on the API client being developed, this may not be desirable. Instead of using the Basic authentication method, the XREST authentication method can be specified to prevent the browser from displaying a login dialog box or error dialog. The semantics are identical, but the keyword "Basic" is replaced with "XREST" in the AUTHORIZATION_STRING

The server will answer the request with:

HTTP/1.1 200 OK [ { "APIKey": "63448e28-a539-45fd-a295-639111bfc96b", "APIKeyExpiry": 1365701720072, "ID": "57526632-faba-4306-b8f2-6dde09156106", "email": "login@mycompany.com", "enterpriseID": "d43f29f5-1b61-4b51-9460-bd59394933b6", "firstName": "csproot", "lastName": "csproot", "role": "CSPROOT", "userName": "csproot" } ]

The APIKey value should be used for all subsequent API calls. The APIKey is valid until APIKeyExpiry. APIKeyExpiry is specified as a POSIX time (seconds since the epoch: 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970), and is provided as a convenience, to allow the client application to renew its API key before expiry rather than waiting for a request to fail due to API key timeout.

## Using the API key

Once an API key has been obtained, the key acts like a password for all subsequent requests. For example, to get all enterprises:

GET /enterprises HTTP/1.1 X-Nuage-Organization: my company Content-Type: application/json Authorization: $AUTHORIZATION_STRING

where the authorization string must be formatted like the following:

$AUTHORIZATION_STRING = Basic base64($LOGIN:$APIKEY)

## Managing Objects

The main philosophy of the API is to allow users to develop a simple and consistent model and feed it with the server replies without having to deal with complexities like sending only modified values, etc. For example, when requesting an enterprise, a JSON object is returned. To change an object.name, you can send only the modified attribute and its value or the entire object including the modified value to the server.

Note that the server can deal with null values. For example, when creating an enterprise, the request can have only the name and description properties with all other object attributes like ID, creationDate, owner, etc., set to null. Alternatively, the request may only send the name and description depending on preference. The main advantage is that the object model can easily be mirrored in the client.

Note that in the following examples, not all required the HTTP headers are displayed to improve readability, but those headers are still required in a properly formed request.

## Fetching Objects

To get list of objects, one uses the GET request. For example, to get all enterprises:

GET /enterprises HTTP/1.1 HTTP/1.1 200 OK X-Nuage-Count: 2 X-Nuage-OrderBy: name ASC X-Nuage-Page: 0 X-Nuage-PageSize: 50 [ { "ID": "cadb679c-26aa-4c5b-bf00-5f7b3f84954f", "creationDate": 1364937936000, "customerID": 1003, "description": "Alcatel Lucent enterprise", "lastUpdatedBy": "57526632-faba-4306-b8f2-6dde09156106", "lastUpdatedDate": 1365551832000, "name": "Alcatel Lucent", "owner": "57526632-faba-4306-b8f2-6dde09156106", "parentID": null, "parentType": null }, { "ID": "25149097-1e23-47f3-ae5e-589b4c27a158", "creationDate": 1365308033000, "customerID": 7667, "description": "Awesome stuff there", "lastUpdatedBy": "57526632-faba-4306-b8f2-6dde09156106", "lastUpdatedDate": 1365308033000, "name": "Nuage Networks", "owner": "57526632-faba-4306-b8f2-6dde09156106", "parentID": null, "parentType": null } ]

To get all groups in the company named Nuage Networks (ID: 25149097-1e23-47f3-ae5e-589b4c27a158):

GET /enterprises/25149097-1e23-47f3-ae5e-589b4c27a158/groups HTTP/1.1 HTTP/1.1 200 OK X-Nuage-Count: 3 X-Nuage-OrderBy: name ASC X-Nuage-Page: 0 X-Nuage-PageSize: 50 [ { "ID": "a296bef5-ff10-46ab-acbb-650281edbcf4", "creationDate": 1365637416000, "description": "Administrator group for enterprise Nuage Networks", "lastUpdatedBy": "57526632-faba-4306-b8f2-6dde09156106", "lastUpdatedDate": 1365637416000, "name": "Administrators", "owner": "57526632-faba-4306-b8f2-6dde09156106", "parentID": "83f56932-d2b3-4951-aca9-15bc40961370", "parentType": "enterprise", "private": true, "role": "ORGADMIN" }, { "ID": "64ddb498-bff8-4746-a8f1-27f7262f2469", "creationDate": 1365637416000, "description": "Default enterprise group that contains all its user.", "lastUpdatedBy": "57526632-faba-4306-b8f2-6dde09156106", "lastUpdatedDate": 1365637416000, "name": "Everybody", "owner": "57526632-faba-4306-b8f2-6dde09156106", "parentID": "83f56932-d2b3-4951-aca9-15bc40961370", "parentType": "enterprise", "private": false, "role": "ORGUSER" }, { "ID": "02420543-6f65-44e4-9556-5ef5002b3ede", "creationDate": 1365637416000, "description": "Network designer group", "lastUpdatedBy": "57526632-faba-4306-b8f2-6dde09156106", "lastUpdatedDate": 1365637416000, "name": "Network Designer", "owner": "57526632-faba-4306-b8f2-6dde09156106", "parentID": "83f56932-d2b3-4951-aca9-15bc40961370", "parentType": "enterprise", "private": true, "role": "ORGNETWORKDESIGNER" } ]

Querying deeper in the example above, a request to get all users in the group Administrators by issuing a request for /enterprises/$ID/groups/$ID will fail because the API only supports three levels of depth, for example,

/parents /parents/ID /parents/ID/children

To query deeper into the hierarchy, one can request:

/children /children/ID /children/ID/grandchildren

So to get all users in Nuage Networks' group named Administrators (ID: a296bef5-ff10-46ab-acbb-650281edbcf4), the request would be:

GET /groups/a296bef5-ff10-46ab-acbb-650281edbcf4/users HTTP/1.1

Note that not all objects can be queried directly. For example, one cannot ask for /users or /groups.

## Creating Objects

To create an object, use a POST request.

For example, to create a new enterprise:

POST /enterprises HTTP/1.1 { "name": "My Enterprise", "description": "Awesome new enterprise", }

To create a child object, like a group inside an enterprise:

POST /enterprises/$ENTERPRISE_ID/groups HTTP/1.1 { "name": "My Group", "description": "Super group" }

## Updating Objects

To update an object, use a PUT request.

The example below updates the enterprise description:

PUT /enterprises/$ENTERPRISE_ID HTTP/1.1 { "name": "My Enterprise", "description": "This is a new description" }

## Deleting objects

To delete an object use a DELETE request.

The example below will delete the enterprise $ENTERPRISE_ID:

DELETE /enterprises/$ENTERPRISE_ID HTTP/1.1

## Push Channel

Each request you or other users send to the server are actually pushed back to all other users (filtered by permissions) via HTTP Server Push using Long Polling. Use of the push channel is optional.

To start listening to the Push channel, send an /events call:

GET /events HTTP/1.1

This is a long polling request, with a timeout set to a certain amount of time (about 1 min). If something happens during this period, the server will send you back a push. A push can contains several events. Pushes are always grouped by events type (CREATE, DELETE, UPDATE, GRANT, REVOKE) and by entity type (enterprise, group, etc).

HTTP/1.1 200 OK { "events": [ { "entities": [ { "ID": "83f56932-d2b3-4951-aca9-15bc40961370", "creationDate": 1365637416599, "customerID": 7669, "description": "The Company", "lastUpdatedBy": "57526632-faba-4306-b8f2-6dde09156106", "lastUpdatedDate": 1365637416599, "name": "The Company", "owner": "57526632-faba-4306-b8f2-6dde09156106", } ], "entityType": "enterprise", "eventReceivedTime": 1365637416620, "type": "CREATE", "userName": "Bob" } ], "uuid": "33164796-0dab-45fd-8c21-6d1c4955b461" }

The output above indicates Bob has created a new enterprise named The Company.

If nothing happened during the timeout period, the following is returned:

HTTP/1.1 200 OK { "events": [], "uuid": "33164796-0dab-45fd-8c21-6d1c4955b461" }

Whether something happened or not, one can ask for the next event by simply resending the /event request, with the last push uuid as query parameter as follows:

GET /events?uuid=$LAST_EVENT_UUID HTTP/1.1

This UUID ensures that events are not lost if something else happened during the time between the response and the next request.

## Filtering

VSD provides a very simple, yet very advanced way to filter entities. Filter can be defined using plain text or using a predicate. The server is able to determine by itself the type of filter requested: a plain text filter or a predicate.

### Plain Text Filtering

Plain text filtering is simple and only requires setting the X-Nuage-Filter: the filter. The server will return only entities that have any of their properties containing the text the filter.

### Predicate Filtering

Predicate is a more advance way to use filters. The syntax is based on the Cocoa Predicate, and allows to build complex queries.

For example, one can send complex filters like:

X-Nuage-Filter: firstName beginswith 'john' and login contains 'admin' X-Nuage-Filter: description contains 'hello' or name contains 'world' X-Nuage-Filter: protocol >= '1024'

See Filtering, Sorting and Paging for more information on what is supported on VSD

More information about predicate syntax is available from (Apple Cocoa documentation)[https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Predicates/predicates.html#//apple_ref/doc/uid/TP40001789]

## Server Response Codes

The server replies using standard HTTP response codes.

### 2XX codes

2XX codes indicate that the request was processed:

- 200: Everything is ok, content is in the body
- 204: Everything is ok, but there is no content in the body (this is the standard reply for an update or a deletion)

### 3XX codes

3XX codes indicate the server needs more information from the client and will be offer different choices:

- 300: Multiple choices: The server needs to ask something to you before proceeding.

For example, sending a request to delete a parent object with children under it:

DELETE /domaintemplates/20a338bb-a759-4de0-bbf8-ddf76910bd32/ HTTP/1.1 Authorization: Basic Y3Nwcm9vdDo2MzQ0OGUyOC1hNTM5LTQ1ZmQtYTI5NS02MzkxMTFiZmM5NmI= X-Nuage-Organization: csp
The server will reply:
HTTP/1.1 300 Multiple Choices Content-Type: application/json { "choices": [ { "id": 1, "label": "OK" }, { "id": 0, "label": "Cancel" } ], "errors": [ { "descriptions": [ { "description": "Removing/Changing the domaintemplate will affect associated instances", "title": "This domaintemplate template is in use" } ], "property": "" } ] }

The server is presenting two choices:

- 1: "OK"
- 2: "Cancel"

To validate, resend the same request, with an HTTP query parameter set to the selected choice:

DELETE /nuage/api/v1_0/domaintemplates/20a338bb-a759-4de0-bbf8-ddf76910bd32/?responseChoice=1 HTTP/1.1 Authorization: Basic Y3Nwcm9vdDo2MzQ0OGUyOC1hNTM5LTQ1ZmQtYTI5NS02MzkxMTFiZmM5NmI= X-Nuage-Organization: csp

### 4XX codes

- 400: Bad request: something is wrong in the request.
- 401: Not authenticated (wrong password or wrong API Key).
- 403: Not authorized (request for something to which you do not have rights).
- 404: Not found (request something that does not exist).
- 409: Conflict (the requested change conflicts with existing configuration)
- 412: Precondition Failed (additional information is required before this request can succeed)

### 5XX codes

- 500: Internal server error. Error is explained in the body.