# Directory Structure for API Routes in 9router: A Complete Guide

> Learn the 9router API routes directory structure under src/app/api/. Discover how folder paths map to URL endpoints and implement handlers in route.js files. A complete Next.js guide.

- Repository: [decolua/9router](https://github.com/decolua/9router)
- Tags: how-to-guide
- Published: 2026-05-08

---

**The 9router API routes are organized under `src/app/api/` using Next.js App Router conventions, where folder paths map directly to URL endpoints and each route is implemented as a [`route.js`](https://github.com/decolua/9router/blob/main/route.js) file exporting HTTP method handlers.**

Understanding the directory structure for API routes in 9router is essential for developers contributing to or integrating with the decolua/9router repository. The project leverages Next.js 13+ App Router file-based routing, creating a predictable hierarchy that mirrors public URL paths. This structure groups related functionality into semantic top-level folders while maintaining clear separation between stable and beta endpoints.

## Root Directory and File Conventions

All server-side API handlers reside in the **`src/app/api/`** directory. The 9router codebase follows the Next.js convention where the filesystem hierarchy directly corresponds to the HTTP path structure. Each endpoint is implemented as a **[`route.js`](https://github.com/decolua/9router/blob/main/route.js)** (or [`route.ts`](https://github.com/decolua/9router/blob/main/route.ts)) file that exports named functions for supported HTTP methods (`GET`, `POST`, `PUT`, `DELETE`).

The mapping is literal: a request to `/api/v1/models` resolves to the file at [`src/app/api/v1/models/route.js`](https://github.com/decolua/9router/blob/main/src/app/api/v1/models/route.js). This convention eliminates manual route configuration and makes the API surface immediately discoverable by browsing the source tree.

## Top-Level Route Organization

The `src/app/api/` directory contains semantic folders that group endpoints by feature area or API version:

- **`v1/`** – Current stable API (v1) containing primary endpoints like `v1/models`, `v1/chat/completions`, and `v1/audio/voices`
- **`v1beta/`** – Early-access beta API for experimental features (e.g., `v1beta/models`)
- **`usage/`** – Usage statistics and logging endpoints including `usage/stream` and `usage/stats`
- **`providers/`** – Provider management routes supporting dynamic IDs (`providers/[id]/models`)
- **`tunnel/`** – Tailscale tunnel helpers such as `tunnel/enable` and `tunnel/tailscale-install`
- **`oauth/`** – OAuth flow handlers for providers like Kiro and GitLab (`oauth/kiro/social-exchange`, `oauth/[provider]/[action]`)
- **`cli-tools/`** – Settings exposed to local CLI clients (`cli-tools/opencode-settings`, `cli-tools/claude-settings`)
- **`media-providers/tts/`** – Text-to-speech provider endpoints (`media-providers/tts/voices`)
- **`cloud/`** – Cloud-related administrative routes (`cloud/auth`, `cloud/credentials/update`)
- **`translator/`** – Translation helper endpoints (`translator/translate`)
- **`keys/`** – API key CRUD operations with dynamic ID support (`keys/[id]`)
- **`settings/`** – Global configuration endpoints (`settings`, `settings/require-login`)
- **`init/`**, **`health/`**, **`shutdown/`** – Lifecycle management helpers

## Dynamic Routes and Parameterized Endpoints

9router utilizes **Next.js dynamic route segments** for resources requiring variable identifiers. Dynamic segments use bracket notation in folder names, such as `[id]` or `[provider]`, which the runtime populates from the URL path.

Key dynamic route implementations include:

- **`src/app/api/providers/[id]/models/route.js`** – Returns available models for a specific provider ID (e.g., `/api/providers/openai/models`)
- **`src/app/api/keys/[id]/route.js`** – Handles CRUD operations for a specific API key
- **`src/app/api/oauth/[provider]/[action]/route.js`** – Generic handler supporting multiple OAuth providers and actions through path parameters

These dynamic segments enable RESTful URL patterns while maintaining a flat, manageable file structure.

## Route Implementation Pattern

Each [`route.js`](https://github.com/decolua/9router/blob/main/route.js) file exports async functions named after the HTTP methods they handle. The 9router source code implements standard request/response patterns within these handlers, parsing query parameters and request bodies according to the endpoint's requirements.

For example, [`src/app/api/v1/chat/completions/route.js`](https://github.com/decolua/9router/blob/main/src/app/api/v1/chat/completions/route.js) exports a `POST` handler that processes chat completion requests, while [`src/app/api/v1/models/route.js`](https://github.com/decolua/9router/blob/main/src/app/api/v1/models/route.js) exports a `GET` handler for listing available AI models. The [`src/app/api/v1/route.js`](https://github.com/decolua/9router/blob/main/src/app/api/v1/route.js) file serves as an entry point that groups top-level v1 routes and may handle sub-route delegation.

## Practical Usage Examples

The following examples demonstrate how the directory structure translates to actual API calls:

Fetching the model list from the v1 endpoint:

```javascript
await fetch('https://your-9router-host/api/v1/models')
  .then(r => r.json())
  .then(console.log);

```

Streaming usage events from the `usage/stream` endpoint:

```javascript
const evt = new EventSource('https://your-9router-host/api/usage/stream');
evt.onmessage = e => console.log('usage event:', JSON.parse(e.data));

```

Accessing a specific provider's models using dynamic routing:

```javascript
const providerId = 'openai';
await fetch(`https://your-9router-host/api/providers/${providerId}/models`)
  .then(r => r.json())
  .then(console.log);

```

## Summary

- **Base Location**: All API routes reside in `src/app/api/` following Next.js App Router conventions.
- **File Convention**: Each endpoint is a [`route.js`](https://github.com/decolua/9router/blob/main/route.js) file exporting HTTP method handlers (`GET`, `POST`, etc.).
- **URL Mapping**: Folder paths under `src/app/api/` directly map to `/api/**` URLs (e.g., `v1/models` → `/api/v1/models`).
- **Versioning**: Separate `v1/` and `v1beta/` folders support stable and experimental API versions.
- **Dynamic Routing**: Bracket notation (`[id]`, `[provider]`) enables parameterized endpoints like `providers/[id]/models`.
- **Feature Grouping**: Top-level folders organize endpoints by domain (usage, providers, oauth, cloud, etc.).

## Frequently Asked Questions

### What is the base directory for 9router API routes?

All API routes in the decolua/9router repository are located under **`src/app/api/`**. This root directory uses Next.js App Router file-system routing conventions, where the folder structure directly corresponds to the URL path structure.

### How does 9router handle API versioning?

9router implements API versioning through separate top-level folders **`v1/`** and **`v1beta/`** under `src/app/api/`. The `v1/` folder contains the current stable API endpoints, while `v1beta/` houses experimental or early-access features, allowing developers to test new functionality without affecting production integrations.

### What file naming convention does 9router use for API endpoints?

Each API endpoint is implemented as a **[`route.js`](https://github.com/decolua/9router/blob/main/route.js)** file (or [`route.ts`](https://github.com/decolua/9router/blob/main/route.ts) for TypeScript) located within its respective folder. This file exports named functions corresponding to HTTP methods (e.g., `export async function GET(request)`), which Next.js automatically invokes when matching requests arrive at the corresponding URL path.

### How are dynamic routes with parameters implemented in 9router?

Dynamic routes use bracket notation in folder names, such as **`[id]`** or **`[provider]`**, placed within the route hierarchy. For example, `src/app/api/providers/[id]/models/route.js` handles requests to `/api/providers/{id}/models`, where the runtime captures the `id` segment from the URL and makes it available to the route handler through the `params` object.