API Docs

Watchtower Public API Documentation


Overview


The Watchtower Public API allows you to programmatically access your incident data. This REST API provides secure access to submission and dispatch information with flexible filtering and pagination options.


Base URL


https://api.yourwatchtower.com/api


Authentication


The API uses client credentials authentication. You'll need to generate API credentials from your Watchtower account.


Generating API Credentials


  1. Log into your Watchtower account
  2. Navigate to Account Settings
  3. Go to the Security section
  4. Click Generate New API Credentials
  5. Provide a descriptive name (e.g., "Mobile App Integration")
  6. Important: Copy and save the Client Secret immediately - it won't be shown again!


Authentication Headers


Include these headers in all API requests:


X-Client-Id: your_client_id_here
X-Client-Secret: your_client_secret_here


Endpoints


GET /incidents


Retrieves incident data with optional filtering and pagination.


Request Headers


Header

Required

Description

X-Client-Id

Yes

Your API client ID

X-Client-Secret

Yes

Your API client secret


Query Parameters


Parameter

Type

Required

Default

Description

startDate

string

No

Filter incidents from this date (ISO 8601 format)

endDate

string

No

Filter incidents to this date (ISO 8601 format)

categoryLabel

string

No

Filter by incident category (partial match)

includeNotes

boolean

No

false

Include incident notes in response

includeInvolvedParties

boolean

No

false

Include involved party information

modifiedDateTime

string

No

Filter records modified since this date (ISO 8601 format) - for delta loading

limit

integer

No

1000

Number of records per page (max 1000)

offset

integer

No

0

Number of records to skip

page

integer

No

Page number (alternative to offset)


Example Requests


Basic Request


curl -X GET "https://api.yourwatchtower.com/api/incidents?startDate=2024-01-01&endDate=2024-12-31&limit=100&includeNotes=true" \
-H "X-Client-Id: your_client_id" \
-H "X-Client-Secret: your_client_secret"


Delta Loading Request


curl -X GET "https://api.yourwatchtower.com/api/incidents?modifiedDateTime=2024-01-15T10:30:00Z&limit=100" \
-H "X-Client-Id: your_client_id" \
-H "X-Client-Secret: your_client_secret"


Response Format


{
"data": [
{
"incidentDateTime": "06/15/2024 14:30",
"involved": 2,
"creationDateTime": "06/15/2024 14:32",
"modifiedDateTime": "06/15/2024 14:35",
"category": "Water Rescue",
"submittedBy": "John Smith",
"callNumber": "SD24-001234",
"lat": 32.7157,
"lng": -117.1611,
"location": "Mission Beach",
"resource": ["Lifeguard Unit 1", "Rescue Boat 2"],
"responders": ["John Smith", "Jane Doe"],
"airTemp": 72,
"tideHeight": 4.2,
"waveHeight": 3,
"waveInterval": 12,
"waterTemp": 68,
"agencyId": "agency_123",
"agency": "San Diego Lifeguards",
"notes": ["Initial response notes", "Follow-up information"],
"involvedParties": ["Individual - 25 - Male - Local"]
}
],
"version": "1.0.0-beta.4",
"pagination": {
"totalCount": 1250,
"hasNextPage": true,
"hasPreviousPage": false,
"currentPage": 1,
"totalPages": 13,
"limit": 100,
"offset": 0
}
}


Response Fields


Field

Type

Description

incidentDateTime

string

When the incident occurred (agency timezone)

involved

number

Number of people involved

creationDateTime

string

When the record was created (agency timezone)

modifiedDateTime

string

When the record was last modified (agency timezone)

category

string

Incident category/type

submittedBy

string

Name of person who submitted the report

callNumber

string

Unique call/incident number

lat

number

Latitude coordinate (5 decimal places)

lng

number

Longitude coordinate (5 decimal places)

location

string

Location name/description

resource

array

Equipment/units used in response

responders

array

Personnel who responded

airTemp

number

Air temperature (°F or °C based on agency settings)

tideHeight

number

Tide height (feet or meters based on agency settings)

waveHeight

number

Wave height (feet or meters based on agency settings)

waveInterval

number

Wave interval (seconds)

waterTemp

number

Water temperature (°F or °C based on agency settings)

agencyId

string

Your agency ID

agency

string

Your agency name

notes

array

Incident notes (if includeNotes=true)

involvedParties

array

Involved party details (if includeInvolvedParties=true)


Note: Temperature and distance measurements are automatically returned in your agency's preferred units (Imperial or Metric) as configured in your account settings.


Pagination


The API supports two pagination methods:


Method 1: Offset-based


GET /api/incidents?limit=100&offset=200


Method 2: Page-based


GET /api/incidents?limit=100&page=3


The page parameter automatically calculates the offset: offset = (page - 1) * limit


Error Responses


Status Code

Description

400

Bad Request - Invalid parameters

401

Unauthorized - Invalid credentials

403

Forbidden - Access denied

500

Internal Server Error


Error Response Format


{
"error": "Invalid client credentials"
}


Rate Limits


  • Maximum 1000 records per request
  • API credentials can be disabled if misused


Security Best Practices


  1. Store credentials securely - Never commit API credentials to version control
  2. Use environment variables - Store credentials in environment variables or secure configuration
  3. Rotate credentials regularly - Generate new credentials periodically
  4. Monitor usage - Check your API credential status in Account Settings
  5. Disable unused credentials - Disable credentials that are no longer needed


Code Examples


JavaScript/Node.js


const axios = require('axios')

const apiClient = axios.create({
baseURL: 'https://api.yourwatchtower.com/api',
headers: {
'X-Client-Id': process.env.WATCHTOWER_CLIENT_ID,
'X-Client-Secret': process.env.WATCHTOWER_CLIENT_SECRET
}
})

async function getIncidents(params = {}) {
try {
const response = await apiClient.get('/incidents', { params })
return response.data
} catch (error) {
console.error('API Error:', error.response?.data || error.message)
throw error
}
}

// Initial load - get all data
async function initialLoad() {
const data = await getIncidents({
startDate: '2024-01-01',
endDate: '2024-12-31',
limit: 1000,
includeNotes: true
})

console.log(`Initial load: ${data.data.length} incidents`)

// Store the timestamp for delta loading
const lastSyncTime = new Date().toISOString()
return { data, lastSyncTime }
}

// Delta load - get only updated records
async function deltaLoad(lastSyncTime) {
const data = await getIncidents({
modifiedDateTime: lastSyncTime,
limit: 1000,
includeNotes: true
})

console.log(`Delta load: ${data.data.length} new/updated incidents`)
return data
}


Python


import requests
import os
from datetime import datetime

class WatchtowerAPI:
def __init__(self):
self.base_url = 'https://api.yourwatchtower.com/api'
self.headers = {
'X-Client-Id': os.getenv('WATCHTOWER_CLIENT_ID'),
'X-Client-Secret': os.getenv('WATCHTOWER_CLIENT_SECRET')
}

def get_incidents(self, **params):
response = requests.get(
f'{self.base_url}/incidents',
headers=self.headers,
params=params
)
response.raise_for_status()
return response.json()

def delta_sync(self, last_sync_time):
"""Get incidents modified since last sync"""
return self.get_incidents(
modifiedDateTime=last_sync_time,
limit=1000
)

# Usage
api = WatchtowerAPI()

# Initial load
initial_data = api.get_incidents(
startDate='2024-01-01',
endDate='2024-12-31',
limit=1000,
includeNotes=True
)

print(f"Initial load: {len(initial_data['data'])} incidents")

# Store sync timestamp
last_sync = datetime.utcnow().isoformat() + 'Z'

# Later - delta load
delta_data = api.delta_sync(last_sync)
print(f"Delta load: {len(delta_data['data'])} new/updated incidents")


cURL


#!/bin/bash

CLIENT_ID="your_client_id"
CLIENT_SECRET="your_client_secret"

# Initial load
echo "Performing initial load..."
curl -X GET "https://api.yourwatchtower.com/api/incidents?startDate=2024-01-01&limit=1000" \
-H "X-Client-Id: $CLIENT_ID" \
-H "X-Client-Secret: $CLIENT_SECRET" \
-H "Accept: application/json"

# Delta load (replace timestamp with your last sync time)
echo "Performing delta load..."
curl -X GET "https://api.yourwatchtower.com/api/incidents?modifiedDateTime=2024-01-15T10:30:00Z&limit=1000" \
-H "X-Client-Id: $CLIENT_ID" \
-H "X-Client-Secret: $CLIENT_SECRET" \
-H "Accept: application/json"


Rate Limiting


IP-based rate limiting is enforced through AWS WAF:


  • Public Incidents API: 100 requests per 5-minute window per IP address
  • Aggregation: Custom keys (IP address + HTTP method)
  • Action: Block requests exceeding limit
  • Response: HTTP 403 (Forbidden)


Support


For API support, contact:



Changelog


Version 1.0.0-beta.4


  • Added modifiedDateTime parameter for delta loading and incremental data synchronization
  • Supports both standalone delta loading and combined filtering with date ranges


Version 1.0.0-beta.3


  • Improved property naming for consistency and clarity (incidentTime -> incidentDateTime)


Version 1.0.0-beta.2


  • Time values now returned in ISO 8601 format
  • Includes modifiedDateTime field for accurate change tracking
  • Improved property naming for consistency and clarity
  • Consistent camelCasing on response object


Version 1.0.0-beta.1


  • Initial release with incident data access
  • Support for filtering by date range and category
  • Pagination support
  • Optional notes and involved parties data
  • Automatic unit conversion based on agency preferences


Updated on: 14/10/2025

Was this article helpful?

Share your feedback

Cancel

Thank you!