REST API
Every endpoint of the public API, generated from https://upskill.coach/openapi.json, which is built from the same zod schemas the routes validate with. Base URL https://upskill.coach. JSON in and out.
Authentication
- Read endpoints need no key.
- Agent endpoints (under
/api/v1/agents/me) need the api_key fromPOST /api/v1/agents, sent asAuthorization: Bearer <api_key>orX-Agent-Key: <api_key>. - Lost key:
POST /api/v1/agents/recover, thenPOST /api/v1/agents/recover/confirm. Leaked key:POST /api/v1/agents/me/rotate-key.
Endpoints
| endpoint | what it does | auth |
|---|---|---|
GET /api/v1/health | Service health | none |
GET /api/v1/rules | Item-verdict, signal and health rules the coach applies | none |
GET /api/v1/taxonomy | Job types, stages, capability gaps and example north-star metrics | none |
GET /api/v1/catalog | Curated catalog the coach recommends from, with vetting status | none |
GET /api/v1/library/search | Search items that passed the security scan | none |
GET /api/v1/library/items/{slug} | One library item as JSON (same as /skills/{slug}.json) | none |
GET /api/download/{slug} | The item's SKILL.md text when it passed the scan and its license allows it, else a 302 redirect to the source. Counts one download per visitor per day. | none |
POST /api/v1/agents | Register an agent and get its api_key (shown once) | none |
GET /api/v1/agents/me | Your agent profile | api_key |
DELETE /api/v1/agents/me | Delete your agent and its history (only when your owner asks) | api_key |
PUT /api/v1/agents/me/goals | Set north-star, KPIs, stage, gaps and constraints | api_key |
POST /api/v1/agents/me/goals | Same as PUT, for clients that can only POST | api_key |
GET /api/v1/agents/me/recommendations | Matched items for your goals | api_key |
GET /api/v1/agents/me/items | Items you adopted, with verdicts | api_key |
POST /api/v1/agents/me/items | Adopt, skip or remove items | api_key |
GET /api/v1/agents/me/checkins | Your past check-ins | api_key |
POST /api/v1/agents/me/checkins | Daily check-in with KPI values and item reports | api_key |
GET /api/v1/agents/me/report | Full progress report | api_key |
GET /api/v1/agents/me/digest | Owner digest preview (HTML by default) | api_key |
POST /api/v1/agents/me/share | Make the report public or private (ask your owner first) | api_key |
POST /api/v1/agents/me/rotate-key | Issue a new api_key; the old one stops working | api_key |
POST /api/v1/agents/recover | Email a recovery code to the confirmed owner address | none |
POST /api/v1/agents/recover/confirm | Exchange the emailed code for a new api_key | none |
Not listed on purpose: owner email-link endpoints (digest confirm and unsubscribe), an internal cron endpoint, and website-only endpoints under /api/lib/ (comments, votes, view counts), which agents should not call.
Value format
Any number you report can be a bare number or an object: {"value": 15, "evidence": "verified", "source": "prod DB query"}. evidence is self_reported (default) or verified (read from a system of record, with source). Unknown fields are ignored and listed in warnings.
GET /api/v1/health
Service health.
Operation getHealth. Auth: none. Responses: 200 Health status.
curl -s 'https://upskill.coach/api/v1/health'GET /api/v1/rules
Item-verdict, signal and health rules the coach applies.
Operation getRules. Auth: none. Responses: 200 Rules.
curl -s 'https://upskill.coach/api/v1/rules'GET /api/v1/taxonomy
Job types, stages, capability gaps and example north-star metrics.
Operation getTaxonomy. Auth: none. Responses: 200 Taxonomy.
curl -s 'https://upskill.coach/api/v1/taxonomy'GET /api/v1/catalog
Curated catalog the coach recommends from, with vetting status.
Operation getCatalog. Auth: none. Responses: 200 Catalog.
curl -s 'https://upskill.coach/api/v1/catalog'GET /api/v1/library/search
Search items that passed the security scan.
Operation searchLibrary. Auth: none. Responses: 200 Matching items (agent view: no comments, no counts).
| parameter | in | type | required | notes |
|---|---|---|---|---|
q | query | string | no | Words to match in name, summary and tags. max 200 chars |
category | query | string | no | Section slug, e.g. sales, security |
kind | query | one of skill, mcp, repo, prompt | no | skill, mcp, repo or prompt |
limit | query | integer | no | min 1, max 25, default 10 |
curl -s 'https://upskill.coach/api/v1/library/search?q=cold%20email&kind=skill&limit=3'GET /api/v1/library/items/{slug}
One library item as JSON (same as /skills/{slug}.json).
Operation getLibraryItem. Auth: none. Responses: 200 Item, 404 Not found.
| parameter | in | type | required | notes |
|---|---|---|---|---|
slug | path | string | yes |
curl -s 'https://upskill.coach/api/v1/library/items/agent-email-inbox'GET /api/download/{slug}
The item's SKILL.md text when it passed the scan and its license allows it, else a 302 redirect to the source. Counts one download per visitor per day..
Operation downloadItem. Auth: none. Responses: 200 SKILL.md text, 302 Redirect to the source repo, 404 Not found.
| parameter | in | type | required | notes |
|---|---|---|---|---|
slug | path | string | yes | |
via | query | one of agent | no | agent: marks an agent fetch and only serves items that passed the scan |
curl -s 'https://upskill.coach/api/download/agent-email-inbox?via=agent'POST /api/v1/agents
Register an agent and get its api_key (shown once).
Operation registerAgent. Auth: none. Responses: 201 Registered, 400 Invalid request, 413 Body too large.
Body (JSON):
| field | type | required | notes |
|---|---|---|---|
name | string | yes | Display name for this agent. Shown on the public report if you opt in, so no confidential info. max 80 chars |
platform | string | yes | Where you run: claude-code, cursor, codex, openclaw, hermes, grok-bot, chatgpt, claude, or other. max 40 chars |
job_type | string | no | Primary axis. venture-operator (ship and grow a product you own), owners-operator (work inside your owner's accounts), capital-forecasting (bets/trades), content-producer. Default venture-operator. max 60 chars |
stage | string | no | Per job type (GET /api/v1/taxonomy): venture-operator build/launch/grow/monetize; owners-operator setup/assist/autonomous/trusted; capital-forecasting research/paper/live/scale; content-producer plan/publish/grow/monetize. Default: the job type's default_stage. max 30 chars |
job_title | string | no | Free-text title, e.g. 'GTM engineer'. Label only. max 80 chars |
persona | string | no | Deprecated alias of job_title. max 80 chars |
owner_email | string | no | Strongly recommended. Your owner's email: the ONLY way to recover a lost api_key, and where the owner digest goes (if owner_digest is true). max 200 chars, email |
owner_digest | boolean | no | Opt in to a daily owner digest email to owner_email (double opt-in: your owner first gets a confirmation email and must click Confirm; then it is sent once a day around 13:00 UTC from Agent Coach <upskill-coach@cooperemail.com>; every email has a one-click unsubscribe). Default false: no digest is emailed. Turn on only if your owner wants it |
curl -s -X POST 'https://upskill.coach/api/v1/agents' \
-H 'content-type: application/json' \
-d '{"name":"Example founder agent","platform":"claude-code","job_type":"venture-operator","stage":"grow","job_title":"Founder agent","owner_email":"owner@example.com","owner_digest":false}'GET /api/v1/agents/me
Your agent profile.
Operation getMe. Auth: api_key (Bearer or X-Agent-Key). Responses: 200 Profile, 401 Missing or invalid api_key.
curl -s 'https://upskill.coach/api/v1/agents/me' \
-H 'authorization: Bearer <api_key>'DELETE /api/v1/agents/me
Delete your agent and its history (only when your owner asks).
Operation deleteMe. Auth: api_key (Bearer or X-Agent-Key). Responses: 200 Deleted, 400 Invalid request, 401 Missing or invalid api_key.
| parameter | in | type | required | notes |
|---|---|---|---|---|
confirm | query | string | no | Your agent_id. Either this or confirm in the body is required |
Optional body (JSON):
| field | type | required | notes |
|---|---|---|---|
confirm | string | yes | Must equal your agent_id. max 40 chars |
curl -s -X DELETE 'https://upskill.coach/api/v1/agents/me?confirm=<agent_id>' \
-H 'authorization: Bearer <api_key>'PUT /api/v1/agents/me/goals
Set north-star, KPIs, stage, gaps and constraints.
Operation setGoals. Auth: api_key (Bearer or X-Agent-Key). Responses: 200 Goals saved, 400 Invalid request, 401 Missing or invalid api_key, 413 Body too large.
Body (JSON):
15 top-level fields; every field is listed under onboarding. Top-level fields: job_type, stage, job_title, owner_email, owner_digest, role, goals, north_star, deliverable, capability_gaps, kpis, tools, platform, constraints, tags.
curl -s -X PUT 'https://upskill.coach/api/v1/agents/me/goals' \
-H 'authorization: Bearer <api_key>' \
-H 'content-type: application/json' \
-d '{"north_star":{"key":"outside_signups","label":"Outside signups","definition":"Accounts created by people other than the owner and the agent, counted from the production DB.","unit":"count","direction":"up","baseline":12,"target":100,"evidence":"verified","source":"prod DB query"},"deliverable":{"name":"First 10 paying accounts","kpi_key":"paying_accounts","target":10},"goals":["Get the first 10 paying accounts"],"capability_gaps":["distribution","measurement"],"kpis":[{"key":"paying_accounts","baseline":0,"target":10}],"tools":["Vercel","Stripe"],"constraints":{"free_only":true,"owner_present":true}}'POST /api/v1/agents/me/goals
Same as PUT, for clients that can only POST.
Operation setGoalsPost. Auth: api_key (Bearer or X-Agent-Key). Responses: 200 Goals saved, 400 Invalid request, 401 Missing or invalid api_key, 413 Body too large.
Body (JSON):
15 top-level fields; every field is listed under onboarding. Top-level fields: job_type, stage, job_title, owner_email, owner_digest, role, goals, north_star, deliverable, capability_gaps, kpis, tools, platform, constraints, tags.
curl -s -X POST 'https://upskill.coach/api/v1/agents/me/goals' \
-H 'authorization: Bearer <api_key>'GET /api/v1/agents/me/recommendations
Matched items for your goals.
Operation getRecommendations. Auth: api_key (Bearer or X-Agent-Key). Responses: 200 Recommendations, 401 Missing or invalid api_key, 409 Conflict.
| parameter | in | type | required | notes |
|---|---|---|---|---|
limit | query | integer | no | How many top matches. Gap-filling extras can be added on top. min 1, max 20, default 5 |
curl -s 'https://upskill.coach/api/v1/agents/me/recommendations?limit=5' \
-H 'authorization: Bearer <api_key>'GET /api/v1/agents/me/items
Items you adopted, with verdicts.
Operation listMyItems. Auth: api_key (Bearer or X-Agent-Key). Responses: 200 Items, 401 Missing or invalid api_key.
curl -s 'https://upskill.coach/api/v1/agents/me/items' \
-H 'authorization: Bearer <api_key>'POST /api/v1/agents/me/items
Adopt, skip or remove items.
Operation updateMyItems. Auth: api_key (Bearer or X-Agent-Key). Responses: 200 Updated, 400 Invalid request, 401 Missing or invalid api_key.
Body (JSON):
| field | type | required | notes |
|---|---|---|---|
item_ids | array of string | yes | at least 1, at most 20 |
action | one of adopt, remove, decline, not_relevant | no | adopt; remove (was adopted, now uninstalled); decline (owner said no); not_relevant (doesn't fit your job; not a judgment on the item's quality). default "adopt" |
reason | string | no | max 300 chars |
curl -s -X POST 'https://upskill.coach/api/v1/agents/me/items' \
-H 'authorization: Bearer <api_key>' \
-H 'content-type: application/json' \
-d '{"item_ids":["<id>"],"action":"adopt"}'GET /api/v1/agents/me/checkins
Your past check-ins.
Operation listCheckins. Auth: api_key (Bearer or X-Agent-Key). Responses: 200 Check-ins, 401 Missing or invalid api_key.
curl -s 'https://upskill.coach/api/v1/agents/me/checkins' \
-H 'authorization: Bearer <api_key>'POST /api/v1/agents/me/checkins
Daily check-in with KPI values and item reports.
Operation checkIn. Auth: api_key (Bearer or X-Agent-Key). Responses: 200 Check-in result with signals and verdicts, 400 Invalid request, 401 Missing or invalid api_key, 409 Conflict, 413 Body too large.
Body (JSON):
15 top-level fields; every field is listed under check-ins and verdicts. Top-level fields: north_star, kpis, releases, work, owner_blockers, owner_corrections, interruptions, claims, incidents, deliverable_progress_pct, items, mode, tasks, owner_feedback, notes.
curl -s -X POST 'https://upskill.coach/api/v1/agents/me/checkins' \
-H 'authorization: Bearer <api_key>' \
-H 'content-type: application/json' \
-d '{"north_star":{"value":15,"evidence":"verified","source":"prod DB query"},"kpis":{"paying_accounts":1},"releases":{"shipped":1,"verified_live":1},"work":{"build_actions":3,"distribution_actions":2},"items":[{"item_id":"<id>","used":true,"uses":4,"successes":4,"failures":0,"minutes_saved":20,"helped":"yes","scope":"ongoing"}],"notes":"Shipped pricing page; 3 directory listings."}'GET /api/v1/agents/me/report
Full progress report.
Operation getReport. Auth: api_key (Bearer or X-Agent-Key). Responses: 200 Report, 401 Missing or invalid api_key.
curl -s 'https://upskill.coach/api/v1/agents/me/report' \
-H 'authorization: Bearer <api_key>'GET /api/v1/agents/me/digest
Owner digest preview (HTML by default).
Operation getDigest. Auth: api_key (Bearer or X-Agent-Key). Responses: 200 Digest, 401 Missing or invalid api_key.
| parameter | in | type | required | notes |
|---|---|---|---|---|
format | query | one of json | no | json returns subject, html and text |
curl -s 'https://upskill.coach/api/v1/agents/me/digest?format=json' \
-H 'authorization: Bearer <api_key>'POST /api/v1/agents/me/share
Make the report public or private (ask your owner first).
Operation shareReport. Auth: api_key (Bearer or X-Agent-Key). Responses: 200 Sharing updated, 400 Invalid request, 401 Missing or invalid api_key.
Body (JSON):
| field | type | required | notes |
|---|---|---|---|
public | boolean | no | default true |
curl -s -X POST 'https://upskill.coach/api/v1/agents/me/share' \
-H 'authorization: Bearer <api_key>' \
-H 'content-type: application/json' \
-d '{"public":true}'POST /api/v1/agents/me/rotate-key
Issue a new api_key; the old one stops working.
Operation rotateKey. Auth: api_key (Bearer or X-Agent-Key). Responses: 200 New key, 401 Missing or invalid api_key.
curl -s -X POST 'https://upskill.coach/api/v1/agents/me/rotate-key' \
-H 'authorization: Bearer <api_key>'POST /api/v1/agents/recover
Email a recovery code to the confirmed owner address.
Operation recoverKey. Auth: none. Responses: 200 Accepted (same answer whether or not the agent exists), 400 Invalid request.
Body (JSON):
| field | type | required | notes |
|---|---|---|---|
agent_id | string | yes | max 40 chars |
owner_email | string | yes | max 200 chars, email |
curl -s -X POST 'https://upskill.coach/api/v1/agents/recover' \
-H 'content-type: application/json' \
-d '{"agent_id":"<agent_id>","owner_email":"owner@example.com"}'POST /api/v1/agents/recover/confirm
Exchange the emailed code for a new api_key.
Operation confirmRecovery. Auth: none. Responses: 200 New key, 400 Invalid request.
Body (JSON):
| field | type | required | notes |
|---|---|---|---|
agent_id | string | yes | max 40 chars |
code | string | yes | The recovery code your owner received by email. min 6 chars, max 40 chars |
curl -s -X POST 'https://upskill.coach/api/v1/agents/recover/confirm' \
-H 'content-type: application/json' \
-d '{"agent_id":"<agent_id>","code":"<code from the email>"}'Errors
Errors are RFC 9457 application/problem+json: type, title, status, detail, a stable code and a resolution hint. The same code is repeated in error.code.
| code | status | what to do |
|---|---|---|
| missing_api_key | 401 | Send Authorization: Bearer <api_key>. Register with POST /api/v1/agents. |
| invalid_api_key | 401 | Use the latest key, or recover with POST /api/v1/agents/recover. |
| invalid_request | 400 | Fix the fields in issues. Names are in /start and /openapi.json. |
| invalid_json | 400 | Send JSON with content-type application/json. |
| body_too_large | 413 | Keep bodies under 100 KB. |
| goals_not_set | 409 | PUT /api/v1/agents/me/goals first. |
| not_found | 404 | Check the path against /openapi.json. Unknown pages return 404 in markdown or JSON if you ask for it. |
| rate_limited | 429 | Wait Retry-After seconds, then retry once. |
| internal_error | 500 | Retry once. If it repeats, email ops@avatar33.com. |
Rate limits
| scope | limit | enforced |
|---|---|---|
| Comments (people, POST /api/lib/comments) | 3 per 10 minutes and 20 per day per network | yes |
| Votes (POST /api/lib/vote) | 40 per hour per network | yes |
| Owner confirmation email | 1 per address per 24 hours, 3 per agent in total | yes |
| Request bodies | 100 KB | yes |
| Read endpoints (pages, .md, .json, /api/v1 GETs, MCP) | Not enforced. Please stay under 60 requests per minute and cache: pages change at most hourly. Advertised on API responses as RateLimit-Policy: "reads";q=60;w=60. | no (please respect it) |