Waypoints API
Complete reference for the Waypoints API endpoints
Waypoints API
The Waypoints API allows you to manage water fountain locations (waypoints). You can list, create, update, and search for waypoints.
Endpoints
GET /api/waypoints
Get all waypoints in the system.
Authentication: Not required
Response:
{
"license": "CC BY-NC 4.0",
"author": "Linus Kang",
"waypoints": [
{
"id": 1,
"name": "Central Park Fountain",
"latitude": 40.7829,
"longitude": -73.9654,
"description": "Beautiful fountain near the lake",
"amenities": ["accessible", "pet-friendly"],
"image": "https://example.com/image.jpg",
"maintainer": "NYC Parks",
"region": "New York",
"approved": true,
"verified": true,
"addedByUserId": "user123",
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}
]
}POST /api/waypoints
Create a new waypoint.
Authentication: Required (Session or API Token)
Request Body:
{
"name": "Example Fountain",
"latitude": 40.7128,
"longitude": -74.0060,
"description": "A convenient water fountain",
"amenities": ["accessible"],
"image": "https://example.com/fountain.jpg",
"maintainer": "City Parks",
"region": "Manhattan"
}Required Fields:
name(string) - Name of the waypointlatitude(number) - Latitude coordinatelongitude(number) - Longitude coordinate
Optional Fields:
description(string) - Description of the waypointamenities(array) - Array of amenity stringsimage(string) - URL to waypoint imagemaintainer(string) - Entity responsible for maintenanceregion(string) - Geographic region
API Token Only Fields:
approved(boolean) - Whether the waypoint is approvedverified(boolean) - Whether the waypoint is verifiedaddedByUserId(string) - User ID of the creator
XP Requirements:
Regular users need sufficient XP (experience points) to create waypoints. API tokens bypass this requirement.
Example Request:
curl -X POST https://bubblymaps.org/api/waypoints \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
"name": "Bryant Park Fountain",
"latitude": 40.7536,
"longitude": -73.9832,
"description": "Modern fountain in the park",
"amenities": ["accessible", "filtered"],
"region": "Manhattan"
}'Response (201 Created):
{
"id": 42,
"name": "Bryant Park Fountain",
"latitude": 40.7536,
"longitude": -73.9832,
"description": "Modern fountain in the park",
"amenities": ["accessible", "filtered"],
"region": "Manhattan",
"approved": false,
"verified": false,
"addedByUserId": "api",
"createdAt": "2024-01-20T15:45:00Z",
"updatedAt": "2024-01-20T15:45:00Z"
}Error Responses:
401 Unauthorized- Missing or invalid authentication403 Forbidden- Insufficient XP to create waypoint400 Bad Request- Missing required fields or invalid data
GET /api/waypoints/[id]
Get a specific waypoint by ID, including its change logs.
Authentication: Not required
URL Parameters:
id(number) - Waypoint ID
Example Request:
curl https://bubblymaps.org/api/waypoints/42Response:
{
"waypoint": {
"id": 42,
"name": "Bryant Park Fountain",
"latitude": 40.7536,
"longitude": -73.9832,
"description": "Modern fountain in the park",
"amenities": ["accessible", "filtered"],
"region": "Manhattan",
"approved": true,
"verified": true,
"addedByUserId": "user456",
"createdAt": "2024-01-20T15:45:00Z",
"updatedAt": "2024-01-21T10:00:00Z"
},
"logs": [
{
"id": 1,
"bubblerId": 42,
"userId": "user456",
"action": "created",
"timestamp": "2024-01-20T15:45:00Z"
},
{
"id": 2,
"bubblerId": 42,
"userId": "moderator123",
"action": "approved",
"timestamp": "2024-01-21T10:00:00Z"
}
]
}Error Responses:
404 Not Found- Waypoint does not exist400 Bad Request- Invalid waypoint ID
PATCH /api/waypoints/[id]
Update an existing waypoint.
Authentication: Required (Session or API Token)
URL Parameters:
id(number) - Waypoint ID
Request Body:
Any combination of the fields from POST /api/waypoints. Only provided fields will be updated.
Example Request:
curl -X PATCH https://bubblymaps.org/api/waypoints/42 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
"description": "Updated description with more details",
"verified": true
}'XP Requirements:
Regular users need sufficient XP to edit waypoints. API tokens bypass this requirement.
Response:
{
"id": 42,
"name": "Bryant Park Fountain",
"latitude": 40.7536,
"longitude": -73.9832,
"description": "Updated description with more details",
"amenities": ["accessible", "filtered"],
"region": "Manhattan",
"approved": true,
"verified": true,
"addedByUserId": "user456",
"createdAt": "2024-01-20T15:45:00Z",
"updatedAt": "2024-01-22T12:30:00Z"
}Error Responses:
401 Unauthorized- Missing or invalid authentication403 Forbidden- Insufficient XP to edit waypoint400 Bad Request- Invalid data404 Not Found- Waypoint does not exist
GET /api/waypoints/search
Search for waypoints by name or other criteria.
Authentication: Not required
Query Parameters:
q(string, required) - Search query string
Example Request:
curl "https://bubblymaps.org/api/waypoints/search?q=park"Response:
{
"waypoints": [
{
"id": 42,
"name": "Bryant Park Fountain",
"latitude": 40.7536,
"longitude": -73.9832,
"description": "Modern fountain in the park",
"region": "Manhattan"
},
{
"id": 43,
"name": "Central Park North Fountain",
"latitude": 40.7967,
"longitude": -73.9519,
"description": "Fountain in Central Park",
"region": "Manhattan"
}
]
}Error Responses:
500 Internal Server Error- Search failed
Data Model
Waypoint Object
| Field | Type | Description |
|---|---|---|
id | number | Unique identifier |
name | string | Name of the waypoint |
latitude | number | Latitude coordinate |
longitude | number | Longitude coordinate |
description | string | Description of the waypoint |
amenities | string[] | Array of amenities |
image | string | URL to waypoint image |
maintainer | string | Maintenance entity |
region | string | Geographic region |
approved | boolean | Approval status |
verified | boolean | Verification status |
addedByUserId | string | Creator user ID |
createdAt | string | Creation timestamp (ISO 8601) |
updatedAt | string | Last update timestamp (ISO 8601) |
Usage Examples
JavaScript/Fetch - Get All Waypoints
async function getAllWaypoints() {
const response = await fetch('https://bubblymaps.org/api/waypoints');
if (!response.ok) {
throw new Error('Failed to fetch waypoints');
}
const data = await response.json();
return data.waypoints;
}
// Usage
getAllWaypoints()
.then(waypoints => {
console.log(`Found ${waypoints.length} waypoints`);
waypoints.forEach(wp => {
console.log(`${wp.name} at (${wp.latitude}, ${wp.longitude})`);
});
})
.catch(error => console.error('Error:', error));JavaScript/Fetch - Create Waypoint with Error Handling
async function createWaypoint(waypointData) {
try {
const response = await fetch('https://bubblymaps.org/api/waypoints', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_TOKEN'
},
body: JSON.stringify(waypointData)
});
if (response.status === 403) {
throw new Error('Insufficient XP to create waypoint');
}
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || 'Failed to create waypoint');
}
return await response.json();
} catch (error) {
console.error('Error creating waypoint:', error);
throw error;
}
}
// Usage
createWaypoint({
name: 'New Park Fountain',
latitude: 40.7589,
longitude: -73.9851,
description: 'Clean water fountain in the park',
amenities: ['accessible', 'cold-water'],
region: 'Manhattan'
})
.then(data => console.log('Created waypoint:', data))
.catch(error => console.error('Failed:', error));Python - Search and Filter Waypoints
import requests
def search_waypoints_by_region(query, region=None):
"""Search for waypoints and optionally filter by region"""
url = f"https://bubblymaps.org/api/waypoints/search?q={query}"
response = requests.get(url)
if response.status_code != 200:
raise Exception(f"Search failed: {response.status_code}")
waypoints = response.json()['waypoints']
# Client-side filtering by region if needed
if region:
waypoints = [wp for wp in waypoints if wp.get('region') == region]
return waypoints
# Usage
results = search_waypoints_by_region('fountain', region='Manhattan')
print(f"Found {len(results)} fountains in Manhattan")
for wp in results:
print(f"- {wp['name']}: {wp.get('description', 'No description')}")Python - Update Waypoint
import requests
def update_waypoint(waypoint_id, updates, api_token):
"""Update a waypoint with new information"""
url = f"https://bubblymaps.org/api/waypoints/{waypoint_id}"
headers = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {api_token}'
}
response = requests.patch(url, json=updates, headers=headers)
if response.status_code == 404:
raise Exception(f"Waypoint {waypoint_id} not found")
elif response.status_code == 403:
raise Exception("Insufficient XP to edit waypoint")
elif response.status_code != 200:
raise Exception(f"Update failed: {response.status_code}")
return response.json()
# Usage
try:
updated = update_waypoint(
waypoint_id=42,
updates={
'description': 'Recently renovated fountain with cold water',
'amenities': ['accessible', 'cold-water', 'bottle-filler']
},
api_token='your_api_token_here'
)
print(f"Updated waypoint: {updated['name']}")
except Exception as e:
print(f"Error: {e}")Use Cases
The Waypoints API is useful for:
- Mobile Apps - Display water fountains on a map
- Navigation - Help users find the nearest fountain
- Data Collection - Crowdsource fountain locations
- Verification - Allow community verification of data
- Integration - Sync fountain data with other services
- Analytics - Track fountain distribution and usage
Best Practices
Creating Waypoints
- Verify coordinates - Ensure latitude and longitude are correct
- Add descriptions - Help users know what to expect
- Include amenities - Make fountains easier to find for specific needs
- Add photos - Visual confirmation helps users identify fountains
- Specify region - Helps with geographic filtering
Updating Waypoints
- Only update what changed - Send only modified fields
- Check verification status - Verified waypoints may need moderator review
- Add detailed descriptions - More information helps the community
- Keep photos current - Update images if the fountain changes
Searching
- Use specific terms - Better search results with specific queries
- Cache results - Don't repeatedly search for the same terms
- Handle empty results - Always check if results array is empty
Rate Limiting
While the API currently doesn't enforce strict rate limits, please be respectful:
- Cache responses when possible
- Batch requests instead of making many individual calls
- Use search instead of fetching all waypoints repeatedly
- Maximum 100 requests per minute recommended
Error Response Format
All error responses follow this format:
{
"error": "Error message description",
"code": "ERROR_CODE",
"details": {
"field": "Additional context"
}
}Common error codes:
INSUFFICIENT_XP- User doesn't have enough XPINVALID_COORDINATES- Coordinates out of valid rangeINVALID_INPUT- Missing or malformed dataNOT_FOUND- Resource doesn't existUNAUTHORIZED- Authentication required or invalid