Documentation
Connect Claude Code, Cursor, or any agent to Foundry notebooks over the Agent API. Create notebooks, upload data, train on Modal GPUs, and poll live logs.
Base URL: https://foundry-mocha-ten.vercel.app
Getting started
- Create an account and verify your email.
- Open Settings → API keys and create a key. Copy the secret once — it starts with
fdry_sk_. - Give that key to your AI agent (Claude Code, Cursor, custom script) as
FOUNDRY_API_KEY. - Point the agent at
https://foundry-mocha-ten.vercel.app/api/v1.
For AI agents
Foundry is built so coding agents can drive training without opening the UI. Tell the agent:
- Host:
https://foundry-mocha-ten.vercel.app - Auth header:
Authorization: Bearer fdry_sk_… - JSON for most calls; multipart form for file uploads (
files=@path). - Preferred loop: create notebook → upload dataset →
POST …/train→ poll…/statusand…/logs.
Paste this into Claude Code
You have access to Foundry Agent API.
Base URL: https://foundry-mocha-ten.vercel.app
Auth: Authorization: Bearer $FOUNDRY_API_KEY
(Key looks like fdry_sk_… — never print the full secret.)
Do this for training jobs:
1. POST /api/v1/notebooks { "title":"…", "templateId":"llm-lora", "gpu":"T4" }
2. POST /api/v1/notebooks/{id}/files multipart field "files" with dataset
3. PATCH /api/v1/notebooks/{id} optional trainConfig (epochs, datasetNote, …)
4. POST /api/v1/notebooks/{id}/train {}
5. Poll GET /api/v1/notebooks/{id}/status and /logs until status is ready or failed
Templates: llm-lora | whisper | handwriting | video | voice | robotics
GPUs: cpu | T4 | L4 | A10G
If you are Claude in Anthropic's cloud sandbox: you CANNOT curl this host
(egress allowlist). Use the GitHub Actions bridge instead — see docs #claude-cloud.
Cursor / local Claude Code can call Foundry directly.Claude Cloud sandbox
Anthropic's cloud agent runs behind an egress proxy with a fixed hostname allowlist (GitHub, npm, PyPI, crates.io, etc.). foundry-mocha-ten.vercel.app is not on that list, so the proxy returns host_not_allowedbefore the request ever reaches Foundry. We cannot change Anthropic's allowlist from Foundry.
What works
- Cursor (or Claude Code on your machine) — uses your PC network; call
/api/v1directly with yourfdry_sk_key. - GitHub Actions bridge — Claude talks to
api.github.com(allowlisted). A workflow on GitHub's runners calls Foundry for you.
Set up the bridge (once)
- Copy
templates/github-agent-bridge/foundry-agent-bridge.ymlinto your repo as.github/workflows/foundry-agent-bridge.yml. - Repo → Settings → Secrets and variables → Actions → add
FOUNDRY_API_KEY= yourfdry_sk_…secret. Optional:FOUNDRY_HOST=https://foundry-mocha-ten.vercel.app. - Tell cloud Claude to dispatch the workflow instead of curling Foundry.
Paste this into Claude Cloud
You cannot reach Foundry's Vercel host from this sandbox (egress allowlist).
Use the GitHub Actions bridge instead:
gh workflow run foundry-agent-bridge.yml \
-f action=create \
-f title="From Claude Cloud" \
-f template_id=llm-lora \
-f gpu=T4
# After it finishes, read the artifact or:
gh run list --workflow=foundry-agent-bridge.yml --limit 1
gh run view RUN_ID --log
Other actions: list | train | status | logs | upload_note
(train/status/logs need -f notebook_id=…)
The user's dashboard at https://foundry-mocha-ten.vercel.app/dashboard/notebooks
will show notebooks created this way (same API key / account).Asking Anthropic to allowlist your domain is possible as a product request, but it is not something Foundry or your API key can unlock today.
Authentication
Every /api/v1/* request needs a Bearer token. Keys are hashed at rest; the plaintext secret is shown once at creation.
curl "https://foundry-mocha-ten.vercel.app/api/v1/notebooks" \
-H "Authorization: Bearer $FOUNDRY_API_KEY"- Prefix:
fdry_sk_ - Max 5 active keys per account
- Manage keys in Dashboard → Settings
- Revoke or delete a key immediately if it leaks
Scopes
Keys can be limited to specific actions. New keys default to all scopes.
| Scope | Allows |
|---|---|
| notebooks:read | List notebooks, get status, read logs |
| notebooks:write | Create, update, delete notebooks |
| notebooks:files | Upload / list / delete dataset files |
| notebooks:run | Run cells (single or all) |
| notebooks:train | Start the train recipe on Modal |
Missing scope → 403 with code: "forbidden". Bad or missing key → 401 unauthorized.
End-to-end flow
export FOUNDRY_API_KEY=fdry_sk_…
export HOST=https://foundry-mocha-ten.vercel.app
# 1) Create
curl -s -X POST "$HOST/api/v1/notebooks" \
-H "Authorization: Bearer $FOUNDRY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Agent train","templateId":"llm-lora","gpu":"T4"}'
# 2) Upload dataset (JSONL recommended)
curl -s -X POST "$HOST/api/v1/notebooks/NOTEBOOK_ID/files" \
-H "Authorization: Bearer $FOUNDRY_API_KEY" \
-F "files=@./train.jsonl"
# 3) Optional config tweak
curl -s -X PATCH "$HOST/api/v1/notebooks/NOTEBOOK_ID" \
-H "Authorization: Bearer $FOUNDRY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"trainConfig":{"epochs":3,"datasetNote":"Support chat pairs"}}'
# 4) Train on Modal
curl -s -X POST "$HOST/api/v1/notebooks/NOTEBOOK_ID/train" \
-H "Authorization: Bearer $FOUNDRY_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'
# 5) Poll
curl -s "$HOST/api/v1/notebooks/NOTEBOOK_ID/status" \
-H "Authorization: Bearer $FOUNDRY_API_KEY"
curl -s "$HOST/api/v1/notebooks/NOTEBOOK_ID/logs" \
-H "Authorization: Bearer $FOUNDRY_API_KEY"Endpoints
All paths are under /api/v1. Responses are JSON unless noted.
/api/v1/notebooksList your notebooks and remaining credits.
Scope: notebooks:read
curl "$HOST/api/v1/notebooks" -H "Authorization: Bearer $FOUNDRY_API_KEY"/api/v1/notebooksCreate a notebook. Optional: title, description, gpu, templateId, trainConfig, cells.
Scope: notebooks:write
curl -X POST "$HOST/api/v1/notebooks" \
-H "Authorization: Bearer $FOUNDRY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"My LoRA","templateId":"llm-lora","gpu":"T4"}'/api/v1/notebooks/:idFetch full notebook: cells, trainConfig, events.
Scope: notebooks:read
/api/v1/notebooks/:idUpdate title, description, gpu, cells, or trainConfig. Updating trainConfig refreshes the FOUNDRY_CONFIG cell.
Scope: notebooks:write
/api/v1/notebooks/:idDelete a notebook.
Scope: notebooks:write
/api/v1/notebooks/:id/filesUpload dataset files. Multipart form field name: files (repeat for multiple). Max ~200 MB each.
Scope: notebooks:files
curl -X POST "$HOST/api/v1/notebooks/ID/files" \
-H "Authorization: Bearer $FOUNDRY_API_KEY" \
-F "files=@./train.jsonl"/api/v1/notebooks/:id/filesList uploaded files and workspace path.
Scope: notebooks:files
/api/v1/notebooks/:id/filesRemove a file. Body: { "name": "train.jsonl" }.
Scope: notebooks:files
/api/v1/notebooks/:id/trainApply optional config, then run the full recipe on Modal (config → load → train → eval → export).
Scope: notebooks:train
curl -X POST "$HOST/api/v1/notebooks/ID/train" \
-H "Authorization: Bearer $FOUNDRY_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'/api/v1/notebooks/:id/runRun cells. Body actions: { "action":"run_all" } | { "action":"run_cell","cellId":"…" } | { "action":"add_cell","kind":"code" }.
Scope: notebooks:run
/api/v1/notebooks/:id/statusLightweight poll: status, running, failed, lastRunAt, Modal readiness.
Scope: notebooks:read
/api/v1/notebooks/:id/logsLive events + cell outputs/errors. Optional ?since=ISO8601 to fetch only newer lines.
Scope: notebooks:read
Templates
Pass templateId on create:
llm-lora— Chat / instruction LoRAwhisper— Speech recognitionhandwriting— Handwriting / visionvideo— Short video adaptersvoice— Voice clonerobotics— Imitation learning
Errors
{
"error": "Invalid or missing API key",
"code": "unauthorized"
}401 unauthorized— missing/invalid Bearer key403 forbidden— key lacks required scope404— notebook not found for this account400— validation / Modal not configured / run failure message inerror
Dataset format
Prefer JSONL: one example per line. Short, clean pairs beat giant dumps.
{"messages":[
{"role":"user","content":"Do you deliver Sundays?"},
{"role":"assistant","content":"Yes — Nairobi only, 10am–4pm."}
]}
{"messages":[
{"role":"user","content":"Shipping time to Mombasa?"},
{"role":"assistant","content":"2–3 business days with standard courier."}
]}After upload, open the notebook in the dashboard or keep driving it via the Agent API.
Credits
Cell runs and training spend credits (notebooks can be set free for testing via NOTEBOOKS_FREE). See Pricing and Billing.
Ready to connect an agent?
Create a key, paste the host + Bearer token into Claude Code or Cursor, and let it create notebooks for you.