REST API

NSoT is designed as an API-first application so that all possible actions are published as API endpoints.

Dynamic Field Selection

All resource endpoints support three query parameters for controlling which fields appear in the response:

?fields=field1,field2

Sparse fieldsets — only return the specified fields.

?omit=field1,field2

Exclude fields — return everything except the listed fields.

?expand=field1,field2

Expand related objects — replace foreign-key values with the full nested object.

These parameters can be combined freely and work on both list and detail endpoints.

Fields & Omit

Return only id and hostname for devices:

$ curl -s "http://localhost:8990/api/sites/1/devices/?fields=id,hostname"

Return devices without the attributes key:

$ curl -s "http://localhost:8990/api/sites/1/devices/?omit=attributes"

Expand

By default, related objects are represented as IDs or natural keys. Use ?expand to inline the full object.

Expand the site on a device:

$ curl -s "http://localhost:8990/api/sites/1/devices/?expand=site_id"

[
    {
        "id": 1,
        "hostname": "foo-bar1",
        "site_id": {
            "id": 1,
            "name": "Test Site",
            ...
        },
        "attributes": {}
    }
]

Expand the device on an interface:

$ curl -s "http://localhost:8990/api/sites/1/interfaces/?expand=device"

Deep (dot-notation) expansion is also supported:

$ curl -s "http://localhost:8990/api/sites/1/interfaces/?expand=device.site_id"

Expandable Fields Reference

Resource

Expandable fields

Device

site_id

Network

site_id, parent_id

Interface

device, parent_id

Attribute

site_id

Unknown expand values are silently ignored.

API Reference

Interactive API reference documentation can be found by browsing to /docs/ on a running NSoT server instance.

Browsable API

Because NSoT is an API-first application, the REST API is central to the experience. The REST API can support JSON or can also be used directly from your web browser. This version is called the “browsable API” and while it doesn’t facilitate automation, it can be very useful.

Visit /api/ in your browser on your installed instance. How cool is that?!

Authentication

Two methods of authentication are currently supported.

User Authentication Header

This is referred to internally as auth_header authentication.

In normal operation NSoT is expected to be run behind an authenticating proxy that passes back a specific header. By default we expect X-NSoT-Email, though it is configurable using the USER_AUTH_HEADER setting.

The value of this header must be the user’s email and is formatted like so:

X-NSoT-Email: {email}

AuthToken

This is referred to internally as auth_token authentication.

API authentication requires the email and secret_key of a user. When a user is first created, a secret_key is automatically generated. The user may obtain their secret_key from the web interface.

Users make a POST request to /api/authenticate/ to passing email and secret_key in JSON payload. They are returned an auth_token that can then be used to make API calls. The auth_token is short-lived (default is 10 minutes and can be change using the AUTH_TOKEN_EXPIRY setting). Once the token expires a new one must be obtained.

The auth_token must be sent to the API using an Authorization header that is formatted like so:

Authorization: AuthToken {email}:{secret_key}

Requests

In addition to the authentication header above all POST, PUT, and PATCH, requests will be sent as JSON rather than form data and should include the header Content-Type: application/json

PUT requests are of note as they are expected to set the state of all mutable fields on a resource. This means if you don’t specificy all optional fields may revert to their default values, depending on the object type.

PATCH allows for partial update of objects for most fields, depending on the object type.

Partial Attribute Updates (PATCH)

When using PATCH to update a resource, attributes are merged with the existing attributes rather than replacing them entirely. This allows you to update individual attributes without needing to send the complete attribute dictionary.

  • Providing {"attributes": {"key": "value"}} will add or update that attribute while leaving all other existing attributes unchanged.

  • Setting an attribute to null will delete it: {"attributes": {"key": null}}.

  • Required attributes cannot be deleted; attempting to do so will return a validation error.

For example, if a device has {"owner": "jathan", "vendor": "juniper"} and you PATCH with {"attributes": {"vendor": "arista"}}, the result will be {"owner": "jathan", "vendor": "arista"}.

Bulk Delete

Multiple resources can be deleted in a single request by sending a DELETE request to the resource list endpoint with a JSON body containing a list of integer IDs.

Request:

DELETE /api/sites/1/devices/
Content-Type: application/json

[1, 2, 3]

Response:

HTTP 204 No Content

Each object’s permissions are validated before deletion. All IDs must be integers. If any ID is invalid or not found, the request will return an error. Duplicate IDs are automatically deduplicated.

OPTIONS will provide the schema for any endpoint.

Responses

All responses will be in format along with the header Content-Type: application/json set.

The JSON payload will be in one of two potential structures and will always contain a status field to distinguish between them. If the status field has a value of "ok", then the request was successful and the response will be available in the data field.

{
    ...
}

If the status field has a value of "error" then the response failed in some way. You will have access to the error from the error field which will contain an error code and message.

{
    "error": {
        "code": 404,
        "message": "Resource not found."
    }
}

Pagination

All responses that return a list of resources will support pagination. If the results object on the response has a count attribute then the endpoint supports pagination. When making a request against this endpoint limit and offset query parameters are supported.

The response will also include next and previous URLs that can be used to retrieve the next set of results. If there are not any more results available, their value will be null.

An example response for querying the sites endpoint might look like:

Request:

GET http://localhost:8990/api/sites/?limit=1&offset=0

Response:

{
    "count": 1,
    "next": "http://localhost:8990/api/sites/?limit=1&offset=1",
    "previous": null,
    "results": [
        {
            "id": 1
            "name": "Site 1",
            "description": ""
        }
    ]
}

Schemas

By performing an OPTIONS query on any endpoint, you can obtain the schema of the resource for that endpoint. This includes supported content-types, HTTP actions, the fields allowed for each action, and their attributes.

An example response for the schema for the devices endpoint might look like:

Request:

OPTIONS http://localhost:8990/api/devices/

Response:

HTTP 200 OK
Allow: GET, POST, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "name": "Device List",
    "description": "API endpoint that allows Devices to be viewed or edited.",
    "renders": [
        "application/json",
        "text/html"
    ],
    "parses": [
        "application/json",
        "application/x-www-form-urlencoded",
        "multipart/form-data"
    ],
    "actions": {
        "PUT": {
            "id": {
                "type": "integer",
                "required": false,
                "read_only": true,
                "label": "ID"
            },
            "hostname": {
                "type": "string",
                "required": true,
                "read_only": false,
                "label": "Hostname",
                "max_length": 255
            },
            "attributes": {
                "type": "field",
                "required": true,
                "read_only": false,
                "label": "Attributes",
                "help_text": "Dictionary of attributes to set."
            }
        },
        "POST": {
            "hostname": {
                "type": "string",
                "required": true,
                "read_only": false,
                "label": "Hostname",
                "max_length": 255
            },
            "attributes": {
                "type": "field",
                "required": false,
                "read_only": false,
                "label": "Attributes",
                "help_text": "Dictionary of attributes to set."
            },
            "site_id": {
                "type": "integer",
                "required": true,
                "read_only": false,
                "label": "Site id"
            }
        }
    }
}

Performing Set Queries

Set Queries allow you to perform complex lookups of objects by attribute/value pairs and are available on all Resources at the /api/:resource/query/ list endpoint for a given resource type.

To perform a set query you must perform a GET request to the query endpoint providing the set query string as a value to the query argument.

For example:

Request:

GET /api/devices/query/?query=vendor=juniper

Response:

HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "attributes": {
            "owner": "jathan",
            "vendor": "juniper",
            "hw_type": "router",
            "metro": "lax"
        },
        "hostname": "lax-r2",
        "site_id": 1,
        "id": 2
    },
    {
        "attributes": {
            "owner": "jathan",
            "vendor": "juniper",
            "hw_type": "router",
            "metro": "iad"
        },
        "hostname": "iad-r1",
        "site_id": 1,
        "id": 5
    }
]

The optional unique argument can also be provided in order to ensure only a single object is returned, otherwise an error is returned.

Request:

GET /api/devices/query/?query=metro=iad&unique=true

Response:

HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "attributes": {
            "owner": "jathan",
            "vendor": "juniper",
            "hw_type": "router",
            "metro": "iad"
        },
        "hostname": "iad-r1",
        "site_id": 1,
        "id": 5
    }
]

If multiple results match the query, when unique has been specified, an error will be returned.

Request:

GET /api/devices/query/?query=vendor=juniper

Response:

HTTP 400 Bad Request
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "error": {
        "message": {
            "query": "Query returned 2 results, but exactly 1 expected"
        },
        "code": 400
    }
}