Skip to main content

Authentication

The TimetableMaster API uses API key authentication to secure access to your timetable data. This guide will help you set up authentication for your applications.

Generating an API Key​

API access is switched on per organisation. If a key is refused with "API access is not enabled for this organisation", contact support to have it enabled.

Step 1: Access Your Dashboard​

  1. Log in to your TimetableMaster account
  2. Navigate to Settings → API Keys
  3. Click Generate New API Key

Step 2: Configure Your API Key​

  • Name: Give your API key a descriptive name (e.g., "School Website", "Mobile App")
  • Expires At: Optionally set an expiration date for enhanced security

Step 3: Save Your API Key​

Important: Copy and store your API key securely immediately after generation. For security reasons, you won't be able to view the full key again.

ttm_1234567890abcdef1234567890abcdef12345678

Using Your API Key​

Authentication Header​

Include your API key in the Authorization header of every API request:

Authorization: Bearer ttm_1234567890abcdef1234567890abcdef12345678

Example Request​

curl -H "Authorization: Bearer ttm_1234567890abcdef1234567890abcdef12345678" \
-H "Content-Type: application/json" \
https://api.timetablemaster.com/api/v1/timetables

Security Best Practices​

Environment Variables​

Store your API key in environment variables, never hardcode it in your application:

// ✅ Good
const apiKey = process.env.TIMETABLE_API_KEY;

// ❌ Bad
const apiKey = "ttm_1234567890abcdef..."; // Never do this!

Secure Storage​

  • Use secure environment variable management
  • Never commit API keys to version control
  • Rotate keys regularly for enhanced security
  • Use different keys for different environments (development, staging, production)

Network Security​

  • Always use HTTPS for API requests
  • Implement proper error handling to avoid exposing keys in logs
  • Consider IP restrictions if your application runs from fixed locations

Key Management​

Multiple Keys​

You can create multiple API keys for different purposes:

  • One for your website integration
  • Another for your mobile app
  • Separate keys for development and production

Key Rotation​

Regularly rotate your API keys for security:

  1. Generate a new API key
  2. Update your applications to use the new key
  3. Revoke the old key once all applications are updated

Revoking Keys​

If a key is compromised or no longer needed:

  1. Go to Settings → API Keys
  2. Find the key and click Revoke
  3. The key will be immediately deactivated

Authentication Errors​

Key and access errors (401)​

Every problem with the key itself returns 401 with the code INVALID_API_KEY. The message says which problem it is:

messageCause
Invalid or inactive API keyThe key does not exist or was revoked
API key has expiredThe key's expiry date has passed. Generate a new one
API access is not enabled for this organisation. Contact support to request it.API access is switched off for your organisation. Keys issued earlier stop working too
Authentication requiredNo Authorization: Bearer ttm_… header was sent
{
"success": false,
"error": {
"code": "INVALID_API_KEY",
"message": "Invalid or inactive API key"
},
"timestamp": "2026-10-06T10:00:00.000Z"
}

Access ended (402)​

When your organisation's access has ended (the trial is over, or the plan was not renewed) or the account is suspended, every request returns 402, whatever the key. This body has a different shape from other errors: error is the message itself, not an object.

{
"code": "ACCESS_EXPIRED",
"access": "locked",
"lockedBecause": "plan_ended",
"error": "Your plan was not renewed. Renew to keep using TimetableMaster."
}
FieldValues
codeACCESS_EXPIRED, or ACCOUNT_SUSPENDED
accesslocked or suspended
lockedBecausetrial_ended, plan_ended or payment_failed; null when suspended

The same key works again as soon as access is restored. You do not need a new one.

Testing Your Authentication​

Quick Test​

Test your API key with this simple request:

curl -H "Authorization: Bearer YOUR_API_KEY" \
https://api.timetablemaster.com/api/v1/timetables

Expected Response​

If authentication is successful, you'll receive your organisation's timetable versions:

{
"success": true,
"data": {
"orgId": "6913a0c4e1b2f3a4b5c6d7e8",
"count": 1,
"timetables": [
{
"id": "6a34108b1d16898202940188",
"name": "Term 1 2026",
"groupId": "6a3410551d16898202940101",
"versionNumber": 3,
"versionName": null,
"status": "published",
"isCurrent": true,
"publishedAt": "2026-08-28T07:15:00.000Z",
"effectiveFrom": 20260901,
"effectiveTo": null,
"schedulingMode": "standard",
"createdAt": "2026-07-01T09:12:00.000Z",
"updatedAt": "2026-08-28T07:15:00.000Z"
}
]
},
"timestamp": "2026-10-06T10:00:00.000Z"
}

See List Timetables for every field.

Programming Language Examples​

JavaScript/Node.js​

const axios = require("axios");

const apiKey = process.env.TIMETABLE_API_KEY;
const baseURL = "https://api.timetablemaster.com/api/v1";

const api = axios.create({
baseURL,
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
});

// Usage
async function getTimetables() {
try {
const response = await api.get("/timetables");
return response.data;
} catch (error) {
console.error("API Error:", error.response.data);
throw error;
}
}

Python​

import requests
import os

API_KEY = os.getenv('TIMETABLE_API_KEY')
BASE_URL = 'https://api.timetablemaster.com/api/v1'

headers = {
'Authorization': f'Bearer {API_KEY}',
'Content-Type': 'application/json'
}

def get_timetables():
response = requests.get(f'{BASE_URL}/timetables', headers=headers)

if response.status_code == 200:
return response.json()
else:
print(f'Error: {response.status_code} - {response.json()}')
return None

PHP​

<?php
$apiKey = $_ENV['TIMETABLE_API_KEY'];
$baseUrl = 'https://api.timetablemaster.com/api/v1';

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

function getTimetables() {
global $baseUrl, $headers;

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $baseUrl . '/timetables');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

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

if ($httpCode === 200) {
return json_decode($response, true);
}

return null;
}
?>

Next: Learn how to make your first API request and explore the available endpoints.