# Dynamic Routes

> A Claude skill from jkaninda/okapi-skills.

- **Type:** Skill
- **Install:** `agentstack add skill-jkaninda-okapi-skills-dynamic-routes`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [jkaninda](https://agentstack.voostack.com/s/jkaninda)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [jkaninda](https://github.com/jkaninda)
- **Source:** https://github.com/jkaninda/okapi-skills/tree/main/dynamic_routes

## Install

```sh
agentstack add skill-jkaninda-okapi-skills-dynamic-routes
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

## Okapi Dynamic Routes

Okapi can enable/disable individual routes, whole groups, and OpenAPI documentation at runtime. Disabled routes respond with 404 — no redeploy required, and the OpenAPI document refreshes automatically.

### Disabling / Enabling a Single Route

```go
route := o.Get("/admin/console", adminHandler)

route.Disable() // requests now get 404
route.Enable()  // back online
```

### Disabling / Enabling a Whole Group

```go
admin := o.Group("/admin", jwtAuth.Middleware)
admin.Get("/users", listUsers)
admin.Get("/audit", listAudit)

admin.Disable() // every route under /admin is 404
admin.Enable()
```

### Toggling OpenAPI Documentation at Runtime

```go
o.WithOpenAPIDisabled() // /docs, /swagger, /redoc, /scalar, /openapi.* return 404

// Bring them back
o.WithOpenAPIDocs(okapi.OpenAPI{Title: "My API", Version: "1.0.0"})
```

### Marking a Route Deprecated

`Deprecated()` keeps the route active but tags it in OpenAPI so clients see a warning. Combine with `Hide()` to remove it from docs entirely.

```go
o.Get("/v1/books", legacyHandler).Deprecated()
o.Get("/internal/metrics", metricsHandler).Hide()
```

Group-level:

```go
v1 := o.Group("/api/v1").Deprecated() // all routes flagged deprecated
```

### Feature Flag Pattern

Toggle routes from config without restarting the process:

```go
type Toggles struct {
    BetaSearch bool
    Sandbox    bool
}

func registerRoutes(o *okapi.Okapi, t *Toggles) {
    search := o.Get("/search", searchHandler)
    sandbox := o.Group("/sandbox", devOnlyMiddleware)
    sandbox.Get("/echo", echoHandler)

    apply := func() {
        if t.BetaSearch { search.Enable() } else { search.Disable() }
        if t.Sandbox    { sandbox.Enable() } else { sandbox.Disable() }
    }

    apply() // initial state
    // Re-call apply() whenever t changes (config reload, admin endpoint, etc.)
}
```

### Admin Endpoint to Toggle Routes

Capture the routes you want to toggle when you register them; `o.Routes()` returns a snapshot (copy) of `Route` values, so iterating it cannot mutate the live registry.

```go
type RouteToggle struct {
    Path    string `json:"path" required:"true"`
    Enabled bool   `json:"enabled"`
}

func wireToggles(o *okapi.Okapi) {
    registry := map[string]*okapi.Route{
        "/beta/search": o.Get("/beta/search", searchHandler),
        "/sandbox":     o.Get("/sandbox", sandboxHandler),
    }

    o.Post("/admin/routes/toggle", okapi.H(func(c *okapi.Context, in *RouteToggle) error {
        route, ok := registry[in.Path]
        if !ok {
            return c.AbortNotFound("route not found")
        }
        if in.Enabled { route.Enable() } else { route.Disable() }
        return c.OK(okapi.M{"path": in.Path, "enabled": in.Enabled})
    }))
}
```

> `o.Routes()` returns a snapshot of registered routes for introspection — useful for listing/exposing what exists, not for mutating state.

### When Documentation Refreshes

The OpenAPI document is rebuilt lazily, so the next request to `/openapi.json` (or any UI route) reflects the current enable/disable state and any newly added webhooks. No cache invalidation step is needed.

### Hiding from Docs (Without Disabling)

```go
o.Get("/internal/health", healthHandler).Hide()       // still serves traffic, omitted from docs
o.Get("/internal/health", healthHandler, okapi.DocHide())
```

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [jkaninda](https://github.com/jkaninda)
- **Source:** [jkaninda/okapi-skills](https://github.com/jkaninda/okapi-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-jkaninda-okapi-skills-dynamic-routes
- Seller: https://agentstack.voostack.com/s/jkaninda
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
