Authentication & Security
Learn how to authenticate API requests, manage API keys, and implement security best practices for Schoolyst integration.
Authentication & Security
Schoolyst uses API key-based authentication to secure all API requests. This guide covers everything you need to know about authenticating with our API and keeping your integration secure.
Overview
All API requests must include a valid API key in the request headers. Schoolyst supports two types of authentication:
- API Key Authentication - For server-to-server communication (recommended)
- OAuth 2.0 - For third-party applications requiring user authorization
API Key Authentication
Getting Your API Key
Access API Settings
- Log in to your Schoolyst dashboard
- Navigate to Settings → API & Integrations
- You'll see the API Management section
Generate New API Key
- Click Generate New API Key
- Give your key a descriptive name (e.g., "Production App", "Mobile App")
- Select the appropriate permissions/scopes
- Click Create
Save Your Credentials
You'll receive:
- API Key - Your public identifier
- API Secret - Your private key (shown only once)
Important
Save your API Secret immediately! It will only be displayed once. If you lose it, you'll need to generate a new key pair.
Using API Keys
Include your API key in the Authorization header of every request:
curl -X GET https://api.schoolyst.com/v1/students \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json"const apiKey = process.env.SCHOOLYST_API_KEY;
const response = await fetch("https://api.schoolyst.com/v1/students", {
method: "GET",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
});
const data = await response.json();import os
import requests
api_key = os.getenv('SCHOOLYST_API_KEY')
headers = {
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json'
}
response = requests.get(
'https://api.schoolyst.com/v1/students',
headers=headers
)
data = response.json()<?php
$api_key = getenv('SCHOOLYST_API_KEY');
$ch = curl_init('https://api.schoolyst.com/v1/students');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $api_key,
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$data = json_decode($response, true);
curl_close($ch);
?>API Key Scopes & Permissions
When creating an API key, you can limit its access to specific resources:
| Scope | Description | Permissions |
|---|---|---|
students:read | View student information | GET students, profiles |
students:write | Create and update students | POST, PUT, DELETE students |
attendance:read | View attendance records | GET attendance data |
attendance:write | Mark and modify attendance | POST, PUT attendance |
academic:read | View classes, subjects | GET academic data |
academic:write | Manage academic data | POST, PUT, DELETE academic |
library:read | View library records | GET library data |
library:write | Manage library operations | POST, PUT library |
reports:read | Access reports and analytics | GET reports |
admin:all | Full administrative access | All operations |
Principle of Least Privilege
Always grant the minimum permissions required for your application. This reduces security risks if a key is compromised.
OAuth 2.0 Authentication
For third-party applications that need to access user data on behalf of users, use OAuth 2.0.
OAuth Flow
Register Your Application
- Go to Settings → OAuth Applications
- Click New Application
- Provide application details:
- Application name
- Redirect URI(s)
- Application description
- Logo (optional)
Get OAuth Credentials
After registration, you'll receive:
- Client ID - Your application's public identifier
- Client Secret - Your application's private key
Implement OAuth Flow
Use the standard OAuth 2.0 authorization code flow:
- Redirect user to authorization URL:
https://accounts.schoolyst.com/oauth/authorize?
client_id=YOUR_CLIENT_ID&
redirect_uri=YOUR_REDIRECT_URI&
response_type=code&
scope=students:read attendance:read&
state=RANDOM_STATE_STRING-
User grants permission
-
Exchange code for access token:
curl -X POST https://accounts.schoolyst.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=AUTHORIZATION_CODE" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "redirect_uri=YOUR_REDIRECT_URI"- Use access token for API requests:
const response = await fetch("https://api.schoolyst.com/v1/students", {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});Token Refresh
Access tokens expire after 1 hour. Use the refresh token to get a new access token:
curl -X POST https://accounts.schoolyst.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "refresh_token=YOUR_REFRESH_TOKEN" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"Security Best Practices
1. Store Credentials Securely
Never expose credentials
Never commit API keys or secrets to version control or expose them in client-side code.
Use Environment Variables:
// .env file
SCHOOLYST_API_KEY = your_api_key_here;
SCHOOLYST_API_SECRET = your_api_secret_here;
// app.js
require("dotenv").config();
const apiKey = process.env.SCHOOLYST_API_KEY;# .env file
SCHOOLYST_API_KEY=your_api_key_here
SCHOOLYST_API_SECRET=your_api_secret_here
# app.py
import os
from dotenv import load_dotenv
load_dotenv()
api_key = os.getenv('SCHOOLYST_API_KEY')// .env file
SCHOOLYST_API_KEY=your_api_key_here
SCHOOLYST_API_SECRET=your_api_secret_here
// app.php
$api_key = getenv('SCHOOLYST_API_KEY');2. Use HTTPS Only
Always use HTTPS for API requests. HTTP requests will be rejected.
// ✅ Good
const url = "https://api.schoolyst.com/v1/students";
// ❌ Bad - Will fail
const url = "http://api.schoolyst.com/v1/students";3. Implement Rate Limiting
Respect API rate limits to avoid throttling:
- Standard: 1000 requests/hour per API key
- Premium: 5000 requests/hour per API key
- Enterprise: Custom limits
Monitor rate limit headers in responses:
const response = await fetch("https://api.schoolyst.com/v1/students");
console.log(response.headers.get("X-RateLimit-Limit")); // 1000
console.log(response.headers.get("X-RateLimit-Remaining")); // 995
console.log(response.headers.get("X-RateLimit-Reset")); // 17000000004. Rotate API Keys Regularly
Rotate your API keys every 90 days or immediately if compromised:
- Generate a new API key
- Update your application with the new key
- Test thoroughly
- Revoke the old key
5. Use Webhooks for Real-time Updates
Instead of polling, use webhooks to receive real-time notifications:
// Webhook endpoint
app.post("/webhooks/schoolyst", (req, res) => {
const signature = req.headers["x-schoolyst-signature"];
// Verify webhook signature
if (verifySignature(req.body, signature)) {
const event = req.body;
// Process event
console.log("Event received:", event.type);
}
res.status(200).send("OK");
});6. Validate Webhook Signatures
Always verify webhook signatures to ensure requests are from Schoolyst:
const crypto = require("crypto");
function verifyWebhookSignature(payload, signature, secret) {
const hmac = crypto.createHmac("sha256", secret);
const digest = hmac.update(JSON.stringify(payload)).digest("hex");
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest));
}import hmac
import hashlib
import json
def verify_webhook_signature(payload, signature, secret):
digest = hmac.new(
secret.encode(),
json.dumps(payload).encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, digest)<?php
function verifyWebhookSignature($payload, $signature, $secret) {
$digest = hash_hmac(
'sha256',
json_encode($payload),
$secret
);
return hash_equals($signature, $digest);
}
?>Error Handling
Handle authentication errors gracefully:
async function makeAuthenticatedRequest(url) {
try {
const response = await fetch(url, {
headers: {
Authorization: `Bearer ${apiKey}`,
},
});
if (response.status === 401) {
throw new Error("Invalid or expired API key");
}
if (response.status === 403) {
throw new Error("Insufficient permissions");
}
if (response.status === 429) {
const resetTime = response.headers.get("X-RateLimit-Reset");
throw new Error(`Rate limit exceeded. Resets at ${resetTime}`);
}
return await response.json();
} catch (error) {
console.error("Authentication error:", error);
throw error;
}
}Common Authentication Errors
| Status Code | Error | Solution |
|---|---|---|
| 401 | UNAUTHORIZED | Check your API key is correct and active |
| 403 | FORBIDDEN | Verify your API key has required permissions |
| 429 | RATE_LIMIT_EXCEEDED | Wait until rate limit resets or upgrade plan |
| 498 | TOKEN_EXPIRED | Refresh your OAuth token |
| 499 | TOKEN_REQUIRED | Include Authorization header in request |
Testing Authentication
Test your authentication setup:
async function testAuthentication() {
try {
const response = await fetch("https://api.schoolyst.com/v1/auth/verify", {
headers: {
Authorization: `Bearer ${process.env.SCHOOLYST_API_KEY}`,
},
});
const result = await response.json();
if (result.success) {
console.log("✅ Authentication successful");
console.log("Permissions:", result.data.scopes);
} else {
console.error("❌ Authentication failed:", result.error);
}
} catch (error) {
console.error("❌ Request failed:", error);
}
}
testAuthentication();import os
import requests
def test_authentication():
api_key = os.getenv('SCHOOLYST_API_KEY')
try:
response = requests.get(
'https://api.schoolyst.com/v1/auth/verify',
headers={'Authorization': f'Bearer {api_key}'}
)
result = response.json()
if result['success']:
print('✅ Authentication successful')
print('Permissions:', result['data']['scopes'])
else:
print('❌ Authentication failed:', result['error'])
except Exception as error:
print('❌ Request failed:', error)
test_authentication()Next Steps
API Reference
Explore all available API endpoints
Webhooks
Set up real-time event notifications
Rate Limits
Understand API usage limits
Security Guide
Advanced security practices
Need Help?
If you're experiencing authentication issues, contact our support team at support@schoolyst.com with your API key ID (not the full key).