Skill: REST API v1 (External)
SkillDev toolsAdding or modifying external REST API v1 endpoints in src/routes/api/v1/. Every change must ship with colocated `*.spec.ts` tests covering auth, success, and error paths, update `doc/development/rest-api.md`, keep patch coverage ≥ 90% on changed lines, and pass `make fix`, `make test-unit`, `make test-integration`, and `make test-e2e` before submission.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Skill: REST API v1 (External) skill
What this skill tells your AI
The instructions your AI receives, as published by exelearning/exelearning in .agents/skills/api-v1/SKILL.md and read by ahel’s review.
Parent: AGENTS.md | Related: backend-route, backend-service
When to Use
Adding or modifying external REST API v1 endpoints for third-party integrations.
Key Files
src/routes/api/v1/*.ts— API v1 route files (projects, pages, blocks, metadata, assets, components, export, users, types)src/routes/api/v1/*.spec.ts— colocated testssrc/routes/api/v1/index.ts— v1 route aggregationdoc/development/rest-api.md— API documentation (MUST be updated)
Critical Rule
/api/v1/* is for EXTERNAL integrations only (LMS, mobile apps, automation scripts, third-party tools).
| Use Case | Technology | Reason |
|---|---|---|
| External clients | REST API v1 | Stateless, JWT auth, easy to integrate |
| Internal UI | Yjs + WebSocket | Real-time sync, CRDT conflict resolution |
Internal frontend code (public/app/) must NEVER call /api/v1/*.
Test Pattern
import { describe, it, expect } from 'bun:test';
const app = new Elysia().use(v1Routes);
it('returns 401 without JWT', async () => {
const res = await app.handle(new Request('http://localhost/api/v1/projects'));
expect(res.status).toBe(401);
});
it('returns projects for authenticated user', async () => {
const token = createTestJwt({ userId: 1 });
const res = await app.handle(new Request('http://localhost/api/v1/projects', {
headers: { Cookie: `token=${token}` },
}));
expect(res.status).toBe(200);
});
Commands
bun test src/routes/api/v1/my-endpoint.spec.ts # Single endpoint
bun test src/routes/api/v1/ # All v1 tests
make fix # Lint
Gotchas
- Update
doc/development/rest-api.md— every endpoint change must be reflected in docs. Reviewers will reject PRs that skip this. - JWT auth on every endpoint — test both authenticated (200) and unauthenticated (401) paths.
- Authorization != Authentication — test that User A cannot access User B's resources (403).
- Register in
src/routes/api/v1/index.ts— new route files won't be loaded otherwise. - Internal frontend must never call v1 — if you see
fetch('/api/v1/...')inpublic/app/, that's a bug.
Done When
- Route in
src/routes/api/v1/with.spec.ts - Registered in
src/routes/api/v1/index.ts -
doc/development/rest-api.mdupdated - Tests cover 200, 401, and 403 paths
- 90%+ coverage
-
make fixpasses clean
Signals
- GitHub stars
- 142
- Forks
- 32
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
api-v1- Source
- github.com/exelearning/exelearning