@swimmable/sdk
v1.0.0
Published
Official JavaScript/TypeScript SDK for the Swimmable API - Real-time swimming conditions and water quality data
Downloads
7
Maintainers
Readme
Swimmable JavaScript/TypeScript SDK
Official JavaScript/TypeScript SDK for the Swimmable API - Get real-time swimming conditions, water quality data, and AI-powered safety scores for beaches, lakes, and pools worldwide.
Features
- 🏊 Real-time Swimming Conditions - Water temperature, weather, and safety data
- 🌊 Enhanced Analysis - AI-powered swimmability scores and detailed breakdowns
- 🏖️ Global Coverage - 15,000+ beaches, lakes, and swimming spots worldwide
- 🔒 Type Safe - Full TypeScript support with comprehensive type definitions
- ⚡ Modern - Promise-based API with async/await support
- 🚀 Lightweight - Minimal dependencies, works in Node.js and browsers
- 📱 Cross-platform - Works in browsers, Node.js, React Native, and more
Installation
npm install @swimmable/sdkyarn add @swimmable/sdkpnpm add @swimmable/sdkQuick Start
Basic Usage (No API Key Required)
import { SwimmableClient } from '@swimmable/sdk';
const client = new SwimmableClient();
// Get current swimming conditions for Santa Monica Beach
const conditions = await client.getConditions({
lat: 34.0195,
lon: -118.4912
});
console.log(`Water temperature: ${conditions.waterTemperature}°C`);
console.log(`Air temperature: ${conditions.airTemperature}°C`);
console.log(`Weather: ${conditions.weatherDescription}`);Enhanced Conditions with Safety Scores
// Get detailed analysis with swimmability scoring
const enhanced = await client.getEnhancedConditions({
lat: 25.7617, // Miami Beach
lon: -80.1918
});
console.log(`Swimmability Score: ${enhanced.swimmabilityScore}/10`);
console.log(`Water Quality Score: ${enhanced.subscores.waterQuality}/10`);
console.log(`Safety Rating: ${enhanced.subscores.surfHazard}/10`);
// Check for any safety warnings
if (enhanced.warnings.length > 0) {
console.log('⚠️ Safety Warnings:', enhanced.warnings);
}With API Key (For Production Use)
const client = new SwimmableClient({
apiKey: 'your-api-key-here' // Get one at https://swimmable.app/signup
});
// Now you can access premium features and higher rate limits
const stats = await client.getUsageStats();
console.log(`API calls this month: ${stats.total_requests}`);API Reference
Client Configuration
interface SwimmableConfig {
apiKey?: string; // Your Swimmable API key
baseUrl?: string; // API base URL (defaults to https://api.swimmable.app)
timeout?: number; // Request timeout in ms (defaults to 10000)
headers?: Record<string, string>; // Custom headers
}Basic Methods
getConditions(coordinates, options?)
Get basic swimming conditions for a location.
const conditions = await client.getConditions({
lat: 34.0522,
lon: -118.2437
});
// Returns BasicConditions interface
interface BasicConditions {
airTemperature: number; // °C
waterTemperature: number; // °C
weatherDescription: string; // e.g., "sunny", "cloudy"
uvIndex: number; // 0-11+ UV index
windSpeed: number; // km/h
waveHeight: number; // meters
timestamp: string; // ISO 8601 timestamp
}getEnhancedConditions(coordinates, options?)
Get detailed analysis with AI-powered safety scores.
const enhanced = await client.getEnhancedConditions({
lat: 21.2765, // Waikiki Beach
lon: -157.8281
});
// Returns EnhancedConditions with swimmability scores, detailed conditions, and warningsgetSpots(options?)
Get list of available swimming spots.
const spots = await client.getSpots();
console.log(`Found ${spots.count} swimming spots`);
spots.spots.forEach(spot => {
console.log(`${spot.name} - ${spot.region}`);
});API Management (Requires API Key)
getUsageStats(days?, options?)
Get your API usage statistics.
const stats = await client.getUsageStats(30); // Last 30 days
console.log(`Total requests: ${stats.total_requests}`);
console.log(`Success rate: ${stats.successful_requests / stats.total_requests * 100}%`);getApiKeys(options?)
List your API keys.
const keys = await client.getApiKeys();
keys.forEach(key => {
console.log(`${key.name}: ${key.is_active ? 'Active' : 'Inactive'}`);
});createApiKey(keyData, options?)
Create a new API key.
const newKey = await client.createApiKey({
name: 'My App Key',
description: 'API key for my swimming app',
// expires_in_days: 365 // Optional expiration
});
console.log('New API key:', newKey.api_key);
// ⚠️ Save this key securely - you won't see it again!Utility Functions
The SDK includes helpful utility functions:
import { LocationUtils, ConditionsUtils, ApiKeyUtils } from '@swimmable/sdk';
// Distance calculation
const distance = LocationUtils.calculateDistance(
{ lat: 34.0522, lon: -118.2437 }, // Santa Monica
{ lat: 25.7617, lon: -80.1918 } // Miami
);
console.log(`Distance: ${distance.toFixed(2)} km`);
// Temperature conversion
const fahrenheit = ConditionsUtils.celsiusToFahrenheit(25);
console.log(`25°C = ${fahrenheit}°F`);
// Safety assessment
const isSafe = ConditionsUtils.isSafeForSwimming(enhancedConditions);
console.log(isSafe ? '✅ Safe to swim' : '⚠️ Check conditions carefully');
// API key validation
const isValidKey = ApiKeyUtils.validateApiKey('swm_1234567890abcdef...');Framework Examples
React Hook
import { useEffect, useState } from 'react';
import { SwimmableClient, BasicConditions } from '@swimmable/sdk';
const client = new SwimmableClient({ apiKey: 'your-key' });
function useSwimmingConditions(lat: number, lon: number) {
const [conditions, setConditions] = useState<BasicConditions | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
async function fetchConditions() {
try {
setLoading(true);
const data = await client.getConditions({ lat, lon });
setConditions(data);
setError(null);
} catch (err) {
setError(err instanceof Error ? err.message : 'Unknown error');
} finally {
setLoading(false);
}
}
fetchConditions();
}, [lat, lon]);
return { conditions, loading, error };
}
// Usage
function BeachConditions() {
const { conditions, loading, error } = useSwimmingConditions(34.0195, -118.4912);
if (loading) return <div>Loading conditions...</div>;
if (error) return <div>Error: {error}</div>;
if (!conditions) return null;
return (
<div>
<h2>Santa Monica Beach</h2>
<p>Water: {conditions.waterTemperature}°C</p>
<p>Air: {conditions.airTemperature}°C</p>
<p>Conditions: {conditions.weatherDescription}</p>
</div>
);
}Vue 3 Composition API
import { ref, onMounted } from 'vue';
import { SwimmableClient } from '@swimmable/sdk';
export function useSwimmingConditions(lat: number, lon: number) {
const client = new SwimmableClient();
const conditions = ref(null);
const loading = ref(true);
const error = ref(null);
const fetchConditions = async () => {
try {
loading.value = true;
conditions.value = await client.getConditions({ lat, lon });
} catch (err) {
error.value = err.message;
} finally {
loading.value = false;
}
};
onMounted(fetchConditions);
return { conditions, loading, error, refresh: fetchConditions };
}Express.js API
import express from 'express';
import { SwimmableClient } from '@swimmable/sdk';
const app = express();
const client = new SwimmableClient({ apiKey: process.env.SWIMMABLE_API_KEY });
app.get('/api/conditions/:lat/:lon', async (req, res) => {
try {
const { lat, lon } = req.params;
const conditions = await client.getConditions({
lat: parseFloat(lat),
lon: parseFloat(lon)
});
res.json(conditions);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000);Error Handling
The SDK throws descriptive errors that you can catch and handle:
import { SwimmableClient, SwimmableError } from '@swimmable/sdk';
const client = new SwimmableClient();
try {
const conditions = await client.getConditions({ lat: 91, lon: 0 }); // Invalid latitude
} catch (error) {
if (error instanceof SwimmableError) {
console.error(`API Error ${error.status}: ${error.message}`);
} else {
console.error('Unexpected error:', error);
}
}Rate Limiting
The SDK includes built-in rate limiting utilities:
import { RateLimiter } from '@swimmable/sdk';
const limiter = new RateLimiter(100, 60000); // 100 requests per minute
async function makeRequest() {
if (!limiter.canMakeRequest()) {
const resetTime = limiter.getResetTime();
throw new Error(`Rate limit exceeded. Try again in ${resetTime}ms`);
}
const conditions = await client.getConditions({ lat: 34, lon: -118 });
limiter.recordRequest();
return conditions;
}TypeScript Support
The SDK is written in TypeScript and includes comprehensive type definitions:
import {
SwimmableClient,
BasicConditions,
EnhancedConditions,
SwimmableConfig,
Coordinates,
SpotInfo
} from '@swimmable/sdk';
// All types are exported and documented
const config: SwimmableConfig = {
apiKey: 'your-key',
timeout: 5000
};
const client = new SwimmableClient(config);Browser Usage
The SDK works in all modern browsers. For older browsers, you may need to polyfill fetch:
<script src="https://unpkg.com/@swimmable/[email protected]/dist/index.umd.js"></script>
<script>
const client = new SwimmableSDK.SwimmableClient();
client.getConditions({ lat: 34.0522, lon: -118.2437 })
.then(conditions => {
console.log('Water temperature:', conditions.waterTemperature + '°C');
});
</script>API Key Management
- Get an API Key: Sign up at swimmable.app/signup
- Environment Variables: Store your API key securely
SWIMMABLE_API_KEY=your-api-key-here - Rate Limits: Free tier includes generous limits, paid plans available
- Security: Never expose API keys in client-side code
Contributing
We welcome contributions! Please see our Contributing Guide.
Support
- 📧 Email: [email protected]
- 📖 Documentation: swimmable.app/docs
- 🐛 Issues: GitHub Issues
- 💬 Community: Discord
License
MIT License - see LICENSE file for details.
Built with ❤️ by the Swimmable team. Making water activities safer worldwide! 🏊♀️🌊
