Schoolyst

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

  1. Log in to your Schoolyst dashboard
  2. Navigate to SettingsAPI & Integrations
  3. You'll see the API Management section

Generate New API Key

  1. Click Generate New API Key
  2. Give your key a descriptive name (e.g., "Production App", "Mobile App")
  3. Select the appropriate permissions/scopes
  4. 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:

ScopeDescriptionPermissions
students:readView student informationGET students, profiles
students:writeCreate and update studentsPOST, PUT, DELETE students
attendance:readView attendance recordsGET attendance data
attendance:writeMark and modify attendancePOST, PUT attendance
academic:readView classes, subjectsGET academic data
academic:writeManage academic dataPOST, PUT, DELETE academic
library:readView library recordsGET library data
library:writeManage library operationsPOST, PUT library
reports:readAccess reports and analyticsGET reports
admin:allFull administrative accessAll 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

  1. Go to SettingsOAuth Applications
  2. Click New Application
  3. 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:

  1. 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
  1. User grants permission

  2. 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"
  1. 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")); // 1700000000

4. Rotate API Keys Regularly

Rotate your API keys every 90 days or immediately if compromised:

  1. Generate a new API key
  2. Update your application with the new key
  3. Test thoroughly
  4. 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 CodeErrorSolution
401UNAUTHORIZEDCheck your API key is correct and active
403FORBIDDENVerify your API key has required permissions
429RATE_LIMIT_EXCEEDEDWait until rate limit resets or upgrade plan
498TOKEN_EXPIREDRefresh your OAuth token
499TOKEN_REQUIREDInclude 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

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).