Skip to content

API overview

Everything in the SkillFoundry web application is backed by a REST API you can use directly. This page covers the conventions that apply to every endpoint; the API reference lists the endpoints themselves, and the integration guide walks through a complete assessment flow.

Base URL and versioning

https://api.skillfoundry.dev/api/v1

All endpoints in these docs are relative to that base. The API is versioned by path prefix; v1 is the current (and only) version.

Interactive documentation generated from the live API is available at:

  • Swagger UI: https://api.skillfoundry.dev/api/v1/docs
  • ReDoc: https://api.skillfoundry.dev/api/v1/redoc

The interactive docs are always in sync with the deployed API — when in doubt, they are authoritative for request/response schemas.

Authentication

Session tokens (JWT)

SkillFoundry uses a hosted identity provider (Descope). Sign-in happens in the browser (email/password, social login, or your organization's SAML SSO); the resulting session JWT authenticates API calls:

Authorization: Bearer <session-jwt>
  • Tokens are short-lived; refresh is handled by the client SDK (there is no server-side refresh endpoint).
  • Your user record is provisioned automatically on your first authenticated request.
  • Roles (candidate, interviewer, orgadmin, admin) are carried in the token and enforced per endpoint — the reference notes the required role where it's stricter than "any authenticated user".

For headless/server-to-server integrations, authenticate a service account through the identity provider's API to obtain a session JWT programmatically.

IDE session tokens

A second credential type exists for in-IDE assessment sessions: tokens with the prefix sf_ide_, minted per attempt (POST /attempts/{attempt_id}/ide-session, default 48-hour expiry, max 5 active per attempt). They're accepted as Bearer tokens on the subset of endpoints an IDE session needs: attempt start/submit, telemetry, behavioral events, and AI chat.

Requests and responses

  • Request and response bodies are JSON (Content-Type: application/json).
  • Timestamps are ISO 8601 strings in UTC.
  • IDs are opaque strings — don't parse them.

Errors

Errors use standard HTTP status codes with a JSON body:

{ "detail": "Human-readable message" }

Validation failures (422) return field-level details:

{
  "detail": [
    { "loc": ["body", "email"], "msg": "value is not a valid email address", "type": "value_error.email" }
  ]
}
Status Meaning Typical causes
400 Bad request Malformed input (e.g., an invalid PR URL)
401 Unauthorized Missing, expired, or invalid token — re-authenticate
403 Forbidden Insufficient role, not a member of the org, or subscription plan limit reached (the message says which, with an upgrade prompt)
404 Not found Wrong ID, or a resource you can't see
409 Conflict Duplicate (e.g., invitation already used)
410 Gone Expired invitation
422 Validation error Schema violations, with field details
429 Rate limited Slow down and retry with backoff
500 Server error Retry; if persistent, contact support with the error_id from the response body

Rate limits

Requests are rate-limited per client IP:

Scope Limit
General API 60 requests / minute
Auth-related paths 10 requests / minute
Uploads 5 requests / minute
Burst (any) 20 requests / 10 seconds

Some features carry their own limits (for example, public challenge submissions at 30/minute per user, AI chat at ~10 messages/minute, and 5 active IDE session tokens per attempt). A 429 response means back off and retry; use exponential backoff in integrations.

API usage may also count against your organization's subscription plan limits — exceeding those returns 403 (not 429) with an upgrade message.

Pagination

List endpoints take page (1-based) and limit query parameters (default limit is typically 10–50, max 50–100 depending on the endpoint) and return a pagination envelope:

{
  "items": ["..."],
  "pagination": { "total": 100, "pages": 10, "current": 1, "limit": 20 }
}

A few endpoints use skip/limit or page_size instead — the interactive docs show the exact parameters per endpoint.

WebSockets

Two streaming endpoints exist:

  • WS /api/v1/notifications/ws/{user_id} — real-time in-app notifications.
  • WS /api/v1/code-execution/ws/{execution_id} — live stdout/stderr for a code execution started via POST /code-execution/execute; send {"type": "stdin", ...} for input or {"type": "terminate"} to stop.

Webhooks

Inbound webhooks currently cover billing only (Stripe → SkillFoundry). Outbound webhooks to customer systems are not yet available; poll the relevant resources (e.g., attempt status, score reports) in the meantime.

Health

GET /health (no auth, outside the /api/v1 prefix) returns service status and version — use it for uptime checks.