Skip to main content
Hawkings uses two pieces of identity on every authenticated request:
  1. An API keyhk-{...}, 5 segments. Identifies the user.
  2. A learning platform — picked per request by code (slug) or uuid. Identifies which workspace the call operates on.
A single API key gives access to every platform the user belongs to. You pick which one to act on by passing platformCode (preferred) or platform (the 24-char UUID) — the SDK turns them into headers.
code is the human-readable slug. Use it when you have it ("acme-academy", "unimiami"). Fall back to uuid for older platforms where code is still null.

Pass the key to the SDK

The SDK reads HAWKINGS_API_KEY and HAWKINGS_PLATFORM_CODE (or HAWKINGS_PLATFORM for the UUID form) from the environment by default. You can also pass them in code:
import Hawkings from "@hawkings/sdk";

// Preferred: identify the platform by code
const hk = new Hawkings({
  apiKey: "hk-...-...-...-...-...",
  platformCode: "acme-academy",
});

// Or by UUID (universal fallback — always works)
const hk = new Hawkings({
  apiKey: "hk-...-...-...-...-...",
  platform: "abc123def456ghi789jkl012",
});
require_once 'vendor/autoload.php';

// Preferred: identify the platform by code
$hk = new \Hawkings\Client([
    'api_key'       => 'hk-...-...-...-...-...',
    'platform_code' => 'acme-academy',
]);

// Or by UUID
$hk = new \Hawkings\Client([
    'api_key'  => 'hk-...-...-...-...-...',
    'platform' => 'abc123def456ghi789jkl012',
]);
from hawkings import Hawkings

hk = Hawkings(api_key="hk-...", platform_code="acme-academy")
curl https://api.hawkings.education/v1/courses \
  -H "x-api-key: hk-..." \
  -H "X-Learning-Platform-Code: acme-academy"

Wire headers

The SDK sends:
HeaderWhen
x-api-keyAlways (except on unauthenticated endpoints).
X-Learning-Platform-CodeWhen you set platformCode.
X-Learning-Platform-UuidWhen you set platform.
If both are set, the backend cross-checks them — they must point to the same workspace.
The legacy long-form API key (hk-...-{platformUuid}) is no longer accepted by the SDK. Split it: take the first 5 segments as apiKey and pass the trailing 24-hex as platform separately.

Scopes

Every key has one or more scopes. The default key issued in the dashboard carries read:* and write:* for everything in its workspace. For machine-to-machine integrations create scoped keys:
ScopeWhat it allows
read:coursesList, retrieve, expand Course, Cohort, Unit, Lesson.
write:coursesAbove + create / update / delete authoring resources.
read:studentsList students and their progress.
write:submissionsCreate submissions (use this for student-facing apps).
ai:generateRun *.generate*() calls.
ai:gradeRun submissions.gradeWithAi().
The dashboard generates scoped keys via copy-paste; programmatically you’d use the Auth API.

End-user authentication

If you’re building a student-facing product, you don’t want to ship your platform-wide key to a browser. Use the token flow:
// Server-side: ask Hawkings for a one-time token for this user
const { token } = await hk.auth.tokenStart({ email: student.email });

// Send `token` to your client
// Server-side: ask Hawkings for a one-time token for this user
$result = $hk->auth->tokenStart(['email' => $student->email]);
$token = $result->token;

// Send `$token` to your client
// Client-side: exchange the token for a session-scoped key
const session = await hk.auth.tokenFinish(token);
// session.api_key is a short-lived key scoped to this user
// Client-side: exchange the token for a session-scoped key
$session = $hk->auth->tokenFinish($token);
// $session->api_key is a short-lived key scoped to this user
The session key inherits only the scopes the student needs: read:lessons, write:submissions, ai:tutor. It expires in 24 hours.

Multiple workspaces

A single API key gives access to every platform the user belongs to. List them and switch by code or uuid:
const platforms = await hk.platforms.list();
// → [{ id: 1, uuid: "...", code: "acme", name: "Acme Academy", ... }, ...]

// Pick by code (preferred)
const acme = hk.withPlatformCode("acme");
const beta = hk.withPlatformCode("beta");

// Or by uuid (when `code` is still null)
const legacy = hk.withPlatform(platforms[0].uuid);

await acme.courses.list();
await beta.courses.list();
$platforms = $hk->platforms->list();
// → [{ id: 1, uuid: "...", code: "acme", name: "Acme Academy", ... }, ...]

$acme = $hk->withPlatformCode('acme');
$beta = $hk->withPlatformCode('beta');
You can also override the platform on a single call without building a new client — see your SDK’s per-request options.

Rotating a key

Rotating is non-disruptive:
  1. Issue a new key in the dashboard.
  2. Deploy it.
  3. Revoke the old one.
Revoked keys return a 401 authentication_error on the next request.

Self-hosted instances

If you’re running Hawkings on your own infrastructure, point the SDK at your base URL:
new Hawkings({
  apiKey: "hk-...",
  baseURL: "https://api.your-school.example",
});
new \Hawkings\Client([
    'api_key'  => 'hk-...',
    'base_url' => 'https://api.your-school.example',
]);