HFU Digital Docs
StarPlan APIGuides

Authentication

When the StarPlan API needs an API key — and when it doesn't

The StarPlan API uses a single authentication scheme: an X-API-Key HTTP header carrying a developer-scoped key.

Anonymous vs authenticated routes

Route groupAuthentication
GET /v1/starplan/programs and all other catalog readsNone — anonymous
GET /v1/starplan/semesters / /courses / /rooms / /instructors / /search / /statistics / /sync/statusNone — anonymous
GET /v1/starplan/week/*None — anonymous
GET /v1/starplan/ical/:semesterId and /urlNone — anonymous
GET /v1/starplan/changes and /changes/:idNone — anonymous
POST /v1/starplan/developers/registerNone — anonymous
GET /v1/starplan/developers/meX-API-Key required
POST /v1/starplan/developers/regenerate-keyX-API-Key required
POST /v1/starplan/developers/deactivateX-API-Key required
GET /v1/starplan/developers/usageX-API-Key required
* /v1/starplan/webhooks* (all methods)X-API-Key required

Key format

API keys have the prefix spk_ followed by 24 random base64url-encoded bytes (32 characters), giving a 36-character total length. Example shape: spk_AbCdEfGh….

The server stores only:

  • A bcrypt hash (10 rounds) of the full key.
  • A 4-character hint equal to the last 4 characters of the raw key, for fast bucket lookup at validation time.

There is no way to recover a lost key — only rotate it via POST /v1/starplan/developers/regenerate-key (which itself requires the current key).

Sending the header

curl https://api.hfu.digital/v1/starplan/developers/me \
  -H 'X-API-Key: spk_AbCd1234…'
await fetch('https://api.hfu.digital/v1/starplan/developers/me', {
  headers: { 'X-API-Key': process.env.STARPLAN_API_KEY },
});

The header name is case-insensitive (x-api-key works too).

Failure modes

ConditionResponse
Header missing on an authenticated route401 UnauthorizedMissing X-API-Key header
Header present but key is unknown / revoked / inactive401 UnauthorizedInvalid or revoked API key
Key prefix is not spk_401 Unauthorized (rejected before the bcrypt compare)

Anonymous developer endpoints

Two endpoints in the /developers group accept anonymous traffic:

  • POST /v1/starplan/developers/register — issues a new key. Anyone can call it; the response contains the only copy of the raw key you'll ever see.
  • The register endpoint enforces a unique email (case-sensitive). A second registration with the same email returns 409 Conflict — Email already registered.

All other /developers/* routes require the requester's own key.

Webhook signatures vs API keys

Webhook deliveries from StarPlan to your server use a separate, per-webhook secret that you set when creating the webhook. That secret signs each delivery with HMAC-SHA256 (X-Webhook-Signature header) — it is unrelated to your developer API key. See Webhooks.

Best practices

  • Treat spk_… like a password: never commit it, never put it in client-side code, never log it. Only the last four characters are safe to surface (the API itself does this via apiKeyHint).
  • Rotate on suspicion of leakage. The new key invalidates the old one immediately.
  • Deactivate keys you no longer need (POST /v1/starplan/developers/deactivate) — there is no per-key TTL, so unused keys live forever until rotated or deactivated.

On this page