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
- Log into your Watchtower account
- Navigate to Account Settings
- Go to the Security section
- Click Generate New API Credentials
- Provide a descriptive name (e.g., "Mobile App Integration")
- 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 |
|---|---|---|
| Yes | Your API client ID |
| Yes | Your API client secret |
Query Parameters
Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| string | No |
| Filter incidents from this date (ISO 8601 format) |
| string | No |
| Filter incidents to this date (ISO 8601 format) |
| string | No |
| Filter by incident category (partial match) |
| boolean | No | false | Include incident notes in response |
| boolean | No | false | Include involved party information |
| string | No |
| Filter records modified since this date (ISO 8601 format) - for delta loading |
| integer | No | 1000 | Number of records per page (max 1000) |
| integer | No | 0 | Number of records to skip |
| 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 |
|---|---|---|
| string | When the incident occurred (agency timezone) |
| number | Number of people involved |
| string | When the record was created (agency timezone) |
| string | When the record was last modified (agency timezone) |
| string | Incident category/type |
| string | Name of person who submitted the report |
| string | Unique call/incident number |
| number | Latitude coordinate (5 decimal places) |
| number | Longitude coordinate (5 decimal places) |
| string | Location name/description |
| array | Equipment/units used in response |
| array | Personnel who responded |
| number | Air temperature (°F or °C based on agency settings) |
| number | Tide height (feet or meters based on agency settings) |
| number | Wave height (feet or meters based on agency settings) |
| number | Wave interval (seconds) |
| number | Water temperature (°F or °C based on agency settings) |
| string | Your agency ID |
| string | Your agency name |
| array | Incident notes (if |
| array | Involved party details (if |
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
- Store credentials securely - Never commit API credentials to version control
- Use environment variables - Store credentials in environment variables or secure configuration
- Rotate credentials regularly - Generate new credentials periodically
- Monitor usage - Check your API credential status in Account Settings
- 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:
- Email: support@yourwatchtower.com
- Phone: 714-316-9734
- Documentation: https://knowledge.yourwatchtower.com/en/
Changelog
Version 1.0.0-beta.4
- Added
modifiedDateTimeparameter 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
Thank you!