Skip to content

Integration guide

A practical, end-to-end walkthrough of the SkillFoundry API: creating a task from a pull request, running a candidate through an assessment, and retrieving the score report. Endpoint details are in the API reference; conventions (auth, errors, rate limits) in the API overview.

All examples use curl with a $TOKEN environment variable holding a session JWT (see Authentication).

1. Create an assessment task from a pull request

curl -X POST https://api.skillfoundry.dev/api/v1/tasks/import-pr \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "pr_url": "https://github.com/your-org/your-repo/pull/123",
    "visibility": "PRIVATE_ORG",
    "organization_id": "org_abc123",
    "tags": ["backend", "python"]
  }'

SkillFoundry snapshots the repository at the PR's base commit and generates a task. For private repositories, connect GitHub or store a token first (POST /github/user-token). Keep the returned task_id.

Alternative creation paths: the Task Builder (POST /task-drafts with an issue + PR pair, then publish with POST /tasks) or templates (GET /public/templates, then POST /public/tasks).

2. Invite the candidate

curl -X POST https://api.skillfoundry.dev/api/v1/invites/candidate \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "email": "candidate@email.com", "task_id": "task_xyz789" }'

The candidate receives an email; on acceptance they're added to your organization with the task assigned. Watch for 403 (candidate plan limit reached), 409 (already invited), and remember invitations expire — resend if needed.

3. The candidate runs the assessment

If candidates use the SkillFoundry web app or VS Code extension, everything in this section happens automatically. If you're building your own client, this is the sequence:

Create and start an attempt

# Create (authenticated as the candidate)
curl -X POST https://api.skillfoundry.dev/api/v1/attempts \
  -H "Authorization: Bearer $CANDIDATE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "task_id": "task_xyz789" }'
# → { "id": "attempt_123", "status": "NOT_STARTED", ... }

# Start (this begins the time limit, if any)
curl -X POST https://api.skillfoundry.dev/api/v1/attempts/attempt_123/start \
  -H "Authorization: Bearer $CANDIDATE_TOKEN"

(Optional) Hand off to an IDE

curl -X POST https://api.skillfoundry.dev/api/v1/attempts/attempt_123/ide-session \
  -H "Authorization: Bearer $CANDIDATE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "expires_in_hours": 48 }'
# → { "session_token": "sf_ide_...", "session_link": "vscode://...", ... }

The sf_ide_ token authenticates the IDE client on attempt, telemetry, and chat endpoints — no JWT needed inside the IDE.

Save work in progress

File changes are persisted as a base64 overlay on the attempt:

curl -X PATCH https://api.skillfoundry.dev/api/v1/attempts/attempt_123/changes \
  -H "Authorization: Bearer $CANDIDATE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "changes": {
      "src/service.py": { "op": "upsert", "content_b64": "aW1wb3J0IG9zCg==" }
    }
  }'

Run tests in the sandbox

# Queue a run
curl -X POST https://api.skillfoundry.dev/api/v1/attempts/attempt_123/runs \
  -H "Authorization: Bearer $CANDIDATE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "changed_files": ["src/service.py"] }'
# → { "id": "run_456", "status": "queued" }

# Poll until it finishes
curl https://api.skillfoundry.dev/api/v1/attempts/attempt_123/runs/run_456 \
  -H "Authorization: Bearer $CANDIDATE_TOKEN"
# → { "status": "SUCCEEDED", "artifact_urls": { "junit": "...", "logs": "..." } }

Runs execute in an isolated sandbox; poll with backoff (runs typically take seconds to a few minutes depending on the repository). Artifact URLs are presigned and time-limited — download promptly.

Custom clients should send behavioral activity so submissions get a full evaluation. Events are posted in batches to POST /siem/events/batch with the candidate's sf_ide_ session token; the event catalog and payload schema are provided to integration partners on request (contact your account team).

Buffer events locally on network failure — the endpoint returns 202 and processes asynchronously. Send activity metadata only, never code content or clipboard text; see Monitoring and data collection for what belongs in telemetry.

Submit

curl -X POST https://api.skillfoundry.dev/api/v1/attempts/attempt_123/submit \
  -H "Authorization: Bearer $CANDIDATE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tests_passed": 10,
    "tests_total": 10,
    "coverage": 0.87,
    "lint_score": 0.95,
    "behavior_signals": {},
    "git_diff": "diff --git a/src/service.py ...",
    "changed_files": ["src/service.py"]
  }'

Submission is final — the attempt is locked and scoring begins.

4. Retrieve results

curl https://api.skillfoundry.dev/api/v1/attempts/attempt_123/score-report \
  -H "Authorization: Bearer $TOKEN"
{
  "overall_score": 82.5,
  "subscores": {
    "correctness": 90,
    "code_quality": 78,
    "test_coverage": 85,
    "behavior": 74,
    "communication": 66
  }
}

Scoring runs asynchronously after submission — poll the attempt until score_id is set (or the score-report endpoint stops returning 404), with backoff. Deeper behavioral detail is available through the evaluation endpoints (Interviewer+), and org-wide trends through /analytics/org/{org_id}.

Integration checklist

  • [ ] Handle 401 by re-authenticating; handle 429 with exponential backoff.
  • [ ] Handle 403 plan-limit errors gracefully (surface the upgrade message to an admin, don't retry).
  • [ ] Treat all IDs as opaque strings; all timestamps as ISO 8601 UTC.
  • [ ] Poll async resources (runs, drafts, learning imports, scoring) with backoff — 202 Accepted means "in progress", not "done".
  • [ ] Never send code content, clipboard text, or credentials in telemetry payloads.
  • [ ] Revoke IDE session tokens (DELETE .../ide-session/{token}) when your client is done with them; each attempt allows at most 5 active tokens.
  • [ ] Use the interactive docs (/api/v1/docs) as the authoritative schema reference.