Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.hawkings.education/llms.txt

Use this file to discover all available pages before exploring further.

The SDK throws typed errors. Catch the parent class to handle anything, or catch a specific subclass for fine-grained logic.
import Hawkings, {
  HawkingsError,
  AuthenticationError,
  RateLimitError,
  InvalidRequestError,
  APIError,
} from "@hawkings/sdk";

try {
  await hk.courses.create({ name: "" });
} catch (err) {
  if (err instanceof InvalidRequestError) {
    console.error(err.fields); // { name: "is required" }
  }
}
In PHP the exception hierarchy is rooted at \Hawkings\Exception\ApiError, with subclasses for each error type (AuthenticationError, PermissionError, NotFoundError, InvalidRequestError, RateLimitError, IdempotencyError, NetworkError). Catch ApiError to handle anything.

Error taxonomy

ClassHTTPWhen it firesRetryable?
AuthenticationError401Bad/expired API key, missing scope.No
PermissionError403Key valid, but no access to this resource.No
NotFoundError404Resource doesn’t exist or is in another workspace.No
InvalidRequestError422Validation failed. Inspect err.fields.No
RateLimitError429Too many requests. err.retry_after is the seconds to wait.Yes (auto)
IdempotencyError409Same idempotency_key reused with a different payload.No
APIError5xxHawkings is having a moment. Auto-retried with backoff.Yes (auto)
NetworkErrorn/aDNS, TLS, timeout. Auto-retried with backoff.Yes (auto)

Automatic retries

The SDK retries 429 and 5xx responses automatically with exponential backoff and jitter. Defaults:
new Hawkings({
  max_retries: 3,         // default
  retry_delay_ms: 500,     // base; doubles each attempt
  retry_on: ["429", "5xx", "network"],
});
Disable for a specific call:
await hk.courses.create({ name: "..." }, { max_retries: 0 });

Idempotency keys

Any create*, update*, or AI generation call can carry an Idempotency-Key. Same key + same body = same response, even if you call it 100 times. Different body with the same key throws IdempotencyError.
await hk.submissions.create(
  { assignmentId, studentId, content },
  { idempotency_key: "subm-2026-05-10-abc" },
);
Idempotency records live for 24 hours.

Error envelope

Every error response carries a structured body:
{
  "error": {
    "type": "invalid_request_error",
    "code": "missing_field",
    "message": "name is required.",
    "fields": { "name": "is required" },
    "request_id": "req_01HX9..."
  }
}
When opening a support ticket, attach request_id — it’s all we need to trace a request end-to-end.