Skip to main content
Ship’s API routing system is built on Koa with automatic route discovery. Endpoints are auto-registered from resources/<name>/endpoints/ — no manual route files needed. All routes pass through global middlewares before reaching their handlers.

Request Flow

Auto-Discovery

Routes register automatically. Each file in resources/<name>/endpoints/ that default-exports createEndpoint({...}) is mounted at /<name>/<path>.
resources/projects/endpoints/list.ts
import createEndpoint from 'routes/createEndpoint';

export default createEndpoint({
  method: 'get',
  path: '/',

  async handler(ctx) {
    // GET /projects/
    return { projects: [] };
  },
});
  • Resource name = URL prefix: resources/projects//projects/*
  • No manual registration — just place files in endpoints/
  • Check startup logs for: [routes] METHOD /resource/path

Auth Default

Every endpoint requires authentication unless isPublic is in the middlewares array. isPublic is a sentinel reference — the route system checks middleware === isPublic by identity.
import createEndpoint from 'routes/createEndpoint';
import isPublic from 'middlewares/isPublic';

export default createEndpoint({
  method: 'post',
  path: '/sign-up',
  schema,
  middlewares: [isPublic],

  async handler(ctx) {
    // accessible without auth
  },
});
For admin endpoints, use isAdmin middleware which checks the x-admin-key header against config.ADMIN_KEY.

Authentication Flow

See Also