Integrate with ER Buoy and RMWHub

API Introduction

API to allow ropeless gear manufacturers to exchange anonymized data with each other and with regulators.

 

Base URL

Environment Base URL Country
Test https://buoy.staging.pamdas.org  
Production https://buoy.pamdas.org   US
Production https://dfo.pamdas.org   Canada

Headers

  • Content-Type: application/json
  • Accept: application/json

Changelog

  • April 28, 2026: Added a new “Considerations” section.
  • April 9, 2026: Updated descriptions for rules affecting last_deployed and last_updated.
  • March 4, 2026: Removed unused optional fields.

Get Gear by Location

Returns Gear within 5 nautical miles of the latitude and longitude. 

GET /api/v1.0/gear/

Query Parameters

page integer Page number within the paginated result set.  
page_size integer Number of results per page. 
lat float Include gear within a range of 5 nautical miles from this latitude; latitude must be between -90 and 90. 
lon float Include gear within a range of 5 nautical miles from this longitude; longitude must be between -180 and 180.          
updated_since ISO 8601 datetime Return items updated since the given timestamp.         
state string Filter by state. Use “deployed” for in-water gear or “hauled” for recovered gear.

Example Request

cURL Command

curl --location '{{site}}/api/v1.0/gear?state=deployed&lat={{latitude}}&lon={{longitude}}' \
--header 'Authorization: Bearer {{your_token}}'

{{site}}: Use the site you have been granted access to.

{{your_token}}:  EarthRanger will provide you with a bearer token to authenticate your requests. This token will  not expire.

 
 

Response Shape

 {
    "id": "<set_id>",
    "display_id": "<mfr_set_id or set_id>",
    "status": "deployed | hauled",
    "type": "single | trawl",
    "manufacturer": "<manufacturer_name>",
    "last_updated": "<ISO 8601>",
    "devices": [
      {
        "device_id": "<device_id>",
        "mfr_device_id": "<mfr_device_id>",
        "label": "a | b | c ...",
        "location": {"latitude": float, "longitude": float},
        "last_updated": "<ISO 8601>",
        "last_deployed": "<ISO 8601>"
      }
    ]
  }

Response Example

{
    "data": {
        "count": 2,
        "next": null,
        "previous": null,
        "results": [
            {
                "id": "6b5ac585-76fe-4af8-9813-f6f56a2c6c32",
                "display_id": "6b5ac585-76fe-4af8-9813-f6f56a2c6c32",
                "status": "deployed",
                "devices": [
                    {
                        "device_id": "fe5b4705-0b36-422c-846b-620d4aae983b",
                        "mfr_device_id": "buoy001",
                        "label": "a",
                        "location": {
                            "latitude": 5.55,
                            "longitude": 5.55
                        },
                        "last_updated": "2026-04-08T07:25:15-07:00",
                        "last_deployed": "2026-04-08T14:25:15.123456+00:00"
                    }
                ],
                "type": "single",
                "manufacturer": "Testing",
                "last_updated": "2026-04-09T23:37:14.935411+00:00"
            },
            {
                "id": "6b5ac585-76fe-4af8-9813-f6f56a2c6cab",
                "display_id": "6b5ac585-76fe-4af8-9813-f6f56a2c6cab",
                "status": "deployed",
                "devices": [
                    {
                        "device_id": "fe5b4705-0b36-422c-846b-620d4aae98dd",
                        "mfr_device_id": "buoy002",
                        "label": "a",
                        "location": {
                            "latitude": 5.54,
                            "longitude": 5.54
                        },
                        "last_updated": "2026-04-08T07:25:15-07:00",
                        "last_deployed": "2026-04-08T14:25:15.123456+00:00"
                    },
                    {
                        "device_id": "fe5b4705-0b36-422c-846b-620d4aae98ee",
                        "mfr_device_id": "buoy003",
                        "label": "b",
                        "location": {
                            "latitude": 5.53,
                            "longitude": 5.53
                        },
                        "last_updated": "2026-04-08T07:25:15-07:00",
                        "last_deployed": "2026-04-08T14:25:15.123456+00:00"
                    }
                ],
                "type": "trawl",
                "manufacturer": "Testing",
                "last_updated": "2026-04-09T23:35:21.221668+00:00"
            }
        ]
    },
    "status": {
        "code": 200,
        "message": "OK"
    }
}
 
 

Get Gear by ID

Returns a single trawl with a matching ID

GET /api/v1.0/gear/{id}

Example Request

cURL Command

Basic request:

curl -X 'GET' \
  'https://{{site}}/api/v1.0/gear/{{your_gear_id}}' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {{your_token}}'

{{site}}: Use the site you have been granted access to.

{{your_token}}:  EarthRanger will provide you with a bearer token to authenticate your requests. This token will  not expire.

 
 

Example Response

API Response

{
    "id": "6b5ac585-76fe-4af8-9813-f6f56a2c6c32",
    "display_id": "6b5ac585-76fe-4af8-9813-f6f56a2c6c32",
    "status": "deployed",
    "devices": [
        {
            "device_id": "fe5b4705-0b36-422c-846b-620d4aae983b",
            "mfr_device_id": "buoy001",
            "label": "a",
            "location": {
                "latitude": 5.55,
                "longitude": 5.55
            },
            "last_updated": "2026-04-08T07:25:15-07:00",
            "last_deployed": "2026-04-08T14:25:15.123456+00:00"
        }
    ],
    "type": "single",
    "manufacturer": "Testing",
    "last_updated": "2026-04-09T23:37:14.935411+00:00"
}
 
 

Submit Gear Location

This API allows users to submit a single trawl with either single or multiple devices.  

POST /api/v1.0/gear/

I. Trawl Information 

Field

Allowed Values

Required

Notes

set_id

RFC-4122 UUIDs

Yes

Unique identifier for the gear set.

 

Notes

  • set_id must not be reused across trawl deployment.
  • set_id must be valid RFC-4122 UUIDs. 

deployment_type

trawl, single, surface

Yes

Type of deployment for this set. 

initial_deployment_date

ISO 8601 datetime

Yes

Required when creating a new gear set for the first time. 

 

Notes

  • Not required for updates.

manufacturer_name

Existing identifier defined by EarthRanger.

Yes

Identifies the manufacturer.  Will be provided by EarthRanger during the initial setup.

devices

array<gear>

Yes

Gear that is part of the set. Can be single or multiple. See table below.

 

Example:
"devices": [
 {
   "device_id": "b1b2c3d4-0002-0002-0002-000000000001",
   …   //see next section
 }
]

Optional Fields (click to expand)

Field

Allowed Values

Notes

set_additional_data

JSON object

Freeform key-value data about the gear set (e.g. vessel name, trip info).

 

Example:

{
 "notes": "Deployed in rocky area",
 "custom_field2": 42
}

 

mfr_set_id

string (max 100) Manufacturer's string reference for the gear set. 
 
 

II. Gear Information

Property

Allowed Values

Required

Notes

device_id

UUID

Yes

Unique identifier for the device. Used as the primary key in the system.

mfr_device_id

string (max 100)

No 

Gear Serial Number.

 

Notes

  • mfr_device_id is used for display purposes in the platform UI.
  • Due to UI limitations, in trawls with two or more devices, only the serial number (mfr_device_id) of the first device is displayed in the Gear feed UI.

last_deployed

ISO 8601 datetime

Yes*

Timestamp when the device was last deployed. 

 

Notes

  • Required on gear deployments.
  • Always use the actual date and time the event happened.
  • Cannot be in the future.

last_updated

ISO 8601 datetime

Yes*

Timestamp of the last update to this device. 

 

Notes

  • Required on gear hauls. 
  • Always use the actual date and time the event happened.
  • When reporting that a device has been hauled, the last_updated time you provide must be later than the time the device was originally deployed
     (last_deployed).
  • Cannot be in the future.

device_status

deployed, hauled, lost

Yes 

Current state of the device. Drives gear set active/inactive logic.

 

Notes

  • When hauling, it's important to use the same set_id and device_id as the request sent during deploy.

location

Latitude: -90 to 90

Longitude: -180 to 180

Yes

Deployed latitude and longitude

{
 "latitude": 10.4,
 "longitude": 40.24
}

Optional Fields (click to expand)

Property

Allowed Values

Notes

positioning_type

gps, acoustic

How the device determines its position. Defaults to gps.

release_type

timed, acoustic, galvanic

The mechanism used to release the device.

device_additional_data

JSON object

Freeform key-value data about the device (e.g. battery level, firmware version). Stored but not actively processed.

 

{
 "notes": "Deployed in rocky area",
 "custom_field1": "value1",
 "custom_field2": 42
}

 
 

III. Examples

Python

import requests                                                                                                                                           
                  
  url = "https://<site>/api/v1.0/gear"                                                                                                                      
                  
  headers = {
      "Authorization": "Bearer <your_token>",
      "Content-Type": "application/json",
  }

  payload = {
      "deployment_type": "trawl",
      "manufacturer_name": "<identifier provided by our team>",
      "set_id": "a1b2c3d4-0001-0001-0001-000000000001",
      "devices_in_set": 2,
      "initial_deployment_date": "2025-12-30T21:34:19+00:00",
      "devices": [
          {
              "device_id": "b1b2c3d4-0002-0002-0002-000000000001",
              "last_deployed": "2025-12-30T21:34:19+00:00",
              "last_updated": "2025-12-30T21:34:19+00:00",
              "device_status": "deployed",
              "release_type": "acoustic",
              "location": {
                  "latitude": 20.622157,
                  "longitude": -103.471536,
              },
          },
          {
              "device_id": "b1b2c3d4-0002-0002-0002-000000000002",
              "last_deployed": "2025-12-30T21:34:27+00:00",
              "last_updated": "2025-12-30T21:34:27+00:00",
              "device_status": "deployed",
              "release_type": "acoustic",
              "location": {
                  "latitude": 20.622158,
                  "longitude": -103.471537,
              },
              "device_additional_data": {
                  "sequence": 2,
                  "serial_number": "SN-00123",
                  "battery_pct": 85,
              },
          },
      ],
  }
 
 

cURL Command

curl --location 'https://{{site}}/api/v1.0/gear' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <your token>' \
--data '{
  "deployment_type": "trawl",
  "manufacturer_name": "<identifier provided by our team>",
  "set_id": "<single-use UUID>",
  "devices_in_set": 2,
  "devices": [
    {
      "device_id": "<UUID>",
      "last_deployed": "2025-12-30T21:34:19+00:00",
      "last_updated": "2025-12-30T21:34:19+00:00",
      "device_status": "deployed",
      "location": {
        "latitude": 20.622157, 
        "longitude": -103.471536
      },
      "release_type": "acoustic"
    },
    {
      "device_id": "<UUID>",
      "last_deployed": "2025-12-30T21:34:27+00:00",
      "last_updated": "2025-12-30T21:34:27+00:00",
      "device_status": "deployed",
      "location": {
        "latitude": 20.622158, 
        "longitude": -103.471537
      }
    }
  ],
  "initial_deployment_date": "2025-12-30T21:34:19+00:00"
}
'
 
 

IV. Response

Example

{
    "data": {
        "detail": "Gears successfully processed",
        "set_id": "cf94d09d-b2b5-43cf-be2b-40f8d663b22f"
    },
    "status": {
        "code": 201,
        "message": "Created"
    }
}
 
 

Considerations

Auto-Haul Behavior

When any device in a gearset is hauled, the system automatically hauls all other deployed devices in the same gearset.

Why Auto-Haul?

Fishing gear sets (trawls) are hauled as a unit - all devices come up together

Manufacturers may only report one device in haul notifications due to operational constraints

This prevents “orphaned” deployed devices when the gearset is physically retrieved

Edge Case: Moving a Device Between Gear Sets

When a device is deployed in Set A and then included in a new gearset Set B (with a different set_id), the system accepts the new deployment and closes the previous one.

The latest deployment is always the current one; the previous gearset is closed out automatically when the payload time is strictly after the existing deployment’s start. You do not need to explicitly haul from SET_A before deploying to SET_B—posting the new gearset does both. Posting an older gearset (payload recorded_at earlier than the current deployment’s start) is rejected with HTTP 400 so that a newer deployment is not overwritten.

Optional explicit workflow: You can still haul from SET_A first and then deploy to SET_B; the result is consistent. The accept-and-close behavior is for cases where the client only sends the new deployment.

Older gearset rejected: If the device is already deployed on SET_B (newer) and a request is sent for SET_A with an earlier recorded_at, the request is rejected with HTTP 400 (OlderGearsetRejectedError). The response body explains that the device is already deployed on a newer gearset and the payload’s deployment time is before that deployment.

Error Handling

The serializer validates and raises ValidationError for:

  • Missing required fields
  • Hauling a device already hauled
  • User permission violations
  • Future dates for deployment/updated timestamps

Device moved to another gearset: If a device is deployed in a new gearset while still deployed elsewhere, the previous deployment is closed automatically when the new deployment’s time is strictly after the existing deployment’s start (see “Edge Case: Moving a Device Between Gear Sets”). If the new payload’s deployment time is at or before the existing deployment’s start (older or same-time gearset), the request is rejected with 400.

All validation errors return HTTP 400 with detailed error messages.

 

April 9, 2026