Working with Constrained Application Protocol

Start Developing Today Create an Account
Working with CoAP allows you to access raw device data streams and develop your own applications and interfaces for working with your network.

Developing with CoAP

The most common use case for developing with CoAP is when you would like to make use of the raw network traffic and device data in order to develop your own custom applications or integrate directly to devices.


The Starfish Gateway is a UDP-based Constrained Application Protocol (CoAP) interface that exposes a forward proxy for Read/Write access to devices on the SSN mesh network. Users of this API and documentation are expected to be familiar with CoAP functionality.

We highly recommend that you get familiar with CoAP and the Silver Springs implementation of the protocol by reading the CoAP Overview.


In addition, here are links to the CoAP specifications:

  • RFC 7252 - The Constrained Application Protocol (CoAP)
  • RFC 7641 - Observing Resources in the Constrained Application Protocol (CoAP)

The Starfish Gateway functions as a standard CoAP-to-CoAP proxy and its usage primarily follows the CoAP standard. Therefore, it can be implemented with standard tools, such as the libcoap library.

Note: The Firefox Copper (CU) CoAP add-on is not supported at this time.

Available CoAP Options

Any CoAP options specifically supported by the CoAP Gateway will be described in its CoAP standard CoRE resource .well-known/core. For details on the features supported by the Starfish Gateway, please visit here.


The SSN Milli NIC supports the following URIs



CoAP Content Format









Returns supported URIs to the next level down, including /sensor URIs.




milli Power Stats Definitions  Expand source

struct power_stats {
    /* These are currently in units of 125ms (bottom 3 bits are sub-second) */

    uint32_t total_time;
    uint32_t sleep_time;
    uint32_t standby_time;
    uint32_t rfc_time;
    uint32_t sfl_time;
    uint32_t nxp_time;
    uint32_t tx_bytes;
    uint32_t rx_time;
    uint32_t charge_ctr_low;
    uint32_t charge_ctr_pause_max;
    uint32_t bat_voltage; /* micro Volts*/

typedef struct {

    coap_sens_tl_t tl;          /* type and length */
    char pad[2];                /* align */
    struct power_stats ps;      /* Power stats, all devs */

} coap_sys_pwr_stats_t;



Clear stats




Only supported query is mod=pwr for retrieving and storing power information, described here. Not CBOR encoded.





This is not intended to be used by CoAP clients, rather an attached sensor to notify the milli that is has rebooted. The milli responds by sending a PUT request to /snsr/sys/time to set the time on the sensor.


Device IC API

The following CoAP URIs should be supported by the Device IC. The default value of {prefix} is "snsr"  in firmware version 1.2.1000 build 117958 and later (it is "sensor" in firmware version 1.2.1000 build 112738 and earlier). When the Device IC receives the request from the Milli, {prefix} will have been stripped from the Uri-Path options. On highly resource-constrained devices, these URIs can be shortened to reduce memory requirements.



CoAP Content Format





Return system information, including build version and date.




Returns supported URIs to the next level down



4 byte binary

Retrieve system time from the sensor, network order time_t.



Set the system time on the sensor. Currently supports absolute time setting, not incremental. Not CBOR encoded.




Reset (reboot) the Device IC.




This is a recommended URI to allow the Milli to notify the Device IC of events that may be of interest, such as a low battery alert. The payload is a 4 byte event value in host order.




Device entering storage mode


Device entering service mode


Low battery alert


Tamper alert


Address Resolution

The Starfish Gateway is accessible from the internet at a domain name which is referred to throughout this document as “gatewayhost."

The Starfish Gateway performs address resolution for the client. So, in order to access a device on the mesh, you must provide the hostname with which it registers with the Silver Spring DNS server. This is referred to throughout this documentation as "domain." To access a device on the mesh the name is comprised of the prefix "ssn", the MAC address of the NIC in upper case with no colons, and the domain.


For instance,

The applicable values for the SSN Starfish Networks are provided in the following table:

Network Gatewayhost Domain
Starfish Test

Starfish Stage
Starfish Prod   TBD
Any other Ask your SSN representative Ask your SSN representative



A typical coap-client proxy request will have several ports specified in it:

coap-client -m get -p <client port> -P gatewayhost:<proxy port> coap://devicehost:<server port>/.well-known/core

An example with port numbers might look like the following:

coap-client -m get -p 12345 -P gatewayhost:5683 coap://devicehost:4849/.well-known/core


To break that down:

  • Client Port - the port that the client uses to send/receive CoAP traffic for this command. This is specified in coap-client using the "-p" flag. In this example the client is going to use port 12345 on the local machine to send/receive traffic. As described above it is very important to use this option consistently when communicating with Gateway so that the client's authenticated session can be looked up.
  • Proxy Port - the port that the CoAP proxy (i.e. Gateway) is listening for traffic on. This is specified as part of the Proxy-Uri, which in coap-client is the "-P" flag. In this example the client is sending requests through the proxy gatewayhost on port 5683.  In the Starfish networks (Test, Stage, and Prod) Gateway listens on port 5683 so this should always be used when using the CoAP API on these networks.
  • Server Port - the port that the CoAP server (i.e. the mesh device) is listening for traffic on. This is specified as part of the target URI, in this case devicehost:4849.


The Silver Spring Milli NICs are only enabled to communicate on the secure port 4849 (the default port 5683 is not enabled) so this must always be used when communicating with these devices.


The CoAP proxy protocol has the default port number 5683, which means it is always optional to specify (just as port 80 is optional for HTTP or 443 is optional for HTTPS). 

coap-client -m get -p 12345 -P gatewayhost coap://devicehost:4849/.well-known/core


It is also valid to tell the client to use port 5683 (i.e. -p 5683)  as long as a CoAP server is not running on the same system and already using that port. However, it can be confusing to differentiate the meaning and destination of commands if client and proxy are all using the same ports.  The examples below will continue to use 12345 as the client port for clarity. 



CoAP API calls are secured using an OAuth token. Authentication and granting of a token requires an API key (ClientID and Secret). Details of API authentication can be found in the Security section of the API Overview page.


Sessions are associated with the client account configured on the CoAP Gateway. The default configuration allows a maximum of 10 concurrent sessions per account, but each must bind to a unique socket on which to receive its responses. By default, the Gateway is configured to close sessions that have been idle for more than four hours (with a 15 minute grace period). Sessions can also be closed explicitly via a DELETE operation on the /sessions URI.


Establishing a session

Clients can establish a CoAP Gateway session using a token which can be obtained using the tokens API.  Refer to the Security section of the API Overview for security, authentication, and how to obtain a token to call APIs. The session is established by POSTing the token as a plain text UTF-8 body to the Gateway's /sessions resource.


  • The "-t 0" specifies the content type of the message as UTF-8.
  • The "-f -" means that the content should be read from STDIN (i.e. the echoed text)


The session will be rejected if the token is expired, unparsable, or not a signed token.


Terminate a session

Once you are finished, you SHOULD delete your session. To close a CoAP Gateway proxy session on port 5683:

coap-client -v 10 -m delete -p 12345 "coap://gatewayhost:5683/sessions"

or equivalently (since the default port is used)

coap-client -v 10 -m delete -p 12345 "coap://gatewayhost/sessions"

If the session is successfully deleted Gateway will respond with a DELETED_202 (message code 66) message.  If the deletion fails for any reason Gateway will respond with a PRECONDITION_FAILED_412 (message code 140) response.


Session timeout

Idle sessions may also be kicked from the Gateway.  A session is considered idle if traffic has not been sent or received between the client and Gateway for more than the configured maxSessionIdleTime (defaults to 4 hours).  If a client wants to ensure that its session remains active it can periodically issue requests to one of the Gateway-local CoAP resources such as /.well-known/core, /echo or by issuing a CoAP ping against Gateway to generate traffic without burdening the mesh. Traffic generated by CoAP observations of mesh resources also counts as activity. When a session times out, Gateway will send the client a non-confirmable CoAP response SERVICE_UNAVAILABLE_503 (message code 163) message.

Any further requests made on a closed session will be rejected with a UNAUTHORIZED_401 (message code 129) response, indicating that the client needs to re-authenticate.

Testing with libcoap 

To get the CoAP client and server programs in your path for testing purposes, you can install libcoap and test CoAP calls as shown in the examples below. 


Given CoAP Gateway running on gatewayhost (see table above) and a device (aka "server") running on NIC mac address 001350050005E7D6 (SSN001350050005E7D6) at domain (see table above), libcoap can be used to test as in the examples below.

Establish a Connection

To establish a session for UDP traffic on port 12345:

Get CoAP Resources 

To get CoAP resources on the device NIC behind the CoAP Gateway proxy:

coap-client -v 10 -m get -p 12345 -P gatewayhost:5683 coap://SSN001350050005E7D6.domain:4849/.well-known/core

Example (note in the example the server port has been left out which will use unsecure port 5683 - this would not work with a Milli NIC which requires 4849)

Get NIC Time 

To get the time on the device NIC behind the CoAP Gateway proxy for NICS that support it (Milli does not support time):

coap-client -v 10 -m get -p 5683 -P gatewayhost:5683 coap://SSN001350050005E7D6.domain:4849/time

Example (note in the example the server port is the unsecure port 5683 - this would not work with a Milli NIC which requires 4849):

Get NIC GPIO Pin Description 

NOTE: the Milli NIC does not currently support any GPIOs. This example is for illustration purposes only.

To get a description of the GPIO pins available on the device NIC behind the CoAP Gateway proxy:

coap-client -v 10 -m get -p 5683 -P gatewayhost:5683 coap:// SSN001350050005E7D6.domain:4849/gpio

Example (note in the example the server port is the unsecure port 5683 - this would not work with a Milli NIC which requires 4849):

Terminate a session

Once you are finished, you SHOULD delete your session. To close a CoAP Gateway proxy session on port 12345:

Attempt to Get CoAP Resource Not Implemented 

Attempting to get a CoAP resource that has not been implemented on a device behind CoAP Gateway proxy should result in a “5.01 Not Implemented” error. 

coap-client -v 10 -m get -p 5683 -P gatewayhost:5683 coap:// SSN001350050005E7D6.domain:4849/dummy


Attempt to Get CoAP Resources without a Session or without Permission

Attempting to access a device behind CoAP Gateway proxy without a session should result in a “4.01 unauthorized” internal error. Similarly, attempting to access a device without the appropriate permission should display the “4.01 unauthorized” internal error.

coap-client -v 10 -m get -p 5683 -P gatewayhost:5683 coap://devicehost:4849/.well-known/core

Seeking help from the CoAP Gateway

A client can send a request to coap://gatewayhost/help by issuing this command:
coap-client -m get -p 54321 coap://

The Gateway responds with
v:1 t:CON c:GET i:40cf {} [ ]
To login, send POST to /sessions
To have your session follow your account across different clients, include the query parameter '&sticky=true'.
To logout, send DELETE to /sessions.
To echo a payload, send POST to /echo.