General Information
Welcome to the Firefly API v1 documentation. This documentation is a work in progress. If anything is unclear or undocumented, please reach out to us at support@digimondo.de.
Firefly API Documentation URL
GET "https://apidocs.fireflyiot.com"
The Firefly APIv1 documentation is located at https://apidocs.fireflyiot.com.
Firefly APIv1 URL
GET "https://api.fireflyiot.com/api/v1"
The Firefly APIv1 is located at https://api.fireflyiot.com/api/v1.
Using the REST API
For the HTTP methods PUT
and POST
you have to pass
Content-Type: application/json
in the request headers.
Authentication
Authentication by API Key
To authorize, use the auth parameter:
# With shell, you can just pass the correct header with each request
curl "https://api.fireflyiot.com/api/v1/devices?auth=secretapikey"
Firefly uses API keys to allow access to the API.
Firefly expects for the API key to be included in all API requests to the server as a HTTP parameter named auth
:
auth=secretapikey
API keys are issued for an organization. They allow access to all resources of that organization and its sub-organizations.
API keys expire after a certain amount of time. The Firefly web interface allows administrators to revoke and renew API keys.
Rate Limiting
General Information
API access is rate-limited per API key to 50 requests over a period of 10 seconds. This is the default value, a change can be requested. In case of surpassing the maximum amount of allowed API calls, a 429
HTTP code will be returned. A wait time before retrying should be implemented, preferably with exponential back-off.
HTTP Response Headers
Every response will include the following three header fields:
x-ratelimit-limit: 50/10000ms
x-ratelimit-reset: 7998
x-ratelimit-remaining: 44
Field | Type | Description |
---|---|---|
x-ratelimit-limit | String | The actual rate limit in the form of “50/10000ms”, meaning 50 requests allowed over a span of 10000 milliseconds |
x-ratelimit-remaining | Integer | The number of remaining requests that are allowed within the current rate limit window |
x-ratelimit-reset | Integer | The number of milliseconds left in the current rate limit window |
Make sure you don’t send requests to the API when x-ratelimit-remaining
is at 0. In that case, wait x-ratelimit-reset
milliseconds before attempting the next request.
Show Rate Limit Details
curl "https://api.fireflyiot.com/api/v1/rate_limit?auth=secretapikey"
This REST endpoint can be used to check the current rate limits for your API key. Calling this endpoint will not count against the rate limits for the key used.
{
"rate_limit":{
"remaining": 48,
"reset": 1234,
"limit": "50/10000ms"
},
"valid_for_key": "secretapikey"
}
Field | Type | Description |
---|---|---|
rate_limit.limit | String | The actual rate limit in the form of “50/10000ms”, meaning 50 requests allowed over a span of 10000 milliseconds |
rate_limit.remaining | Integer | The number of remaining requests that are allowed within the current rate limit window |
rate_limit.reset | Integer | The number of milliseconds left in the current rate limit window |
valid_for_key | String | The API key for which these rate limit values are valid |
Devices
A device is a sensor or appliance which is capable of receiving and/or transmitting LoRaWAN packets. Every device is assigned a unique EUI
. Depending on the mode of initial authentication, a device address
might be assigned.
Show All Devices
Sample request
GET "https://api.fireflyiot.com/api/v1/devices?auth=secretapikey"
Sample response
{
"devices": [
{
"updated_at": "2016-05-25T09:02:41.307000",
"otaa": false,
"network_session_key": "3C0FD994269EA89AEDDDDDCF55ADDD68",
"eui": "00000000AABBCCDD",
"name": "Device #1",
"description": "The Device with #1",
"inserted_at": "2016-05-20T13:51:04.643000",
"application_session_key": "3C0FD994269EA89AEDDDDDCF55ADDD68",
"application_key": null,
"address": "A4DDB314",
"tags": [],
"override_location": false,
"location": null,
"skip_fcnt_check": true,
"rx2_data_rate": 0,
"frame_counter": 0,
"deduplicate": false,
"class_c": false,
"adr_limit": 3,
"region": "EU868",
"organization_id": 123,
"organization": {
"name": "Firefly",
"id": 123,
"description": null
},
"multicast_groups": []
},
{
"updated_at": "2016-06-20T13:56:39.689000",
"otaa": false,
"network_session_key": "C3F4FC908AAAAFBA6A2DEA826151E7B2",
"eui": "00000000DECF02EF",
"name": "Device #2",
"description": "The Device with #2",
"inserted_at": "2016-06-20T13:56:39.689000",
"application_session_key": "C3F4FC908AAAAFBA6A2DEA826151E7B2",
"application_key": null,
"address": "23DDB76A",
"tags": [],
"override_location": true,
"location": {
"lon": 9.99383518836612,
"lat": 53.545519559434155
},
"skip_fcnt_check": true,
"rx2_data_rate": 1,
"frame_counter": 0,
"deduplicate": false,
"class_c": false,
"adr_limit": null,
"region": "EU868",
"organization_id": 123,
"organization": {
"name": "Firefly",
"id": 123,
"description": null
},
"multicast_groups": [
{
"updated_at": "2020-04-03T12:57:42.075024",
"region": "EU868",
"organization_id": 123,
"name": "testing testing",
"mc_nwk_s_key": "FA554C6FD47D95053F6D79C1EBFDF95F",
"mc_app_s_key": "8DA1650B4D41B44055D2AC12E4FB7FA1",
"mc_addr": "C88CC9D7",
"inserted_at": "2020-04-03T09:07:13.261855",
"id": 1,
"group_type": "c",
"f_cnt": 165
}
]
}
]
}
List all devices for the organizations for which the API key is valid.
Request Fields
Field | Type | Description |
---|---|---|
tags | Comma-separated strings | Limits the devices shown to to ones supporting one or more of the tags specified, e.g. “sensor, heating” (optional) |
include_organization | Boolean | Include the device’s organization in the response (optional, default: false ) |
include_multicast_groups | Boolean | Include the device’s multicast groups in the response (optional, default: false ) |
Response Format
The response is a JSON
representation of an array of devices in no particular order.
Response Fields (per Device)
Field | Type | Description |
---|---|---|
address | String | Hexadecimal address of the Device |
adr_limit | Integer | Limit ADR to this data rate |
application_key | String | Application key valid for this device |
application_session_key | String | Application session key valid for this device (optional) |
class_c | Boolean | Device is a class c device |
deduplicate | Boolean | Merge consecutive packets with equal frame counter |
description | String | Description of the device |
device_class_id | Integer | ID of device class if set |
eui | String | Unique EUI for this device |
frame_counter | Integer | Downlink frame counter |
inserted_at | Date | Creation date of this Device |
location | Object | {lon, lat} location coordinates if set through location override |
name | String | Name of this device |
network_session_key | String | Network session key valid for this device |
organization | Object | {id, name, description} of the device’s organization (optional) |
organization_id | Integer | Organization ID of this device |
otaa | Boolean | Device activation is OTAA (Over the Air Activation) |
override_location | Boolean | If location override is set for this device |
region | String | LoRaWAN region identifier (e.g. “EU868”) |
rx2_data_rate | Integer | Data rate used to send down packets in RX2 window |
skip_fcnt_check | Boolean | Skip frame counter incrementing check |
tags | Array of strings | All tags associated with this device |
updated_at | Date | Date of last modification of this Device |
multicast_groups | Array of objects | List of currently associated multicast groups |
Show Device
Show a single device identified by either an EUI
or a device address
.
Show by EUI
Sample request: Show device by its EUI
GET "https://api.fireflyiot.com/api/v1/devices/eui/D4022191A445D748?auth=secretapikey"
Every device is assigned a unique EUI when it is created. Using this value to access the device will allow correct access independent of the internal structure of the database the device data is stored in.
Show by Device Address
Sample request: Show device by its device address
GET "https://api.fireflyiot.com/api/v1/devices/address/B43320AD?auth=secretapikey"
A device can be assigned a device address when it’s activated. Using this value to access the device will allow correct access only when the device was already issued a device address.
Response Format
Sample response
{
"device": {
"updated_at": "2016-06-13T10:23:44",
"otaa": true,
"network_session_key": "16FF5B814953444C60713918EDDFA4E7",
"eui": "D4022191A445D748",
"name": "A sample Device",
"description": null,
"inserted_at": "2016-05-13T14:11:04.816000",
"application_session_key": "7B44352BFFAA2A784A744E61EE31BAF3",
"application_key": "DE22FC9088517FBA6A2DED836151E722",
"address": "B43320AD",
"tags": [],
"skip_fcnt_check": true,
"rx2_data_rate": 1,
"frame_counter": 0,
"deduplicate": false,
"class_c": false,
"adr_limit": null,
"region": "EU868",
"organization_id": 500,
"organization": {
"name": "Firefly",
"id": 500,
"description": null
},
"override_location": false,
"location": null,
"multicast_groups": [
{
"updated_at": "2020-04-03T12:57:42.075024",
"region": "EU868",
"organization_id": 123,
"name": "testing testing",
"mc_nwk_s_key": "FA554C6FD47D95053F6D79C1EBFDF95F",
"mc_app_s_key": "8DA1650B4D41B44055D2AC12E4FB7FA1",
"mc_addr": "C88CC9D7",
"inserted_at": "2020-04-03T09:07:13.261855",
"id": 1,
"group_type": "c",
"f_cnt": 165
}
]
}
}
The response is a single JSON
representation of a device, wrapped in a device
object.
Response Fields
Field | Type | Description |
---|---|---|
address | String | Hexadecimal address of the Device |
adr_limit | Integer | Limit ADR to this data rate |
application_key | String | Application key valid for this device |
application_session_key | String | Application session key valid for this device (optional) |
class_c | Boolean | Device is a class c device |
deduplicate | Boolean | Merge consecutive packets with equal frame counter |
description | String | Description of the device |
device_class_id | Integer | ID of device class if set |
eui | String | Unique EUI for this device |
frame_counter | Integer | Downlink frame counter |
inserted_at | Date | Creation date of this Device |
location | Object | {lon, lat} location coordinates if set through location override |
name | String | Name of this device |
network_session_key | String | Network session key valid for this device |
organization | Object | {id, name, description} of the device’s organization (optional) |
organization_id | Integer | Organization ID of this device |
otaa | Boolean | Device activation is OTAA (Over the Air Activation) |
override_location | Boolean | If location override is set for this device |
region | String | LoRaWAN region identifier (e.g. “EU868”) |
rx2_data_rate | Integer | Data rate used to send down packets in RX2 window |
skip_fcnt_check | Boolean | Skip frame counter incrementing check |
tags | Array of strings | All tags associated with this device |
updated_at | Date | Date of last modification of this Device |
multicast_groups | Array of objects | List of currently associated multicast groups |
Create Device
Sample request
POST "https://api.fireflyiot.com/api/v1/devices?auth=secretapikey"
Sample request body
{
"organization": 11,
"device": {
"name": "Device #3",
"description": "this is the third device",
"tags": ["tag1", "tag2"],
"otaa": false,
"eui": "800086E8F84D1C6A",
"address": "AB6A392E",
"network_session_key": "E66E964F8C3A1A14DE729BF95DA53E52",
"application_session_key": "E95A58B86883E3BADDEE15E7DC24442F",
"class_c": false,
"region": "EU868",
"rx2_data_rate": 0,
"adr_limit": 2,
"deduplicate": false,
"skip_fcnt_check": false,
"device_class_id": 1,
"override_location": true,
"location": {"lat": 53.4, "lon": 9.9}
}
}
Sample response
{
"device": {
"id": 53,
"name": "Device #3",
"description": "this is the third device",
"tags": [
"tag1",
"tag2"
],
"otaa": false,
"eui": "800086E8F84D1C6A",
"address": "AB6A392E",
"application_key": null,
"network_session_key": "E66E964F8C3A1A14DE729BF95DA53E52",
"application_session_key": "E95A58B86883E3BADDEE15E7DC24442F",
"class_c": false,
"region": "EU868",
"rx2_data_rate": 0,
"adr_limit": 2,
"deduplicate": false,
"skip_fcnt_check": false,
"device_class_id": 1,
"override_location": true,
"location": {
"lat": 53.4,
"lon": 9.9
},
"frame_counter": null,
"organization_id": 11,
"inserted_at": "2020-08-07T08:47:42.025744",
"updated_at": "2020-08-07T08:47:42.025757"
}
}
Request Fields
Field | Type | Description |
---|---|---|
organization | Integer | ID of the organization (required) |
application | Integer | ID of the application (optional) |
device | Object | Device parameters |
device.name | String | Name (optional) |
device.description | String | Description (optional) |
device.tags | Array of strings | Tags (optional) |
device.otaa | Boolean | Device activation is OTAA (true) or ABP (false) (required) |
device.eui | String | Hex-encoded EUI (required) |
device.application_key | String | Hex-encoded application key (required if OTAA) |
device.address | String | Hex-encoded device address (required if ABP) |
device.network_session_key | String | Hex-encoded network session key (required if ABP) |
device.application_session_key | String | Hex-encoded application session key (required if ABP) |
device.class_c | Boolean | Class C capable (optional, default: false) |
device.region | String | LoRaWAN region identifier (optional, default: “EU868”) |
device.rx2_data_rate | Integer | Data rate used to send down packets in RX2 window (optional) |
device.adr_limit | Integer | Limit ADR to this data rate (optional) |
device.deduplicate | Boolean | Merge consecutive packets with equal frame counter (optional, default: false) |
skip_fcnt_check | Boolean | Skip frame counter incrementing check (optional, default: false) |
device.device_class_id | Integer | ID of device class (optional) |
device.override_location | Boolean | Override location provided by device class (optional, default: false) |
device.location | Object | {lon, lat} location coordinates if set through location override (optional) |
Response Fields
Same as Single Device Response fields.
Update Device
Sample request
PUT "https://api.fireflyiot.com/api/v1/devices/eui/2564927382738492?auth=secretapikey"
Sample request body
{
"device": {
"description": "A new test device"
}
}
Sample response
{
"device": {
"updated_at": "2020-08-07T11:26:12.391522",
"tags": [],
"skip_fcnt_check": false,
"rx2_data_rate": null,
"region": "EU868",
"override_location": false,
"otaa": true,
"organization_id": 11,
"network_session_key": null,
"name": null,
"location": null,
"inserted_at": "2020-08-07T09:14:33.707253",
"id": 55,
"frame_counter": 0,
"eui": "2564927382738492",
"device_class_id": null,
"description": "A new test device",
"deduplicate": false,
"class_c": false,
"application_session_key": null,
"application_key": "0FD295473FF2EC81FAA2447C70C8732F",
"adr_limit": null,
"address": null
}
}
A device can be updated by sending a PUT/PATCH
request to the corresponding endpoint. It expects a JSON
-body with the fields that should be changed.
This endpoint will not send packets, it will only reconfigure the device. To send packets, use the Send Packets to Device method.
Request Fields
Only the fields that should be updated need to be specified.
Field | Type | Description |
---|---|---|
device | Object | Device parameters |
device.name | String | Name (optional) |
device.description | String | Description (optional) |
device.tags | Array of strings | Tags (optional) |
device.otaa | Boolean | Device activation is OTAA (true) or ABP (false) (required) |
device.eui | String | Hex-encoded EUI (required) |
device.application_key | String | Hex-encoded application key (required if OTAA) |
device.address | String | Hex-encoded device address (required if ABP) |
device.network_session_key | String | Hex-encoded network session key (required if ABP) |
device.application_session_key | String | Hex-encoded application session key (required if ABP) |
device.class_c | Boolean | Class C capable (optional, default: false) |
device.region | String | LoRaWAN region identifier (optional, default: “EU868”) |
device.rx2_data_rate | Integer | Data rate used to send down packets in RX2 window (optional) |
device.adr_limit | Integer | Limit ADR to this data rate (optional) |
device.deduplicate | Boolean | Merge consecutive packets with equal frame counter (optional, default: false) |
skip_fcnt_check | Boolean | Skip frame counter incrementing check (optional, default: false) |
device.device_class_id | Integer | ID of device class (optional) |
device.override_location | Boolean | Override location provided by device class (optional, default: false) |
device.location | Object | {lon, lat} location coordinates if set through location override (optional) |
Response Fields
Same as Single Device Response fields.
Delete Device
Sample request
DELETE "https://api.fireflyiot.com/api/v1/devices/eui/2564927382738492?auth=secretapikey"
Sample response
204 No Content
To delete a device, a DELETE
request must be sent with the corresponding device EUI.
Response
When the device was deleted, a 204
success message will be returned.
List Packets
Sample request
GET "https://api.fireflyiot.com/api/v1/devices/eui/2564927382738492/packets?auth=secretapikey"
Sample response
{
"more": true,
"packets": [
{
"ack": false,
"bandwidth": 125,
"codr": "4/6",
"device_eui": "2564927382738492",
"fopts": "",
"fcnt": 12882,
"freq": 866.349812,
"gwrx": [
{
"tmst": 3977700196,
"time": "2016-06-22T07:35:34.774224Z",
"rssi": 2,
"lsnr": 8.5,
"gweui": "0000024B080E006D"
}
],
"modu": "LORA",
"mtype": "unconfirmed_data_up",
"payload_encrypted": false,
"payload": "415141414277673D",
"port": 2,
"received_at": "2016-06-22T09:35:35",
"size": 28,
"spreading_factor": 7,
"uid": "8a569133-ba44-4d7e-5555-af62faf9f722"
},
{
"ack": true,
"bandwidth": 100,
"codr": "4/6",
"device_eui": "2564927382738492",
"fopts": "",
"fcnt": 12883,
"freq": 866.347719,
"gwrx": [
{
"tmst": 1468815219,
"time": "2016-07-18T04:13:39.573216Z",
"rssi": -35,
"lsnr": 5.1,
"gweui": "0102030205060708"
}
],
"modu": "LORA",
"mtype": "confirmed_data_up",
"payload_encrypted": false,
"payload": "415141414277673A",
"port": 2,
"received_at": "2016-06-22T09:39:16",
"size": 28,
"spreading_factor": 7,
"uid": "8a569133-7752-4d7e-810d-af62faf9f722"
}
]
}
Returns packets received by the device.
Request Query Parameters
Query Parameter | Description |
---|---|
direction | When set to asc , it will return the oldest packets first. When set to desc , it will return the most recent packets. (optional, default: desc ). |
limit_to_last | Number of packets to be returned. Ordered by creation date, descending (unless otherwise specified through the direction parameter). (optional, default: 1 , max: 100 ) |
offset | Number of most recent packets to skip before returning packets. (optional, default: 0 ) |
payload_only | Only return payload, parsed payload (where applicable), timestamp, and device address of the packet. (optional, default: false ) |
received_after | Only return packets after this date. If this parameter is used and no limit_to_last value is supplied, limit_to_last will be set to 10 . Default is the Unix epoch timestamp (meaning that no packets will be omitted). Specify an ISO 8601 date string here. |
Response
The more
field will return a boolean value stating if there are more packets in the database than collected with the query specified. This should be used for proper paging implementations.
In the packets
collection that is returned, every item represents a packet that was sent by the device.
As a reference, please check the LoRa documentation for the precise meaning of this data.
Field | Description |
---|---|
ack | Acknowledgement |
bandwidth | Bandwidth |
codr | LoRa ECC coding rate identifier |
datr | Data rate |
device_eui | Device EUI |
fopts | FOpts |
fcnt | Frame counter |
freq | Frequency |
gwrx | Data relevant to the gateway that received the packet |
gwrx.gweui | Gateway EUI |
gwrx.lsnr | LSNR |
gwrx.rssi | RSSI |
gwrx.tmst | Gateway-specific timestamp of when the packet was received (nanoseconds). This is not a ‘real’ time value, as it is reset whenever the gateway is restarted or instructed to reset. Used to guarantee uniqueness of packets. |
gwrx.time | ISO 8601 timestamp of when the packet was received |
modu | Modulation, will be “LORA” |
mtype | Type and direction of Packet |
parsed | If available, the decoded and parsed payload (as configured in the device class) |
payload | Payload that was sent in the packet |
payload_encrypted | Was the payload encrypted? |
port | Port on which the packet was sent |
received_at | ISO 8601 timestamp of server receiption |
size | Length of the payload |
spreading_factor | Spreading factor |
uid | Unique ID of the packet used by the server |
Track the uid
field to ensure packet uniqueness when persisting it into a database.
List Mac Events
Sample request
GET "https://api.fireflyiot.com/api/v1/devices/eui/2564927382738492/mac_events?auth=secretapikey"
Sample response
{
"more": true,
"mac_events": [
{
"uid": "8a569133-aa44-4d7e-810d-af62faf9f722",
"type": "join_accept",
"received_at": "2016-07-15T14:31:11",
"frame_counter": null,
"for_frame_counter": null,
"direction": "down",
"device_eui": "2564927382738492"
},
{
"uid": "2d4289f0-03c9-4c42-b078-04aff6e91180",
"type": "join_request",
"received_at": "2016-07-15T14:31:11",
"frame_counter": null,
"for_frame_counter": null,
"direction": "up",
"device_eui": "2564927382738492"
}
]
}
Returns non-data packets (e.g. join requests, join accepts) received by and sent to the device.
Request Query Parameters
Query Parameter | Description |
---|---|
direction | When set to asc , it will return the oldest packets first. When set to desc , it will return the most recent packets. (optional, default: desc ). |
limit_to_last | Number of packets to be returned. Ordered by creation date, descending (unless otherwise specified through the direction parameter). (optional, default: 1 , max: 100 ) |
offset | Number of most recent packets to skip before returning packets. (optional, default: 0 ) |
received_after | Only return packets after this date. If this parameter is used and no limit_to_last value is supplied, limit_to_last will be set to 10 . Default is the Unix epoch timestamp (meaning that no packets will be omitted). Specify an ISO 8601 date string here. |
Response
The more
field will return a boolean value stating of there are more mac events in the database than collected with the query specified. This should be used for proper paging implementations.
In the mac_events
collection that is returned, every item represents a mac event that was sent to or received by the device.
As a reference, please check the LoRa documentation for the precise meaning of this data.
Field | Description |
---|---|
device_eui | Device EUI |
frame_counter | Frame counter |
for_frame_counter | Frame counter reference |
received_at | ISO 8601 timestamp of server receiption |
direction | Direction of the packet, up (from the device) or down (to the device) |
type | Type of the packet, can be any of the following: join_request , join_accept , ack_up , ack_down , mic_fail , appserver_join_accept . |
uid | Unique ID of the packet used by the server |
Track the uid
field to ensure mac event uniqueness when persisting it into a database.
List Down Packets
Sample request
GET "https://api.fireflyiot.com/api/v1/devices/eui/2564927382738492/down_packets?auth=secretapikey"
Sample response
{
"packets": [
{
"spreading_factor": 12,
"sent": "2016-08-30T10:20:35.139026",
"rx_data": {
"tmst": 3014015996,
"time_on_air": 1155072,
"size": 12,
"rx_window": "rx1",
"rfch": 0,
"powe": 14,
"modu": "LORA",
"ipol": true,
"gw_mac": "0000024B080E00A1",
"freq": 868.5,
"datr": "SF12BW125",
"data": "YCOfO0EgFBKtaGMw",
"codr": "4/5"
},
"raw_payload": "60239F3B41444412AD686330",
"port": 0,
"payload": "",
"parsed_packet": {
"port": 0,
"pending": false,
"payload": null,
"mtype": "unconfirmed_data_down",
"mic_pass": true,
"major": 0,
"mac_cmds": [],
"fopts_len": 0,
"fcnt": 4628,
"dir": "down",
"dev_eui": null,
"dev_addr_hex": "223b9f23",
"adrackreq": false,
"adr": false,
"ack": true
},
"inserted_at": "2016-08-30T12:20:35",
"frame_counter": 4628,
"device_eui": "2564927382738492",
"bandwidth": 125,
"ack": false,
"uid": "8a569133-aa44-4d7e-810d-af62faf9f722"
}
],
"more": true
}
Returns packets sent to the device.
Request Query Parameters
Query Parameter | Description |
---|---|
direction | When set to asc , it will return the oldest packets first. When set to desc , it will return the most recent packets. (optional, default: desc ). |
limit_to_last | Number of packets to be returned. Ordered by creation date, descending (unless otherwise specified through the direction parameter). (optional, default: 1 , max: 100 ) |
offset | Number of most recent packets to skip before returning packets. (optional, default: 0 ) |
payload_only | Only return payload, parsed payload (where applicable), timestamp, and device address of the packet. (optional, default: false ) |
received_after | Only return packets after this date. If this parameter is used and no limit_to_last value is supplied, limit_to_last will be set to 10 . Default is the Unix epoch timestamp (meaning that no packets will be omitted). Specify an ISO 8601 date string here. |
Response
The more
field will return a boolean value stating of there are more down packets in the database than collected with the query specified. This should be used for proper paging implementations.
In the packets
collection that is returned, every item represents a down packet that was sent to the device.
As a reference, please check the LoRa documentation for the precise meaning of this data.
Field | Description |
---|---|
ack | Acknowledgement |
bandwidth | Bandwidth |
device_eui | Device EUI |
frame_counter | Frame counter |
parsed_packet | The decoded and parsed payload of the packet |
payload | Payload |
received_at | ISO 8601 timestamp of server receiption |
rx_data | Meta data relevant to the gateway |
sent | ISO 8601 timestamp of sent date (null if not sent yet) |
spreading_factor | Spreading factor |
uid | Unique ID of the packet used by the server |
Track the uid
field to ensure packet uniqueness when persisting it into a database.
Create (send) packet to device
Sample request
POST "https://api.fireflyiot.com/api/v1/devices/eui/2564927382738492/packet?auth=secretapikey"
Sample request body
{
"payload": "Test Payload",
"encoding": "utf8",
"port": 1,
"confirmed": false
}
Sample response
{
"sent_packet": {
"uid": "724f0f4b-df8c-4e5b-a00d-203bdfa737ab",
"port": 1,
"payload": "54657374205061796C6F6164",
"fcnt": 15
}
}
Send a packet to the device. Make sure the payload is correctly encoded as specified on the encoding
parameter.
Request Fields
The request body must be a valid JSON
object with these fields:
Field | Type | Description |
---|---|---|
encoding | String | Encoding of the payload. Allowed values are base16 , base64 and utf8 |
payload | String | Payload to be sent in the device |
port | Integer | Port on the device to send the packet to |
confirmed | Boolean | Ask the device to acknowledge the down packet (optional, default: false) |
gateway_id | String | For class C devices a gateway EUI can be specified that will be used to send the down packet (optional) |
Response Fields
Field | Description |
---|---|
fcnt | Integer |
payload | String |
port | Integer |
uid | String |
Show Down Packet
Sample request
GET "https://api.fireflyiot.com/api/v1/devices/eui/2564927382738492/down_packets/724f0f4b-df8c-4e5b-a00d-203bdfa737ab?auth=secretapikey"
Sample response
{
"packet": {
"uid": "724f0f4b-df8c-4e5b-a00d-203bdfa737ab",
"spreading_factor": null,
"sent": null,
"rx_data": null,
"received_at": "2020-04-08T09:11:19.055259",
"raw_payload": null,
"port": 12,
"payload": "ABCD",
"parsed_packet": null,
"frame_counter": 1,
"device_eui": "2564927382738492",
"bandwidth": null,
"ack": false
}
}
Returns a single packet that was sent or is to be sent to the device, identified by its uid
. If the response field sent
is null
, then the down packet is still queued and has not been sent yet.
Response
Same as List Down Packets.
Remove Queued Down Packet
Sample request
DELETE "https://api.fireflyiot.com/api/v1/devices/eui/2564927382738492/down_packets/724f0f4b-df8c-4e5b-a00d-203bdfa737ab?auth=secretapikey"
Sample response
204 No Content
To remove a queued down packet, a DELETE
request must be sent with the corresponding uid
. Only packets that have not been sent yet ("sent": null
) can be deleted.
Response
When the packet was deleted, a 204
success message will be returned.
Manage Multicast Groups
Sample request
POST "https://api.fireflyiot.com/api/v1/devices/eui/2564927382738492/multicast_groups?auth=secretapikey"
Sample request body
{
"multicast_groups": [1]
}
Sample response
{
"device": {
"updated_at": "2016-06-13T10:23:44",
"otaa": true,
"network_session_key": "16FF5B814953444C60713918EDDFA4E7",
"eui": "2564927382738492",
"name": "A sample Device",
"description": null,
"inserted_at": "2016-05-13T14:11:04.816000",
"application_session_key": "7B44352BFFAA2A784A744E61EE31BAF3",
"application_key": "DE22FC9088517FBA6A2DED836151E722",
"address": "B43320AD",
"tags": [],
"organization_id": 500,
"organization": {
"name": "Firefly",
"id": 500,
"description": null
},
"override_location": false,
"location": null,
"multicast_groups": [
{
"updated_at": "2020-04-03T12:57:42.075024",
"region": "EU868",
"organization_id": 123,
"name": "testing testing",
"mc_nwk_s_key": "FA554C6FD47D95053F6D79C1EBFDF95F",
"mc_app_s_key": "8DA1650B4D41B44055D2AC12E4FB7FA1",
"mc_addr": "C88CC9D7",
"inserted_at": "2020-04-03T09:07:13.261855",
"id": 1,
"group_type": "c",
"f_cnt": 165
}
]
}
}
Associate a device to multicast groups or remove associations. The multicast_groups
field is not additive, it must always consist of the entire list of multicast groups that should be associated to this device after the request is done. Set to empty list to remove all multicast group associations.
Request Fields
The request rody must be a valid JSON
object with these fields:
Field | Type | Description |
---|---|---|
multicast_groups | Array of Integer | List of multicast group IDs |
Response Fields
Same as Show Device.
Applications
Show Applications
Sample request
GET "https://api.fireflyiot.com/api/v1/applications?auth=secretapikey"
Sample response
{
"applications": [
{
"updated_at": "2016-05-31T14:04:47.598000",
"name": "Testing Applications",
"inserted_at": "2016-05-31T14:04:47.598000",
"id": 18,
"eui": null,
"description": "Test Application 1"
},
{
"updated_at": "2016-06-07T15:02:41.613000",
"name": "App Test 1",
"inserted_at": "2016-06-07T15:02:41.613000",
"id": 19,
"eui": null,
"description": "E.ON power meter application"
},
{
"updated_at": "2016-04-21T10:47:21.770000",
"name": "Test Applikation 2",
"inserted_at": "2016-04-21T10:47:21.770000",
"id": 3,
"eui": "3435343334353435",
"description": "Beschreibung für die Applikation"
}
]
}
List all applications for the organizations for which the API key is valid.
Response Format
The response is a JSON
representation of an array of applications in no particular order.
Response Fields (per Device)
Field | Type | Description |
---|---|---|
inserted_at | Date | Date of creation of this application |
description | String | Description of this application |
eui | String | Unique EUI of this application |
id | Integer | Unique ID of this application in the Firefly database |
name | String | Name for this application |
sink | JSON | Additional data for the application |
updated_at | Date | Date of last modification of this application |
List EUIs of Devices
Sample request
GET "https://api.fireflyiot.com/api/v1/applications/1/euis?auth=secretapikey"
Sample response
{
"devices": [
{
"eui": "000000004136AF4A",
"address": "4136AF4A"
},
{
"eui": "00000000232317D2",
"address": "232317D2"
},
{
"eui": "000000004137DF3A",
"address": "4137DF3A"
}
]
}
Lists all devices that belong to this application.
Response Format
The response is a JSON
representation of an array of devices in no particular order.
Response Fields (per Device)
Field | Type | Description |
---|---|---|
address | String | Hexadecimal representation of the device address |
eui | String | Device EUI |
Device Classes
Show Device Classes
Sample request
GET "https://api.fireflyiot.com/api/v1/device_classes?auth=secretapikey"
Sample response
{
"device_classes": [
{
"updated_at": "2016-04-22T12:52:16.109000",
"script": {
"variables": {
"gps": {
"type": "gps",
"name": "gps"
},
"batteryLevel": {
"type": "range",
"name": "batteryLevel"
},
"battery": {
"type": "hidden",
"name": "battery"
}
},
"parseElements": [
{
"type": "int",
"target": "battery",
"bits": "8"
},
{
"type": "int",
"target": "gps.latitude",
"signed": true,
"bits": "24"
},
{
"type": "int",
"target": "gps.longitude",
"signed": true,
"bits": "24"
},
{
"type": "int",
"target": "gps.altitude",
"signed": true,
"bits": "16"
}
],
"calculateElements": [
{
"target": "batteryLevel",
"formula": "battery != 0 ? (battery - 1) / 253 : null"
},
{
"target": "gps.latitude",
"formula": "gps.latitude / (1 << 23) * 90"
},
{
"target": "gps.longitude",
"formula": "gps.longitude / (1 << 23) * 180"
}
]
},
"name": "Test Device Class",
"inserted_at": "2016-04-20T15:09:18.911000",
"id": 2,
"description": null
}
]
}
This route shows all device classes registered to the API key.
Response Format
The response is a JSON
representation of an array of device classes in no particular order.
Response Fields (per Device Class)
Field | Type | Description |
---|---|---|
description | String | Description |
id | Integer | ID |
inserted_at | String | Date of Creation |
name | String | Name |
script | JSON | Script data for the frontend application |
updated_at | String | Date of last modification |
Show Single Device Class
Sample request
GET "https://api.fireflyiot.com/api/v1/device_classes/1?auth=secretapikey"
Sample response
{
"device_classes": {
"updated_at": "2016-04-22T12:52:16.109000",
"script": {
"variables": {
"gps": {
"type": "gps",
"name": "gps"
},
"battery": {
"type": "hidden",
"name": "battery"
}
},
"parseElements": [
{
"type": "int",
"target": "battery",
"bits": "8"
},
{
"type": "int",
"target": "gps.latitude",
"signed": true,
"bits": "24"
},
{
"type": "int",
"target": "gps.longitude",
"signed": true,
"bits": "24"
},
{
"type": "int",
"target": "gps.altitude",
"signed": true,
"bits": "16"
}
],
"calculateElements": [
{
"target": "batteryLevel",
"formula": "battery != 0 ? (battery - 1) / 253 : null"
},
{
"target": "gps.latitude",
"formula": "gps.latitude / (1 << 23) * 90"
},
{
"target": "gps.longitude",
"formula": "gps.longitude / (1 << 23) * 180"
}
]
},
"name": "Test Device Class",
"inserted_at": "2016-04-20T15:09:18.911000",
"id": 2,
"description": null
}
}
This route shows a single device class registered to the API key by ID.
Response Fields
Field | Type | Description |
---|---|---|
description | String | Description |
id | Integer | ID |
inserted_at | String | Date of Creation |
name | String | Name |
script | JSON | Script data for the frontend application |
updated_at | String | Date of last modification |
List EUIs of Devices
Sample request
GET "https://api.fireflyiot.com/api/v1/device_classes/1/euis?auth=secretapikey"
Sample response
{
"devices": [
{
"eui": "000000004136AF4A",
"address": "4136AF4A"
},
{
"eui": "00000000232317D2",
"address": "232317D2"
},
{
"eui": "000000004137DF3A",
"address": "4137DF3A"
}
]
}
Lists all devices that belong to this device class.
Response Format
The response is a JSON
representation of an array of devices in no particular order.
Response Fields (per Device)
Field | Type | Description |
---|---|---|
address | String | Hexadecimal representation of the device address |
eui | String | Device EUI |
All Packets
Sample request
GET "https://api.fireflyiot.com/api/v1/packets?auth=secretapikey"
The API provides an endpoint to fetch all packets for the organizations for which your API key was issued.
Request Query Parameters
Query Parameter | Description |
---|---|
direction | When set to asc , it will return the oldest packets first. When set to desc , it will return the most recent packets. (optional, default: desc ). |
limit_to_last | Number of packets to be returned. Ordered by creation date, descending (unless otherwise specified through the direction parameter). (optional, default: 1 , max: 100 ) |
offset | Number of most recent packets to skip before returning packets. (optional, default: 0 ) |
payload_only | Only return payload, parsed payload (where applicable), timestamp, and device address of the packet. (optional, default: false ) |
received_after | Only return packets after this date. If this parameter is used and no limit_to_last value is supplied, limit_to_last will be set to 10 . Default is the Unix epoch timestamp (meaning that no packets will be omitted). Specify an ISO 8601 date string here. |
skip_suborgs | Do NOT show packets from devices that are not directly in the organization that the API key is registered for. (optional) |
Response
The API will provide the same fields as in List Packets.
Multicast Groups
Multicast group object
Example multicast group object
{
"id": 1,
"name": "test name",
"mc_addr": "F4F41991",
"mc_nwk_s_key": "86D893F1E98058D528A2E4C857290758",
"mc_app_s_key": "01CB10490014E6BFCE384CD22B32B3EE",
"region": "EU868",
"group_type": "c",
"f_cnt": 0,
"organization_id": 123,
"rx2_data_rate": 2,
"inserted_at": "2020-03-17T15:51:44.707076",
"updated_at": "2020-03-17T15:54:38.479367"
}
Field | Type | Description |
---|---|---|
id | Integer | (read-only) ID of the multicast group |
name | String | Name (required) |
mc_addr | String | Hex-encoded multicast group address (required, length: 8 characters) |
mc_nwk_s_key | String | Hex-encoded multicast group network session key (required, length: 32 characters) |
mc_app_s_key | String | Hex-encoded multicast group application session key (required, length: 32 characters) |
region | String | Region identifier (default: “EU868”) |
group_type | String | Group type/class (default: “c”) |
f_cnt | Integer | Frame counter (default: 0) |
organization_id | Integer | Organization ID (required) |
rx2_data_rate | Integer | SF 12=0, … , SF 7=5 (default: null) |
Create multicast group
Endpoint POST /api/v1/multicast_groups?auth={secretapikey}
Request Body JSON object with a field multicast_group
that contains a
multicast group object, the id
field is generated automatically
Show multicast group
Endpoint GET /api/v1/multicast_groups/{id}?auth={secretapikey}
List all multicast groups
Endpoint GET /api/v1/multicast_groups?auth={secretapikey}
Update multicast group
Endpoint PUT /api/v1/multicast_groups/{id}?auth={secretapikey}
Request Body JSON object with field multicast_group
that contains all the values
you want to overwrite. See: multicast group object
Delete multicast group
Endpoint DELETE /api/v1/multicast_groups/{id}?auth={secretapikey}
List all associated devices
Endpoint GET /api/v1/multicast_groups/{id}/devices?auth={secretapikey}
Multicast down packet object
{
"updated_at": "2020-04-03T12:57:42.077389",
"uid": "0854c37d-fd25-4e0c-bd4f-ff3e7855908c",
"spreading_factor": 12,
"sent": "2020-04-03T12:57:42.077319",
"rx_data": {
"time_on_air": 1482752,
"size": 23,
"rx_window": "rx2",
"rfch": 0,
"powe": 27,
"modu": "LORA",
"ipol": true,
"imme": true,
"gwtx": [
{
"sent": "2020-04-03T12:57:42.077319Z",
"gweui": "7276FF0000000000"
}
],
"freq": 869.525,
"datr": "SF12BW125",
"data": "YKrP7ikApQAB0dnWXVrobDA6o5BJch4=",
"codr": "4/5"
},
"raw_payload": "60AACFEE2900A50001D1D9D65D5AE86C303AA39049721E",
"port": 1,
"payload": "30000000010000003005",
"parsed_packet": {},
"organization_id": 123,
"multicast_group_id": 1,
"inserted_at": "2020-04-03T12:57:41.673260",
"frame_counter": 165,
"bandwidth": 125
}
The multicast down packet object is similar to the regular device down packet with some notable differences:
Field | Description |
---|---|
uid | Unique ID of the multicast down packet |
sent | Timestamp when sent, null when queued |
multicast_group_id | ID of the multicast group |
rx_data.gwtx | List of transmit objects for each gateway used to broadcast the down packet |
Create (send) multicast down packet
Endpoint POST /api/v1/multicast_groups/{id}/multicast_down_packets?auth={secretapikey}
Sample request body
{
"payload": "ABCDEF",
"encoding": "base16",
"port": 1,
"gateway_staggered_delay": 5000
}
Send a downlink packet to the multicast group. Make sure the payload is correctly encoded as specified on the encoding
parameter.
Request Fields
The Request Body must be a valid JSON
Object with these fields:
Field | Type | Description |
---|---|---|
encoding | String | Encoding of the payload. Allowed values are base16 , base64 and utf8 (required) |
payload | String | Payload to be sent in the packet (required) |
port | Integer | Port to send the packet to (required) |
gateway_ids | Array of String | List of gateway IDs to use for sending (optional) |
gateway_staggered_delay | Integer | Toggle Multicast Downlink delay in milliseconds Zero or default delay 3.000 (optional) |
Response
If successful a multicast down packet object with automatically generated uid
.
List all multicast down packets for a multicast group
Endpoint GET /api/v1/multicast_groups/{id}/multicast_down_packets?auth={secretapikey}
Same query parameters as in list down packets apply.
Show multicast down packet
Endpoint GET /api/v1/multicast_groups/{id}/multicast_down_packets/{uid}?auth={secretapikey}
Delete queued multicast down packet
Endpoint DELETE /api/v1/multicast_groups/{id}/multicast_down_packets/{uid}?auth={secretapikey}
Only packets that have not been sent yet ("sent": null
) can be deleted.
Gateways
Gateway object
Example gateway object
{
"id": 1,
"name": "test name",
"eui": "C859D9EED5333DE6",
"auth_token": "6B1A3106D0B93E63F85E143B68333B0D",
"organization_id": 123,
"inserted_at": "2020-03-17T15:51:44.707076",
"updated_at": "2020-03-17T15:54:38.479367"
}
Field | Type | Description |
---|---|---|
id | Integer | (read-only) ID of the gateway |
name | String | Name (required) |
eui | String | Hex-encoded gateway EUI (required, length: 16 characters) |
auth_token | String | Hex-encoded gateway auth token used for Basic Station client token auth mode (length: 32 characters) |
organization_id | Integer | Organization ID (required) |
Create gateway
Endpoint POST /api/v1/gateways?auth={secretapikey}
Request Body JSON object with a field gateway
that contains a
gateway object, the id
field is generated automatically
Show gateway
Endpoint GET /api/v1/gateways/{id}?auth={secretapikey}
List all gateways
Endpoint GET /api/v1/gateways?auth={secretapikey}
Update gateway
Endpoint PUT /api/v1/gateways/{id}?auth={secretapikey}
Request Body JSON object with field gateway
that contains all the values
you want to update. See: gateway object
Delete gateway
Endpoint DELETE /api/v1/gateways/{id}?auth={secretapikey}
API Key Management
Show own API Key Metadata
Sample request
GET "https://api.fireflyiot.com/api/v1/apikeys?auth=secretapikey"
Sample response
{
"apikey": {
"valid_until": "2017-02-20T14:28:00",
"rate_scale": 1000,
"rate_limit": 5,
"organization_id": 25,
"name": "Test API Key",
"may_be_modified": false,
"key": "93444e69bd7aadddd0b280dcc20e479b",
"created_at": "2016-11-22T14:28:11.000000"
}
}
Shows information about validity and rate limiting values attached to the API key being used.
Response Format
The response is a JSON
representation of an API key.
Response Fields
Field | Type | Description |
---|---|---|
valid_until | Date | ISO date of the point in time when this API key becomes automatically revoked |
rate_scale | Integer | Time window for rate limiting |
rate_limit | Integer | Number of allowed calls in rate limit time window |
organization_id | Integer | ID of the organization for which the API key was issued |
name | String | Name |
may_be_modified | Boolean | States whether this API key can be changed by the organization it was issued for |
key | String | The actual value of the API key, to be used as a credential |
created_at | Date | Date of when the API key was created |
Show API Key Metadata
Sample request
GET "https://api.fireflyiot.com/api/v1/apikeys/93444e69bd7aadddd0b280dcc20e479b?auth=secretapikey"
Sample response
{
"apikey": {
"valid_until": "2017-02-20T14:28:00",
"rate_scale": 1000,
"rate_limit": 5,
"organization_id": 25,
"name": "Test API Key",
"may_be_modified": false,
"key": "93444e69bd7aadddd0b280dcc20e479b",
"created_at": "2016-11-22T14:28:11.000000"
}
}
Shows information about validity and rate limiting values attached to the API key sent as a query parameter.
Response Format
The response is a JSON
representation of an API key.
Response Fields
Field | Type | Description |
---|---|---|
valid_until | Date | ISO date of the point in time when this API key becomes automatically revoked |
rate_scale | Integer | Time window for rate limiting |
rate_limit | Integer | Number of allowed calls in rate limit time window |
organization_id | Integer | ID of the organization for which the API key was issued |
name | String | Name |
may_be_modified | Boolean | States whether this API key can be changed by the organization it was issued for |
key | String | The actual value of the API key, to be used as a credential |
created_at | Date | Date of when the API key was created |
Show API Keys for Own Organization
Sample request
GET "https://api.fireflyiot.com/api/v1/apikeys/organization?auth=secretapikey"
Sample response
{
"remaining": 3,
"apikeys": [
{
"valid_until": "2016-11-17T12:19:00",
"rate_scale": 10000,
"rate_limit": 100,
"organization_id": 25,
"name": "Csaba Harta",
"may_be_modified": false,
"key": "9b608eaba123456c51dc25eb438d54c3",
"created_at": "2016-08-19T12:19:47.000000"
},
{
"valid_until": "2017-02-13T16:01:55.192672",
"rate_scale": 10000,
"rate_limit": 50,
"organization_id": 25,
"name": "Test HCP Rate 50",
"may_be_modified": false,
"key": "fe65af387dceeb5543435780c48babb",
"created_at": "2016-11-15T16:01:55.000000"
}
]
}
Shows all API keys issued for the organization for which the API key used is issued.
Response Format
The response is a JSON
representation of a list of API keys.
Response Fields (per API Key)
Field | Type | Description |
---|---|---|
valid_until | Date | ISO date of the point in time when this API key becomes automatically revoked |
rate_scale | Integer | Time window for rate limiting |
rate_limit | Integer | Number of allowed calls in rate limit time window |
organization_id | Integer | ID of the organization for which the API key was issued |
name | String | Name |
may_be_modified | Boolean | States whether this API key can be changed by the organization it was issued for |
key | String | The actual value of the API key, to be used as a credential |
created_at | Date | Date of when the API key was created |
Response Fields (additional)
Field | Type | Description |
---|---|---|
remaining | Integer | The number of API keys that can be created before the limit is reached |
Show API Keys for Organization
Sample request
GET "https://api.fireflyiot.com/api/v1/apikeys/organization/25?auth=secretapikey"
Sample response
{
"remaining": 3,
"apikeys": [
{
"valid_until": "2016-11-17T12:19:00",
"rate_scale": 10000,
"rate_limit": 100,
"organization_id": 25,
"name": "Csaba Harta",
"may_be_modified": false,
"key": "9b608eaba123456c51dc25eb438d54c3",
"created_at": "2016-08-19T12:19:47.000000"
},
{
"valid_until": "2017-02-13T16:01:55.192672",
"rate_scale": 10000,
"rate_limit": 50,
"organization_id": 25,
"name": "Test HCP Rate 50",
"may_be_modified": false,
"key": "fe65af387dceeb5543435780c48babb",
"created_at": "2016-11-15T16:01:55.000000"
}
]
}
Shows all API keys issued for the specified organization.
Response Format
The response is a JSON
representation of a list of API keys.
Response Fields (per API Key)
Field | Type | Description |
---|---|---|
valid_until | Date | ISO date of the point in time when this API key becomes automatically revoked |
rate_scale | Integer | Time window for rate limiting |
rate_limit | Integer | Number of allowed calls in rate limit time window |
organization_id | Integer | ID of the organization for which the API key was issued |
name | String | Name |
may_be_modified | Boolean | States whether this API key can be changed by the organization it was issued for |
key | String | The actual value of the API key, to be used as a credential |
created_at | Date | Date of when the API key was created |
Response Fields (additional)
Field | Type | Description |
---|---|---|
remaining | Integer | The number of API keys that can be created before the limit is reached |
Renew API Key
Sample request
PUT "https://api.fireflyiot.com/api/v1/apikeys/renew?auth=secretapikey"
Sample response
{
"revoked_key": {
"revoked": true,
"key": "93444e69bd7aadddd0b280dcc20e479b"
},
"created_key": {
"valid_until": "2017-05-17T11:52:19.789049",
"rate_scale": 20,
"rate_limit": 20,
"organization_id": -1,
"name": "test",
"may_be_modified": false,
"key": "b974e02ccd082b0ddddaa7db96e44439",
"created_at": "2017-02-16T11:52:19.825607"
}
}
Revokes currently used API key and creates a new API Key in one atomic operation.
Response Format
The response is a JSON
representation of the newly created API key and information about the revocation of the old one.
Response Fields
Field | Type | Description |
---|---|---|
revoked_key.revoked | Boolean | States whether the old API key was successfully revoked |
revoked_key.key | String | The API key that was revoked |
created_key.valid_until | Date | ISO Date of the point in time when the new API key becomes automatically revoked |
created_key.rate_scale | Integer | Time window for rate limiting |
created_key.rate_limit | Integer | Amount of allowed calls in rate limit time window |
created_key.organization_id | Integer | Identifier of the organization for which the new API key was issued |
created_key.name | String | Name of the new API key |
created_key.may_be_modified | Boolean | States whether the new API key can be changed by the organization it was issued for |
created_key.key | String | The actual value of the new API key, to be used as a credential |
created_key.created_at | Date | Date of when the new API key was created |
Revoke API Keys
Sample request
POST "https://api.fireflyiot.com/api/v1/apikeys/revoke?auth=secretapikey"
{
keys: ["3c5e3b7a4c7f746a7043896bf4bd5643", "d1d0c10c3196e811999cd7535f08bd16"]
}
Sample response
{
"apikeys": [
{
"revoked": true,
"key": "3c5e3b7a4c7f746a7043896bf4bd5643"
},
{
"revoked": true,
"key": "d1d0c10c3196e811999cd7535f08bd16"
}
]
}
Revokes given API keys.
Request Fields
Field | Type | Description |
---|---|---|
keys | Array of Strings | The API keys to be revoked |
Response Format
The response is a JSON
representation of information about the revocation of the listed API keys.
Response Fields (per API Key)
Field | Type | Description |
---|---|---|
revoked | Boolean | States whether the API key was successfully revoked |
key | String | The API key that was revoked |
Create API Key
Sample request
POST "https://api.fireflyiot.com/api/v1/apikeys?auth=secretapikey"
{
"key": {
"name": "test",
"rate_scale": 20,
"rate_limit": 20
}
}
Sample response
{
"apikey": {
"valid_until": "2017-05-17T12:02:21.614030",
"rate_scale": 20,
"rate_limit": 20,
"organization_id": 36,
"name": "test",
"may_be_modified": false,
"key": "a4bb2cbcb07dd56ddd996374f7415b54",
"created_at": "2017-02-16T12:02:21.633122"
}
}
Creates a new API key in the organization to which the currently used API key is assigned.
Response Format
The response is a JSON
representation of an API key.
Response Fields
Field | Type | Description |
---|---|---|
valid_until | Date | ISO date of the point in time when this API key becomes automatically revoked |
rate_scale | Integer | Time window for rate limiting |
rate_limit | Integer | Number of allowed calls in rate limit time window |
organization_id | Integer | ID of the organization for which the API key was issued |
name | String | Name |
may_be_modified | Boolean | States whether this API key can be changed by the organization it was issued for |
key | String | The actual value of the API key, to be used as a credential |
created_at | Date | Date of when the API key was created |
Create API Key in Organization
Sample request
POST "https://api.fireflyiot.com/api/v1/apikeys/organization/36?auth=secretapikey"
{
"key": {
"name": "test",
"rate_scale": 20,
"rate_limit": 20
}
}
Sample response
{
"apikey": {
"valid_until": "2017-05-17T12:02:21.614030",
"rate_scale": 20,
"rate_limit": 20,
"organization_id": 36,
"name": "test",
"may_be_modified": false,
"key": "a4bb2cbcb07dd56ddd996374f7415b54",
"created_at": "2017-02-16T12:02:21.633122"
}
}
Creates a new API key in the specified organization.
Response Format
The response is a JSON
representation of an API key.
Response Fields
Field | Type | Description |
---|---|---|
valid_until | Date | ISO date of the point in time when this API key becomes automatically revoked |
rate_scale | Integer | Time window for rate limiting |
rate_limit | Integer | Number of allowed calls in rate limit time window |
organization_id | Integer | ID of the organization for which the API key was issued |
name | String | Name |
may_be_modified | Boolean | States whether this API key can be changed by the organization it was issued for |
key | String | The actual value of the API key, to be used as a credential |
created_at | Date | Date of when the API key was created |
Statistics
API that provides statistical data for up packets in devices and organizations. Meant to be plugged into 3rd party billing application.
Example output
{
"buckets": [
{
"packets": 1913,
"date": "2016-10-01T00:00:00Z",
"bytes": 44813
},
{
"packets": 8615,
"date": "2016-11-01T00:00:00Z",
"bytes": 249863
},
{
"packets": 0,
"date": "2016-12-01T00:00:00Z",
"bytes": 0
},
{
"packets": 659,
"date": "2017-01-01T00:00:00Z",
"bytes": 19119
}
]
}
Devices
Device stats URL
GET https://api.fireflyiot.com/api/v1/statistics/devices/{eui}?auth={secretapikey}
Used to query for statistics over a single device.
Organizations
Organization stats URL
GET https://api.fireflyiot.com/api/v1/statistics/organizations/{org id}?auth={secretapikey}
Used to query for statistics over all devices (recursively) in an organization.
Options
Field | Type | Description |
---|---|---|
after | date | (Organizations) Only return statistics for the time after the given date. Can be combined with before to query for a range. |
before | date | (Organizations) Only return statistics for the time before the given date. Can be combined with after to query for a range. |
interval | day / month |
(Organizations, Devices) Interval of the buckets. |
fill_missing | boolean | (Organizations, Devices) true by default. For device queries, this will detects buckets that are missing from the database output and populate them with 0 values. |
MQTT
Create a MQTT subscription for organization_up_packets
POST "https://api.fireflyiot.com/api/v1/subscriptions?auth=secretapikey"
{
"subscription": {
"name": "foobar",
"organization_id": 8,
"bindings": [{
"type": "organization_up_packets",
"opts": {
"organization": 8
},
"template_id": 1
}],
"queues": [{
"type": "mqtt"
}]
}
}
You can use MQTT to receive events from your devices in real time.
To enable MQTT you first have to create a subscription with a queue of type mqtt
.
Field | Type | Description |
---|---|---|
name | String | Name your subscription |
organization_id | Integer | ID of your organization |
bindings.type | String | Type of the binding. possible values |
bindings.opts | Object | Options that depend on the binding type (here: organization ID) |
See the sections about bindings, queues, and templates to learn more about subscription configuration. For most applications binding type organization_up_packets
and the default template template_id: 1
should be sufficient, so the only parameters you have to replace in the sample request on the right are the subscription name and your organization ID.
Sample response
{
"subscription": {
"queues": [
{
"uid": "eeb95e33-d1ba-4a46-b22f-0c27a5955e53",
"opts": {
"access_key": "e944c8bf28b7f036a0dc20b5024e2e3a"
}
}
]
}
}
In the response to your create-subscription-request you will (among other things) find your subscription queue’s uid
and access_key
. These are your credentials to connect to the Firefly MQTT broker. The broker runs through our RabbitMQ server and uses virtual hosts to separate data.
MQTT | Connection Parameter |
---|---|
Host | rabbithole.fireflyiot.com |
Port | 1883 |
Port (TLS) | 8883 Client needs to trust Let’s Encrypt CA |
User | {uid}:{uid} |
Password | {access_key} |
Topics | Filtered: organizations/{organization_id}/devices/{eui} All: organizations/+/devices/+ |
Using the connection parameters above you can now connect and subscribe to topics in the format organizations/{organization_id}/devices/{eui}
. To receive events from more than one device/organization use the wildcard +
for organization_id
and/or eui
.
Connect to the MQTT broker using the mosquitto client
mosquitto_sub -v \
-t 'organizations/+/devices/+' \
-h rabbithole.fireflyiot.com \
-p 8883 \
-u 'eeb95e33-d1ba-4a46-b22f-0c27a5955e53:eeb95e33-d1ba-4a46-b22f-0c27a5955e53' \
-P 'e944c8bf28b7f036a0dc20b5024e2e3a' \
--cafile /etc/ssl/cert.pem
Subscriptions (WebSocket, Webhook, Polling, MQTT)
Subscriptions allow you to fine-tune which events are sent where.
- Subscription Routes events coming from bindings to output queues
- Binding Defines which events are listened to
- Queue Defines where incoming events are sent to
- Template Defines what the payload of events looks like
Subscriptions can be set up with a REST API.
Subscription Object
Field | Type | Description |
---|---|---|
id | integer | (read only) Unique ID of the subscription |
name | string | Human-readable name of the subscription |
bindings | array | List of bindings, see: Binding Object |
queues | array | List of queues, see: Queue Object |
organization_id | integer | Unique ID of the organization this subscription is attached to |
List all subscriptions
Sample request
GET "https://api.fireflyiot.com/api/v1/subscriptions?auth={secretapikey}"
Sample response
{
"subscriptions": [
{
"bindings": [
{
"id": 22,
"opts": {
"device_eui": null,
"id": "6d7fa8f9-6d3f-42a8-92f3-bc0cd6f3b98d",
"include_suborganizations": null,
"organization": -1
},
"subscription_id": 3,
"template_id": 2,
"type": "organization_up_packets"
}
],
"id": 3,
"name": "test",
"organization_id": -1,
"queues": [
{
"opts": {},
"subscription_id": 3,
"type": "websocket",
"uid": "eeb95e33-d1ba-4a46-b22f-0c27a5955e53"
}
]
}
]
}
Will list all subscriptions of the organization the used API key is bound to.
Endpoint GET /api/v1/subscriptions?auth={secretapikey}
Returns
Field | Type | Description |
---|---|---|
subscriptions | array | List of subscriptions, see: Subscription Object |
Create Subscription
Sample request
POST "https://api.fireflyiot.com/api/v1/subscriptions?auth=secretapikey"
{
"subscription": {
"name": "foobar",
"organization_id": 8,
"bindings": [{
"type": "organization_up_packets",
"opts": {
"organization": 8
},
"template_id": 1
}],
"queues": [{
"type": "websocket"
}]
}
}
Creates a new subscription. You don’t need to define bindings or queues right away, you can also add them later with the respective API methods for:
- Add queue to subscription
- Add binding to subscription
- Remove queue from subscription
- Remove binding from subscription
If you choose to not configure queues or bindings right away, pass an empty list []
.
Endpoint POST /api/v1/subscriptions?auth={secretapikey}
Request body JSON object with this field:
Field | Type |
---|---|
subscription | Subscription object |
Update Subscription
Update a subscription by using PUT
on its URL and passing only the values you
want to change.
To update bindings or queues, use the Update Binding and Update Queue endpoints respectively.
Endpoint PUT /api/v1/subscriptions/{subscription_id}?auth={secretapikey}
Request body JSON object with this field:
Field | Type |
---|---|
subscription | Subscription object |
Delete Subscription
Endpoint DELETE /api/v1/subscriptions/{subscription_id}?auth={secretapikey}
Subscription Bindings
A binding defines which events should be passed to a subscription’s queues.
Binding Object
Example binding object
{
"id": 1,
"type": "organization_up_packets",
"opts": {
"organization": 12
},
"template_id": 52,
"subscription_id": 31
}
Field | Type | Description |
---|---|---|
id |
Integer | (read only) Unique ID of the binding |
type |
String | Type of the binding. possible values |
opts |
Object | Options that depend on the type |
template_id |
Integer | ID of the template that renders this binding’s payload |
subscription_id |
Integer | ID of the subscription of this binding |
Binding Types
Organization level types
Example organization
opts
{
"organization": 32
}
Generally, organization level types will bind to all packets in all devices of the organization specified in opts
and its suborganizations.
organization_up_packets
organization_down_packets
organization_mac_events
Options
Field | Type | Description |
---|---|---|
organization |
Integer | ID of the organization |
Device level types
Example device
opts
{
"device_eui": "3DA6B1B33D2C0CCA"
}
Device level types will bind to all packets in one device.
device_up_packets
device_down_packets
device_mac_events
Options
Field | Type | Description |
---|---|---|
device_eui |
String | Base16 encoded big endian EUI of the device. |
Create Binding
Endpoint POST /api/v1/subscriptions/{subscription_id}/bindings?auth={secretapikey}
Request Body JSON with these fields:
Field | Type |
---|---|
binding | Binding object |
Show Binding
Endpoint GET /api/v1/subscriptions/{subscription_id}/bindings/{binding_id}?auth={secretapikey}
List all bindings of subscription
Endpoint GET /api/v1/subscriptions/{subscription_id}/bindings?auth={secretapikey}
Update Binding
You can edit a binding later if you want to change properties. Like with all other update API methods, you only have to pass the fields you want to change.
Endpoint PUT /api/v1/subscriptions/{subscription_id}/bindings/{binding_id}?auth={secretapikey}
Request Body Same as Add binding, but you can omit fields that you don’t want to edit.
Response Body A JSON Object with a field binding
, containing a
Binding object. This represents the binding after your changes have been applied to it.
Delete Binding
Use this to remove a binding from a subscription.
Endpoint DELETE /api/v1/subscriptions/{subscription_id}/bindings/{binding_id}?auth={secretapikey}
Subscription Queues
Queue Object
Example queue object
{
"uid": "eeb95e33-d1ba-4a46-b22f-0c27a5955e53",
"type": "http_push",
"subscription_id": 12,
"opts": {
"url": "http://api.iot-app.io/push/",
"method": "POST"
}
}
Field | Type | Description |
---|---|---|
uid |
UUID | (read-only) Unique ID of the queue |
type |
String | Type of the queue. possible values |
subscription_id |
Integer | ID of the queue’s subscription |
opts |
Object | Options for the queue that depend on its type |
Queue Types
The queue type decides how the events and messages get to your application.
We currently offer http_push
(webhook), websocket
, http_pull
(polling) and mqtt
.
http_push
Pushes all events to an external HTTP server.
It is recommended to use HTTPS to prevent bad people from eaves-dropping on your data.
Options
Field | Type | Description |
---|---|---|
method |
String | HTTP method to use (GET , POST , PUT , DELETE , PATCH ) |
url |
String | HTTP URL to push to |
headers |
Object | key-value list of headers to use in the HTTP request. |
websocket
WebSocket endpoint that sends events as they happen.
After creation, a client can connect to wss://api.fireflyiot.com/api/v1/subscriptions/websocket/{uid}
, where {uid}
is replaced with whatever uid
was returned by the API.
The queue will only start accumulating messages after the first client has connected to the WebSocket.
In case of disconnects, messages will be stored until the client reconnects or 2 hours have passed, whichever comes first. This allows clients to recover from crashes or restarts without missing any events.
It is possible to connect multiple clients to the same WebSocket, in which case messages are distributed equally in a round-robin fashion.
If you want all clients to receive all messages, you need to create a queue for each client.
http_pull
HTTP endpoint to poll for new messages.
Use GET https://api.fireflyiot.com/api/v1/subscriptions/http_pull/<uid>?auth=<apikey>
to get new events. Similar to the WebSocket queue, events will only be kept for 2 hours.
Options
You can pass the following query parameters when calling the URL.
encoding
(String) Decides how the payload should be formatted in the HTTP Body.
Possible values:
json
Use when the payload is also JSON. This will result in a JSON list ([]
) containing all the payloads. (default)base16
Use when payload is binary. Payloads will be separated by a linefeed (\n
).base64
Use when payload is binary. Payloads will be separated by a linefeed (\n
).utf8
Use when payload can be represented in UTF-8. Payloads will be separated by 2 linefeeds (/n/n
).
separator
(String) Overrides the separation string when the encoding is not json
.
limit
(Integer) Defines the maximum amount of messages to return. If not set, will return all messages.
mqtt
MQTT endpoint to subscribe to events.
When creating an MQTT subscription the API will respond with an access_key
in the opts
field along with the uid
. See the MQTT Section for details.
Create Queue
Endpoint POST /api/v1/subscriptions/{subscription_id}/queues?auth={secretapikey}
Request Body JSON object with a field queue
that contains a
Queue Object, the uid
field is generated automatically
Show Queue
Endpoint GET /api/v1/subscriptions/{subscription_id}/queues/{queue_uid}?auth={secretapikey}
List all queues of subscription
Endpoint GET /api/v1/subscriptions/{subscription_id}/queues?auth={secretapikey}
Update Queue
Endpoint PUT /api/v1/subscriptions/{subscription_id}/queues/{queue_uid}?auth={secretapikey}
Request Body JSON object with field queue
that contains all the values
you want to overwrite. See: Queue Object
Delete Queue
Endpoint DELETE /api/v1/subscriptions/{subscription_id}/queues/{queue_uid}?auth={secretapikey}
Subscription Templates
Each binding has a template which is used to format each message that was received over it.
Template Object
Example object
{
"id": 45,
"name": "Device JSON",
"source": "<%= Poison.encode!(@subject) %>",
"organization_id": 31,
"visibility": "public",
"code_type": "eex"
}
Field | Type | Description |
---|---|---|
id |
Integer | (read only) Unique ID of the template |
name |
String | Human readable name of the template. Used to identify it in the UI. |
source |
String | Source code of the template. Language depends on code_type field |
organization_id |
Integer | ID of the organization the template is bound to |
visibility |
String | Visibility of the template to other organizations. Possible values |
code_type |
String | Language of the source code. Possible values |
Template Language
Templates currently support code written the following languages:
Language | code_type |
Documentation |
---|---|---|
Elixir | ex |
Homepage |
Embedded Elixir | eex |
HexDocs |
When creating or updating a template, the code will be checked for allowed function calls and modules.
Allowed Modules
Allowed Functions
The following functions of the Kernel module are whitelisted:
:<>
:__block__
:""
:var!
:if
:case
:length
:is_atom
:is_integer
:is_binary
:is_tuple
:is_map
:is_float
:+
:-
:*
:/
:"->"
:|>
:.
Template Visibility
parent_organizations
- Only the organization this template is bound to and all of its ancestors can see this templatesub_organizations
- Ancestors and descendants can see this templateeveryone
- All organizations can see this template
List Templates
Endpoint GET /api/v1/templates?auth={secretapikey}
Lists all templates that are visible to the organization the given secretapikey
is bound to.
Create Template
Endpoint POST /api/v1/templates?auth={secretapikey}
Request Body JSON object with a field template
that contains a
Template Object
Update Template
Endpoint PUT /api/v1/templates/{template_id}?auth={secretapikey}
Request Body JSON object with field template
that contains all the values
you want to overwrite. See: Template Object
Delete Template
Endpoint DELETE /api/v1/templates/{template_id}?auth={secretapikey}
WebSocket API (deprecated)
The WebSocket API has been deprecated in favor of subscriptions.
To continue using WebSockets, create a subscription with a websocket
queue.
General
The Firefly websocket API allows for real-time streaming of packets as they are received by the application server. A HTTP websocket connection needs to be established with wss://api.fireflyiot.com/api/websocket.
Authentication
The Firefly websocket API uses the same API keys that are used for the REST API.
Use the API key as a connection parameter like wss://api.fireflyiot.com/api/websocket?auth=secretapikey
.
Libraries
To connect to the application server channels, you will need to use a Phoenix Channels-compatible library.
JavaScript
var phoenix = require("./phoenix-common.js")
var socket = new phoenix.Socket("wss://api.fireflyiot.com/api", {
transport: require("websocket").w3cwebsocket,
params: {auth: "206b02ed500addc57bb12244151d6a7a"
}})
socket.connect()
socket.onError(function(err) {console.log("error:", err)})
var channel = socket.channel("device:000000001EE00001", {
received_after: "2016-08-02 00:00:00"
})
channel.join()
.receive("ok", function() {console.log("joined")})
.receive("error", function(reason) {console.log("error:", reason)})
channel.on("packets", function(message) {console.log("message", message)})
To connect via JavaScript, you can either use the JavaScript supplied with the Phoenix Framework or use the ready-to-use Phoenix channels JavaScript client library that we supply at digimondo/phoenix-websocket-js, called phoenix-common.js
.
Channels
Once connected, you can subscribe to channels which will expose received packets for each device.
Device Channels
Connect to device:<eui>
, e.g. device:00000000413B9F61
to receive packet updates for the device with the corresponding EUI.
Device Class Channels
Connect to device_class:<id>
, e.g. device_class:1
to receive device updates for the device class with the corresponding ID.