API reference
Endpoint reference for the SkillFoundry REST API, grouped by domain. All paths are relative to https://api.skillfoundry.dev/api/v1 and require Authorization: Bearer <token> unless marked Public. See the API overview for authentication, errors, rate limits, and pagination conventions, and the interactive docs at /api/v1/docs for full request/response schemas.
Role legend: endpoints are available to any authenticated user unless a stricter role is noted — Candidate, Interviewer+ (interviewer, org admin, or platform admin), Org Admin, Admin (platform staff). IDE means the endpoint also accepts sf_ide_ session tokens.
Users and profile
| Method |
Path |
Notes |
| GET |
/users/me |
Current user profile |
| PUT |
/users/me |
Update profile — {name?, picture?} |
| GET |
/users/profile/github-status |
Whether a GitHub account is linked |
| POST |
/users/sync-role |
Re-sync role from the identity provider (use after a role change) |
Onboarding
| Method |
Path |
Notes |
| GET |
/onboarding/status |
Onboarding completion state |
| POST |
/onboarding/complete |
Mark onboarding done |
Organizations
| Method |
Path |
Notes |
| GET |
/organizations |
List your organizations — search, page, limit |
| POST |
/organizations |
Create — {name, website?, description?, industry?, size?, ...}; creator becomes org admin |
| GET |
/organizations/{org_id} |
Organization details |
| PUT |
/organizations/{org_id} |
Update organization fields |
| GET |
/organizations/{org_id}/members |
Member list |
| POST |
/organizations/{org_id}/members |
Add member — {email, role}; counts against seat limit |
| GET |
/organizations/{org_id}/settings |
Org Admin. AI policy, timezone, language, hiring-only mode, branding |
| PATCH |
/organizations/{org_id}/settings |
Org Admin. Update settings |
| GET |
/organizations/{org_id}/branding |
Branding + plan entitlements (any member) |
| GET |
/organizations/{org_id}/dashboard |
Org Admin. Dashboard metrics |
Invitations
| Method |
Path |
Notes |
| POST |
/organizations/{org_id}/invitations |
Create invitation |
| POST |
/organizations/{org_id}/invitations/{invitation_id}/resend |
Resend |
| GET |
/organizations/invitations/accept/{token} |
Public. Preview an invitation |
| POST |
/organizations/invitations/accept/{token} |
Accept (must be signed in) |
| GET |
/invites/validate?token= |
Validate an invite token — returns org, role, expiry, email match |
| POST |
/invites/accept/{token} |
Accept; applies role and any attached task assignment |
| POST |
/invites/candidate |
Invite a candidate (optionally with a task) |
SSO and SCIM (Org Admin)
| Method |
Path |
Notes |
| GET |
/auth/sso/discovery?email= |
Public. Whether an email domain uses SSO |
| GET |
/organizations/{org_id}/sso |
Current SAML/SCIM configuration + SP metadata |
| PUT |
/organizations/{org_id}/sso |
Configure — {sso_enabled, enforce_sso, idp_metadata_url?, email_domains[], role_mappings[]} |
| DELETE |
/organizations/{org_id}/sso |
Disable SSO |
| POST |
/organizations/{org_id}/sso/scim/token |
Generate SCIM token — returns {token, scim_base_url} |
| DELETE |
/organizations/{org_id}/sso/scim |
Disable SCIM |
Tasks
PR-derived tasks
| Method |
Path |
Notes |
| POST |
/tasks/import-pr |
Create a task from a pull request — {pr_url, visibility, organization_id?, tags[]} |
| GET |
/tasks |
List tasks you can see |
| GET |
/tasks/{task_id} |
Task detail |
| GET |
/tasks/{task_id}/snapshot |
Repository snapshot metadata (pre-PR base state) |
| GET |
/tasks/{task_id}/snapshot/files/{file_path} |
File content from the snapshot |
| GET |
/tasks/{task_id}/base-commit-files |
File tree at the base commit |
| GET |
/public/tasks/{task_id} |
Public. Read-only task view (brief + GitHub metadata) |
Task Builder (Org Admin)
| Method |
Path |
Notes |
| POST |
/task-drafts |
Draft from an issue + PR pair — {issue_url, pr_url, github_token?}; processes asynchronously |
| GET |
/task-drafts/{draft_id} |
Draft status/content |
| GET |
/task-drafts |
List drafts — status?, limit |
| POST |
/tasks |
Publish a draft — {draft_id, candidate_title?, candidate_markdown?} |
Templates
| Method |
Path |
Notes |
| GET / POST |
/templates |
List / create task templates |
| GET / PUT / DELETE |
/templates/{template_id} |
Manage a template |
| GET |
/public/templates |
Curated public catalog — difficulty, programming_language, search, page, limit |
| POST |
/public/tasks |
Create a task from a public template — {template_id} |
Attempts and scoring
The core assessment lifecycle. See the integration guide for the sequence.
| Method |
Path |
Notes |
| POST |
/attempts |
Create an attempt — {task_id, candidate_id?} |
| POST |
/attempts/{attempt_id}/start |
IDE. Start the attempt (starts any time limit) |
| PATCH |
/attempts/{attempt_id}/changes |
Persist file changes — {changes: {"<path>": {op, content_b64?}}} |
| POST |
/attempts/{attempt_id}/submit |
IDE. Final submission — {tests_passed, tests_total, coverage, lint_score, behavior_signals{}, git_diff?, changed_files[], notes?}. Irreversible. |
| GET |
/attempts/{attempt_id} |
Attempt state (NOT_STARTED, IN_PROGRESS, SUBMITTED, EXPIRED, CANCELLED) |
| GET |
/attempts |
List attempts — task_template_id?, candidate_id? |
| GET |
/attempts/{attempt_id}/results |
The candidate's own result. overall_score, a per-area breakdown, and verified test counts. Always 200 for an attempt the caller owns: visibility is visible, pending (still scoring) or withheld (the assigning organization turned off candidate_score_visibility). |
| GET |
/attempts/{attempt_id}/score-report |
Raw score report for the caller's own attempt: overall_score, subscores (correctness, code_quality, test_coverage, behavior, communication). Reviewer-only fields are redacted; 403 CANDIDATE_SCORES_WITHHELD when the organization withholds scores. Reviewers read the unredacted report via /evaluation/attempts/{id}. |
Test runs
| Method |
Path |
Notes |
| POST |
/attempts/{attempt_id}/runs |
Queue a sandboxed test run — {changed_files[]} |
| GET |
/attempts/{attempt_id}/runs |
List runs |
| GET |
/attempts/{attempt_id}/runs/{run_id} |
Run status (queued → running → SUCCEEDED/FAILED) + artifact download URLs (JUnit XML, logs) when complete |
IDE sessions
| Method |
Path |
Notes |
| POST |
/attempts/{attempt_id}/ide-session |
Mint an sf_ide_ token — {expires_in_hours?} (default 48h, max 5 active) → {session_token, session_link, expires_at, task_info} |
| POST |
/ide-session/validate |
Public. Validate a token — {session_token} → attempt, user, chat config |
| GET |
/attempts/{attempt_id}/ide-sessions |
List active sessions |
| DELETE |
/attempts/{attempt_id}/ide-session/{session_token} |
Revoke a token |
Behavioral telemetry
| Method |
Path |
Notes |
| POST |
/tasks/attempts/events |
IDE. Batch editor activity → 202 |
| POST |
/siem/events/batch |
IDE. Batch behavioral activity for analysis → 202. Event schema available to integration partners on request. |
Candidate workflow (template tasks)
| Method |
Path |
Notes |
| GET |
/candidate/tasks |
Candidate. Available tasks — difficulty, tags[], page, limit |
| GET |
/candidate/tasks/{task_id} |
Task detail |
| POST |
/candidate/tasks/{task_id}/run-tests |
Run the task's tests against provided code |
| POST |
/candidate/tasks/{task_id}/submissions |
Submit — {code, language, notes?, ai_metadata?} |
| GET |
/candidate/tasks/{task_id}/submissions/{submission_id} |
Submission detail |
| GET |
/candidate/dashboard |
Dashboard stats |
Evaluation (Interviewer+)
| Method |
Path |
Notes |
| GET |
/evaluation/evaluation-queue |
Pending submissions — status, page, limit |
| POST |
/evaluation/submissions/{submission_id}/evaluate |
Run automated evaluation |
| GET |
/evaluation/submissions/{submission_id}/report |
Evaluation report (also readable by the submission's owner) |
| POST |
/evaluation/submissions/{submission_id}/manual-review |
Adjust — {points_adjustment, reason, additional_feedback?} |
AI personas (chat)
| Method |
Path |
Notes |
| POST |
/customers/chat |
IDE. Message the AI customer persona for a task |
| GET |
/customers/chat/history/{task_id} |
IDE. Customer chat history |
| POST |
/tpm/chat |
IDE. Message the AI TPM persona |
| GET |
/tpm/chat/history/{task_id} |
IDE. TPM chat history |
AI mentor
| Method |
Path |
Notes |
| POST |
/ai-mentor/request-hint |
Request a Socratic hint on a task |
| GET |
/ai-mentor/hint-history/{task_id} |
Hints already given |
| POST |
/ai-mentor/code-review |
AI code review of your work |
| GET |
/ai-mentor/learning-path-recommendation |
Suggested learning path |
Code execution
| Method |
Path |
Notes |
| POST |
/code-execution/execute |
Start an execution — {files[{path, content}], entryPoint, language, taskId?} → {executionId} |
| WS |
/code-execution/ws/{execution_id} |
Stream stdout/stderr; send stdin/terminate messages |
| POST |
/code-execution/execute/{execution_id}/stop |
Stop a running execution |
| POST |
/code-execution/execute-sync |
Synchronous execution (short programs) |
Gamification
| Method |
Path |
Notes |
| GET |
/gamification/profile/me |
XP, level, badges, streak |
| POST |
/gamification/public-challenge |
Get a challenge — {difficulty?, tags?, exclude_completed?} |
| POST |
/gamification/submit-public-challenge/{task_id} |
Submit — {code, language} (rate-limited 30/min) |
| GET |
/gamification/daily-challenge |
Today's featured challenge |
| GET |
/gamification/leaderboard |
Rankings — period?, limit? |
| GET |
/gamification/achievements |
Your achievements |
Learning
Learning paths
| Method |
Path |
Notes |
| GET |
/learning/paths |
Available paths — role?, skill? |
| POST |
/learning/enroll |
Enroll — {learning_path_id} |
| GET |
/learning/progress/{learning_path_id} |
Module-level progress |
| POST |
/learning/complete-task/{task_id} |
Mark a path task complete |
| GET |
/learning/certificates |
Earned certificates |
| GET |
/learning/resources |
Resource library |
Repository-based learning modules
| Method |
Path |
Notes |
| GET |
/learning/languages |
Supported languages |
| GET |
/learning/curated-repos |
Curated repositories — language, page, page_size |
| POST |
/learning/repos/import |
Import a repo — {git_url, language} → 202 (async) |
| POST |
/learning/repos/{repo_id}/plans |
Compile a plan — {goal_track} → 202 (async) |
| GET |
/learning/plans/{plan_id}/sprints |
Sprint list |
| GET |
/learning/sprints/{sprint_id}/tasks |
Tasks in a sprint (paginated) |
| GET |
/learning/tasks/{task_id} |
Task + starting snapshot |
| POST |
/learning/tasks/{task_id}/submissions |
Submit → 202 (async scoring) |
| GET |
/learning/submissions/{submission_id} |
{status, score, similarity, feedback} |
| GET |
/learning/users/me/progress?plan_id= |
Your progress |
Behavioral analysis
| Method |
Path |
Notes |
| GET |
/behavioral/report?period_days= |
Your behavioral report (overall score, per-skill breakdowns, recommendations) |
| GET |
/behavioral/skill/{skill_name} |
Single-skill analysis |
| GET |
/behavioral/comparison |
Peer comparison |
| POST |
/behavioral/analyze-submission |
Analyze — {submission_id} |
GitHub integration
| Method |
Path |
Notes |
| POST |
/github/connect / /github/disconnect |
Link/unlink your GitHub account |
| GET |
/github/profile |
Linked GitHub profile summary |
| POST / GET |
/github/user-token |
Store / check a personal access token (for private repos) |
| GET |
/github/pull-requests |
List your PRs |
| POST |
/github/import-pull-requests |
Import your PRs as tasks |
| POST |
/github/repository-pr-tasks |
Org Admin. Bulk-create tasks from a repository's PRs |
| POST |
/github/tasks |
Org Admin. Create a task from a GitHub issue |
| Method |
Path |
Notes |
| GET |
/comments?taskId= |
Q&A on a task |
| POST |
/comments |
Create a comment |
| POST |
/comments/{comment_id}/responses |
Respond |
Notifications
| Method |
Path |
Notes |
| WS |
/notifications/ws/{user_id} |
Real-time notification stream |
| GET / PATCH |
/notifications/settings |
Notification preferences (channels + per-event toggles) |
Subscriptions and billing
| Method |
Path |
Notes |
| GET |
/subscriptions/plans |
Public. Available plans with pricing and features |
| POST |
/subscriptions/checkout-session |
Start checkout — {orgId, planId, billingPeriod} → Stripe {sessionId} |
| GET |
/subscriptions/current |
Current subscription |
| POST |
/subscriptions/upgrade / /downgrade |
Change plan — {planId, billingPeriod} |
| POST |
/subscriptions/preview-change |
Proration preview before changing |
| POST |
/subscriptions/pause / /resume / /cancel |
Lifecycle (cancel takes {immediate?}) |
| GET |
/subscriptions/invoices |
Invoice list (+ /{invoice_id}/download) |
| GET / POST / DELETE |
/subscriptions/payment-methods |
Manage cards |
| GET |
/subscriptions/usage / /limits / /plan-limits |
Usage vs. plan caps |
| GET |
/subscriptions/billing-portal |
Stripe self-service portal URL |
Analytics (Org Admin for org scopes)
| Method |
Path |
Notes |
| GET |
/analytics/user/{user_id}?days= |
User analytics |
| GET |
/analytics/task/{task_id} |
Task performance |
| GET |
/analytics/org/{org_id} |
Organization analytics (+ /skills, /improvement, /code-quality) |
Data management
| Method |
Path |
Notes |
| POST |
/data/export/organization/{org_id} |
Export your organization's data |
Knowledge base
| Method |
Path |
Notes |
| GET |
/knowledge-base |
Articles (paginated) |
| GET |
/knowledge-base/search |
Search |
| GET |
/knowledge-base/categories |
Categories |
| POST |
/knowledge-base/{article_id}/helpful |
Rate an article |
Waitlist
| Method |
Path |
Notes |
| POST |
/waitlist |
Public. Join — {email, name?, source?} (rate-limited: 5/hour/IP, 1/day/email) |
| GET |
/waitlist/check?email= |
Public. Check status |
Platform-admin endpoints (/admin/*, /superadmin/*, /monitoring/*) and internal service endpoints exist but are restricted to SkillFoundry staff and are not documented here.