Skip to main content

Making API Requests

This guide will help you understand how to make requests to the TimetableMaster API, handle responses, and implement best practices for reliable integration.

Base URL and Endpoints

All API requests should be made to our base URL:

https://www.timetablemaster.com/api/v1/

Available Endpoints

EndpointMethodDescription
/timetablesGETList all timetables
/timetables/{id}GETGet specific timetable data
/teachers/{id}/scheduleGETGet teacher schedule
/classes/{id}/scheduleGETGet class schedule
/rooms/{id}/allocationGETGet room allocation

Request Format

Required Headers

Every request must include these headers:

Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

HTTP Methods

The TimetableMaster API currently supports:

  • GET: Retrieve data (all current endpoints)
  • POST: Create data (future endpoints)
  • PUT: Update data (future endpoints)
  • DELETE: Remove data (future endpoints)

Response Format

All API responses follow a consistent JSON structure:

Success Response

{
"success": true,
"data": {
// Response data here
},
"timestamp": "2024-07-15T10:30:00.000Z"
}

Error Response

{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human readable error message"
},
"timestamp": "2024-07-15T10:30:00.000Z"
}

Making Your First Request

Let's start with a simple request to list all timetables:

Step 1: Set Up Your Request

curl -X GET \
'https://www.timetablemaster.com/api/v1/timetables' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json'

Step 2: Examine the Response

{
"success": true,
"data": {
"orgId": "your-org-id",
"timetables": [
{
"id": "tt_12345",
"name": "Term 1 2025",
"status": "published",
"createdAt": "2025-01-15T08:00:00.000Z",
"updatedAt": "2025-01-20T14:30:00.000Z"
}
]
},
"timestamp": "2024-07-15T10:30:00.000Z"
}

Step 3: Get Detailed Timetable Data

Use the timetable ID from the previous response:

curl -X GET \
'https://www.timetablemaster.com/api/v1/timetables/tt_12345' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json'

Programming Language Examples

JavaScript/Node.js

Using fetch (Browser/Node.js 18+)

const API_KEY = "your_api_key_here";
const BASE_URL = "https://www.timetablemaster.com/api/v1";

async function getTimetables() {
try {
const response = await fetch(`${BASE_URL}/timetables`, {
method: "GET",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
});

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

const data = await response.json();

if (data.success) {
return data.data.timetables;
} else {
throw new Error(`API error: ${data.error.message}`);
}
} catch (error) {
console.error("Error fetching timetables:", error);
throw error;
}
}

// Usage
getTimetables()
.then((timetables) => {
console.log("Available timetables:", timetables);
})
.catch((error) => {
console.error("Failed to fetch timetables:", error);
});

Using axios

const axios = require("axios");

const api = axios.create({
baseURL: "https://www.timetablemaster.com/api/v1",
headers: {
Authorization: `Bearer ${process.env.TIMETABLE_API_KEY}`,
"Content-Type": "application/json",
},
});

// Add response interceptor for error handling
api.interceptors.response.use(
(response) => response.data,
(error) => {
if (error.response) {
throw new Error(`API Error: ${error.response.data.error.message}`);
} else if (error.request) {
throw new Error("Network error: No response received");
} else {
throw new Error(`Request error: ${error.message}`);
}
}
);

async function getSpecificTimetable(timetableId) {
try {
const response = await api.get(`/timetables/${timetableId}`);
return response.data;
} catch (error) {
console.error("Error:", error.message);
throw error;
}
}

Python

Using requests

import requests
import os
from typing import Dict, List, Optional

class TimetableMasterAPI:
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = 'https://www.timetablemaster.com/api/v1'
self.headers = {
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json'
}

def _make_request(self, endpoint: str) -> Dict:
"""Make a GET request to the API"""
url = f"{self.base_url}/{endpoint}"

try:
response = requests.get(url, headers=self.headers, timeout=30)
response.raise_for_status()

data = response.json()

if not data.get('success'):
raise Exception(f"API Error: {data.get('error', {}).get('message', 'Unknown error')}")

return data['data']

except requests.exceptions.RequestException as e:
raise Exception(f"Request failed: {str(e)}")
except ValueError as e:
raise Exception(f"Invalid JSON response: {str(e)}")

def get_timetables(self) -> List[Dict]:
"""Get list of all timetables"""
data = self._make_request('timetables')
return data['timetables']

def get_timetable(self, timetable_id: str) -> Dict:
"""Get specific timetable data"""
return self._make_request(f'timetables/{timetable_id}')

# Usage
api_key = os.getenv('TIMETABLE_API_KEY')
api = TimetableMasterAPI(api_key)

try:
# Get all timetables
timetables = api.get_timetables()
print(f"Found {len(timetables)} timetables")

# Get detailed data for the first timetable
if timetables:
first_timetable = api.get_timetable(timetables[0]['id'])
print(f"Timetable '{first_timetable['name']}' has {len(first_timetable['schedule'])} scheduled slots")

except Exception as e:
print(f"Error: {e}")

PHP

<?php

class TimetableMasterAPI {
private $apiKey;
private $baseUrl = 'https://www.timetablemaster.com/api/v1';

public function __construct($apiKey) {
$this->apiKey = $apiKey;
}

private function makeRequest($endpoint) {
$url = $this->baseUrl . '/' . $endpoint;

$headers = [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);

if ($error) {
throw new Exception("cURL error: " . $error);
}

if ($httpCode !== 200) {
throw new Exception("HTTP error: " . $httpCode);
}

$data = json_decode($response, true);

if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception("JSON decode error: " . json_last_error_msg());
}

if (!$data['success']) {
throw new Exception("API error: " . $data['error']['message']);
}

return $data['data'];
}

public function getTimetables() {
$data = $this->makeRequest('timetables');
return $data['timetables'];
}

public function getTimetable($timetableId) {
return $this->makeRequest('timetables/' . $timetableId);
}
}

// Usage
try {
$apiKey = $_ENV['TIMETABLE_API_KEY'] ?? '';
$api = new TimetableMasterAPI($apiKey);

// Get all timetables
$timetables = $api->getTimetables();
echo "Found " . count($timetables) . " timetables\n";

// Get detailed data for the first timetable
if (!empty($timetables)) {
$timetable = $api->getTimetable($timetables[0]['id']);
echo "Timetable '" . $timetable['name'] . "' has " . count($timetable['schedule']) . " scheduled slots\n";
}

} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
?>

Best Practices

1. Error Handling

Always implement proper error handling:

async function safeTimetableRequest(timetableId) {
try {
const response = await fetch(`/api/v1/timetables/${timetableId}`, {
headers: { Authorization: `Bearer ${apiKey}` },
});

if (!response.ok) {
// Handle HTTP errors
if (response.status === 401) {
throw new Error("Invalid API key");
} else if (response.status === 404) {
throw new Error("Timetable not found");
} else if (response.status === 429) {
throw new Error("Rate limit exceeded");
} else {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
}

const data = await response.json();

if (!data.success) {
throw new Error(`API Error: ${data.error.message}`);
}

return data.data;
} catch (error) {
console.error("Timetable request failed:", error);
// Handle error appropriately (show user message, retry, etc.)
throw error;
}
}

2. Rate Limiting

Respect rate limits and implement retry logic:

import time
import random

def make_request_with_retry(url, headers, max_retries=3):
for attempt in range(max_retries + 1):
try:
response = requests.get(url, headers=headers)

if response.status_code == 429:
# Rate limited - wait and retry
if attempt < max_retries:
wait_time = (2 ** attempt) + random.uniform(0, 1)
time.sleep(wait_time)
continue
else:
raise Exception("Rate limit exceeded - max retries reached")

response.raise_for_status()
return response.json()

except requests.exceptions.RequestException as e:
if attempt < max_retries:
time.sleep(1)
continue
raise e

3. Response Caching

Cache responses to reduce API calls:

class TimetableCache {
constructor(ttlMinutes = 30) {
this.cache = new Map();
this.ttl = ttlMinutes * 60 * 1000; // Convert to milliseconds
}

get(key) {
const item = this.cache.get(key);
if (!item) return null;

if (Date.now() > item.expiry) {
this.cache.delete(key);
return null;
}

return item.data;
}

set(key, data) {
this.cache.set(key, {
data,
expiry: Date.now() + this.ttl,
});
}
}

const cache = new TimetableCache(30); // 30 minute cache

async function getCachedTimetable(timetableId) {
const cacheKey = `timetable_${timetableId}`;

// Check cache first
let timetable = cache.get(cacheKey);
if (timetable) {
return timetable;
}

// Fetch from API
timetable = await fetchTimetableFromAPI(timetableId);

// Store in cache
cache.set(cacheKey, timetable);

return timetable;
}

4. Request Timeouts

Always set appropriate timeouts:

const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout

try {
const response = await fetch("/api/v1/timetables", {
headers: { Authorization: `Bearer ${apiKey}` },
signal: controller.signal,
});

clearTimeout(timeoutId);
return await response.json();
} catch (error) {
clearTimeout(timeoutId);
if (error.name === "AbortError") {
throw new Error("Request timeout");
}
throw error;
}

Testing Your Integration

1. Test Authentication

# Test with valid API key
curl -H "Authorization: Bearer YOUR_VALID_API_KEY" \
https://www.timetablemaster.com/api/v1/timetables

# Test with invalid API key (should return 401)
curl -H "Authorization: Bearer invalid_key" \
https://www.timetablemaster.com/api/v1/timetables

2. Test Error Handling

# Test with non-existent timetable ID (should return 404)
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://www.timetablemaster.com/api/v1/timetables/non_existent_id

3. Monitor Response Times

# Use curl to measure response time
curl -w "Time: %{time_total}s\n" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o /dev/null -s \
https://www.timetablemaster.com/api/v1/timetables

Next Steps

Now that you understand how to make requests:

  1. Explore specific API endpoints