# Working with the Resources API

## Overview

The SignalK specification defines a number of resources (routes, waypoints, notes, regions & charts) each with its own path under the root `resources` path (e.g. `/signalk/v2/api/resources/routes`).

Additionally, the `/resources` path can be used to host other user defined resource types, each grouped within its own folder (e.g. `/signalk/v2/api/resources/fishingZones`).

The Resources API validates requests to these resource paths and passes them to a Resource Provider plugin for storage and retrieval.

Client applications can then use `HTTP` requests to these paths to store (`POST`, `PUT`), retrieve (`GET`) and remove (`DELETE`) resource entries.

Note: the ability to store resource entries is controlled by the server security settings so client applications may need to authenticate for write / delete operations to complete successfully.

### Retrieving Resources

Resource entries are retrived by submitting an HTTP `GET` request to the relevant path.

For example to return a list of all available routes

    HTTP GET 'http://hostname:3000/signalk/v2/api/resources/routes'

or alternatively fetch a specific route.

    HTTP GET 'http://hostname:3000/signalk/v2/api/resources/routes/94052456-65fa-48ce-a85d-41b78a9d2111'

A filtered list of entries can be retrieved based on criteria such as:

- being within a bounded area
- distance from vessel
- total entries returned
- map zoom level

by supplying a query string containing `key | value` pairs in the request.

Example 1: Retrieve waypoints within 50km of the vessel. Note: distance in meters value should be provided.

    HTTP GET 'http://hostname:3000/signalk/v2/api/resources/waypoints?distance=50000'

Example 2: Retrieve up to 20 waypoints within 90km of the vessel.

    HTTP GET 'http://hostname:3000/signalk/v2/api/resources/waypoints?distance=90000&limit=20'

Example 3: Retrieve waypoints within a bounded area. Note: the bounded area is supplied as bottom left & top right corner coordinates in the form swLongitude,swLatitude,neLongitude,neLatitude.

    HTTP GET 'http://hostname:3000/signalk/v2/api/resources/waypoints?bbox=[-135.5,38,-134,38.5]'

_Example 4: Return notes for display on a map view at zoom level 5.

    HTTP GET 'http://hostname:3000/signalk/v2/api/resources/notes?zoom=5'

It is up to the provider to determine which resource entries are returned for any given zoom level. As a guide we recommend alignment with the criteria in the following document: https://wiki.openstreetmap.org/wiki/Zoom_levels_.

### Deleting Resources

Resource entries are deleted by submitting an HTTP `DELETE` request to a path containing the `id` of the resource to delete.

Example: Delete from storage the route with id `94052456-65fa-48ce-a85d-41b78a9d2111`.

    HTTP DELETE 'http://hostname:3000/signalk/v2/api/resources/routes/94052456-65fa-48ce-a85d-41b78a9d2111'

### Creating / updating Resources

Creating a new resource entry:

Resource entries are created by submitting an HTTP `POST` request to a path for the relevant resource type.

    HTTP POST 'http://hostname:3000/signalk/v2/api/resources/routes' {resource_data}

The new resource is created and its `id` (generated by the server) is returned in the response message.

    {
      "state": "COMPLETED",
      "statusCode": 200,
      "id": "94052456-65fa-48ce-a85d-41b78a9d2111"
    }

Note: Each `POST` will generate a new `id` so if the resource data remains the same duplicate resources will be created.

Updating a resource entry:

Resource entries are updated by submitting an HTTP `PUT` request to a path for the relevant resource type that includes the resource `id`.

    HTTP PUT 'http://hostname:3000/signalk/v2/api/resources/waypoints/94052456-65fa-48ce-a85d-41b78a9d2111'

As the `PUT` request replaces the record with the supplied `id`, the submitted resource data should contain a complete record for the resource type being written.

Each resource type has a specific set of attributes that are required to be supplied before the resource entry can be created or updated.

If either the submitted resource data or the resource id are invalid then the operation is aborted._

Note: the submitted resource data is validated against the OpenApi schema definition for the relevant resource type.

## Multiple Providers for a Resource Type

The Resources API will allow for multiple plugins to register as a provider for the same resource type.

When this scenario occurs the server services request in the following ways:

Listing entries:

When a list of resources is requested

for example:

    HTTP GET 'http://hostname:3000/signalk/v2/api/resources/waypoints'

each registered provider will be asked to return matching entries and the server aggregates the results and returns them to the client.

Requests for specific resources:

When a request is received for a specific resource

for example:

    HTTP GET 'http://hostname:3000/signalk/v2/api/resources/waypoints/94052456-65fa-48ce-a85d-41b78a9d2111'

    HTTP PUT 'http://hostname:3000/signalk/v2/api/resources/waypoints/94052456-65fa-48ce-a85d-41b78a9d2111'

    HTTP DELETE 'http://hostname:3000/signalk/v2/api/resources/waypoints/94052456-65fa-48ce-a85d-41b78a9d2111'

each registered provider will polled to determine which one owns the entry with the supplied id. The provider with the resource entry is then the target of the requested operation (`getResource()`, `setResource()`, `deleteResource()`).

Creating new resource entries:

When a request is received to create a new resource

for example:

    HTTP POST 'http://hostname:3000/signalk/v2/api/resources/waypoints'

By default the first provider that was registered for that resource type will be the target of the requested operation (`setResource()`).

You can view the registered providers for a resource type by making the following request:

    HTTP GET 'http://hostname:3000/signalk/v2/api/resources/{resourceType}/_providers'

_Example: `HTTP GET 'http://hostname:3000/signalk/v2/api/resources/charts/_providers'

    [
      "charts",
      "resources-provider"
    ]

You can retrieve the default provider for a resource type by making the following request:

    HTTP GET 'http://hostname:3000/signalk/v2/api/resources/{resourceType}/_providers/_default'

Example: `HTTP GET 'http://hostname:3000/signalk/v2/api/resources/charts/_providers/_default'

    "resources-provider"

You can change the provider used for writing a resource record in the following ways:

1. Per-request by using the `?provider=` query parameter.
2. Setting a "default" provider for a specific resource type

1. Per-request by using the `?provider=` query parameter:

When multiple providers are registered for a resource type the client can specify which provider should be the target of the request by using the query parameter `provider`.

Example:

    HTTP GET 'http://hostname:3000/signalk/v2/api/resources/waypoints?provider=my-plugin-id'

    HTTP GET 'http://hostname:3000/signalk/v2/api/resources/waypoints/94052456-65fa-48ce-a85d-41b78a9d2111?provider=my-plugin-id'

    HTTP PUT 'http://hostname:3000/signalk/v2/api/resources/waypoints/94052456-65fa-48ce-a85d-41b78a9d2111?provider=my-plugin-id'

    HTTP DELETE 'http://hostname:3000/signalk/v2/api/resources/waypoints/94052456-65fa-48ce-a85d-41b78a9d2111?provider=my-plugin-id'

    HTTP POST 'http://hostname:3000/signalk/v2/api/resources/waypoints?provider=my-plugin-id'

the value assigned to `provider` is the `plugin id` of the resource provider plugin.

The plugin id can be obtained from the Signal K server url http://hostname:3000/skServer/plugins.

Example:

    HTTP GET 'http://hostname:3000/plugins'

    [
      {
        "id": "mysk-resource-plugin",  // <-- plugin id
        "name": "Resources Provider",
        "packageName": "mysk-resource-plugin",
        "version": "1.3.0",
        ...
      },
      ...
    ]

2. Setting a default provider for a resource type:

To change the default provider for a resource type make a POST request to http://hostname:3000/signalk/v2/api/resources/{resourceType}/_providers/_default/{pluginId} where `pluginId` is the id of resource provider plugin.

Example: Direct create new chart source entries to `my-chart-plugin`.

    HTTP POST 'http://hostname:3000/signalk/v2/api/resources/charts/_providers/_default/my-chart-plugin'