API Guidelines

Best practices, caching recommendations, and what to expect when integrating with the RadioMV API.

Overview

The RadioMV API consists of static JSON files hosted on Cloudflare. This means:

Do's

Always fetch schedule URLs from app config Never hardcode schedule URLs. Always fetch appv2.json first and use the stationScheduleUrl field from each station. This ensures your app automatically gets the correct URLs when we release new versions.

Recommended Flow

// 1. Fetch app config (hardcode only this URL)
const config = await fetch('https://api.radiomv.studio/appv2.json');
const data = await config.json();

// 2. Get schedule URL from station object
const station = data.stations.find(s => s.id === "1");
const scheduleUrl = station.stationScheduleUrl;

// 3. Fetch schedule using the URL from config
const schedule = await fetch(scheduleUrl);
const programs = (await schedule.json()).schedule;
Cache responses appropriately Schedule files change ~3 times per year. App configuration changes more frequently but not constantly. Cache aggressively.

Caching Recommendations

File Update Frequency Recommended Cache
appv1.json Weekly to monthly 24 hours, check version on app launch
Schedule files ~3 times per year 7 days, check lastUpdated periodically

Implementation Best Practices

Version Checking Example

// Smart fetching with version check
async function fetchWithVersionCheck(url, cachedData) {
    try {
        const response = await fetch(url);
        const data = await response.json();

        // For appv1.json
        if (data.config?.version === cachedData?.config?.version) {
            return cachedData; // No changes
        }

        // For schedule files
        if (data.lastUpdated === cachedData?.lastUpdated) {
            return cachedData; // No changes
        }

        return data; // New data
    } catch (error) {
        return cachedData; // Fallback to cache
    }
}

Don'ts

Avoid these common mistakes Following these guidelines ensures your integration remains stable and performant.

Things to Avoid

What to Expect

Update Frequency

Change Type Frequency Examples
Artwork updates Seasonally (~4x/year) Holiday themes, seasonal artwork
Schedule changes Rarely (~3x/year) New programs, time slot changes
Stream URL changes Very rare Infrastructure updates
New stations Very rare New language or channel launch
Schema changes Very rare New fields, structure changes

Breaking Changes Policy

We follow semantic versioning for schedule files:

Backwards Compatibility We strive to maintain backwards compatibility. New fields will be added as optional. Existing fields will not be removed without a major version bump.

Availability

Error Handling

Recommended Pattern

async function loadStationData() {
    const CACHE_KEY = 'radiomv_app_config';

    try {
        // Try to fetch fresh data
        const response = await fetch(
            'https://api.radiomv.studio/appv1.json',
            { timeout: 10000 }
        );

        if (!response.ok) {
            throw new Error(`HTTP ${response.status}`);
        }

        const data = await response.json();

        // Validate essential fields exist
        if (!data.stations || !Array.isArray(data.stations)) {
            throw new Error('Invalid response structure');
        }

        // Cache the valid response
        localStorage.setItem(CACHE_KEY, JSON.stringify(data));

        return data;

    } catch (error) {
        console.warn('Failed to fetch, using cache:', error);

        // Fall back to cached data
        const cached = localStorage.getItem(CACHE_KEY);
        if (cached) {
            return JSON.parse(cached);
        }

        // Fall back to bundled data
        return require('./fallback-config.json');
    }
}

Timezone Handling

All schedule times are in America/Los_Angeles (Pacific Time). To display in the user's local timezone:

function convertToLocalTime(timeStr, stationTimezone) {
    // timeStr is "HH:MM" format
    const [hours, minutes] = timeStr.split(':').map(Number);

    // Create date in station timezone
    const today = new Date();
    const dateStr = today.toISOString().split('T')[0];

    const stationDate = new Date(
        `${dateStr}T${timeStr}:00`
    );

    // Format in user's local timezone
    return stationDate.toLocaleTimeString('en-US', {
        hour: 'numeric',
        minute: '2-digit',
        timeZone: stationTimezone,
        timeZoneName: 'short'
    });
}

Support

For API issues or questions: