Skip to content
Back to skills

Bknd Api Discovery

ASecurity

Use when exploring Bknd's auto-generated API endpoints. Covers REST endpoint patterns, route listing, module base paths, SDK method mapping, admin panel API explorer, and understanding the API structure.

  • 42 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added February 10, 2026
developmenttypescriptgobashtestingdebuggingapifrontenddocumentation

Works with

  • cli
  • api

Security analysis

A96/100
  • mediumUses curl or wget to download content

Pro shows the line behind each finding and how to fix it

Scanned February 12, 2026

npx -y skills add cameronapak/freedom-stack-v3 --skill bknd-api-discovery --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Bknd Api Discovery?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Bknd Api Discovery
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/cameronapak-bknd-api-discovery/badge)](https://www.skillsdirectory.com/skills/cameronapak-bknd-api-discovery)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: bknd-api-discovery
description: Use when exploring Bknd's auto-generated API endpoints. Covers REST endpoint patterns, route listing, module base paths, SDK method mapping, admin panel API explorer, and understanding the API structure.
---

# API Discovery

Explore and understand Bknd's auto-generated REST API endpoints.

## Prerequisites

- Running Bknd instance (local or deployed)
- Access to admin panel (optional but helpful)
- Basic understanding of REST APIs

## When to Use UI Mode

- Browsing available entities and their fields
- Viewing schema structure visually
- Quick endpoint exploration via browser

**UI steps:** Admin Panel > Data > Entities

## When to Use Code Mode

- Listing all registered routes programmatically
- Understanding endpoint patterns for integration
- Debugging route registration issues
- Building API documentation

## Understanding Bknd's API Structure

Bknd auto-generates REST endpoints for all configured modules:

```
┌─────────────────────────────────────────────────────────────┐
│                    Bknd API Structure                       │
├─────────────────────────────────────────────────────────────┤
│  /api/data      → CRUD for all entities                     │
│  /api/auth      → Authentication (login, register, logout)  │
│  /api/media     → File uploads and serving                  │
│  /api/system    → System operations                         │
│  /flow          → Flow management and triggers              │
│  /admin         → Admin UI (if enabled)                     │
└─────────────────────────────────────────────────────────────┘
```

## Code Approach

### Step 1: List All Routes (CLI)

Use the debug command to list all registered routes:

```bash
bknd debug routes
```

**Output:**

```
GET     /admin/*
GET     /api/auth/me
POST    /api/auth/password/login
POST    /api/auth/logout
POST    /api/auth/register
GET     /api/data/:entity
POST    /api/data/:entity
GET     /api/data/:entity/:id
PATCH   /api/data/:entity/:id
DELETE  /api/data/:entity/:id
POST    /api/media/upload
GET     /api/media/:path
...
```

### Step 2: Data API Endpoints

All entities get CRUD endpoints automatically:

| Method | Path | Description | SDK Method |
|--------|------|-------------|------------|
| GET | `/api/data/:entity` | List records | `api.data.readMany(entity)` |
| POST | `/api/data/:entity/query` | List (complex query) | `api.data.readMany(entity, query)` |
| GET | `/api/data/:entity/:id` | Get single record | `api.data.readOne(entity, id)` |
| GET | `/api/data/:entity/:id/:ref` | Get related records | `api.data.readManyByReference(...)` |
| POST | `/api/data/:entity` | Create record(s) | `api.data.createOne/Many(entity, data)` |
| PATCH | `/api/data/:entity/:id` | Update single | `api.data.updateOne(entity, id, data)` |
| PATCH | `/api/data/:entity` | Update many | `api.data.updateMany(entity, where, data)` |
| DELETE | `/api/data/:entity/:id` | Delete single | `api.data.deleteOne(entity, id)` |
| DELETE | `/api/data/:entity` | Delete many | `api.data.deleteMany(entity, where)` |
| POST | `/api/data/:entity/fn/count` | Count records | `api.data.count(entity, where)` |
| POST | `/api/data/:entity/fn/exists` | Check existence | `api.data.exists(entity, where)` |

**Example: Explore posts entity**

```bash
# List all posts
curl http://localhost:7654/api/data/posts

# Get post by ID
curl http://localhost:7654/api/data/posts/1

# Get with query params
curl "http://localhost:7654/api/data/posts?limit=10&sort[created_at]=desc"

# Get with relations
curl "http://localhost:7654/api/data/posts?with[]=author&with[]=comments"

# Complex query via POST
curl -X POST http://localhost:7654/api/data/posts/query \
  -H "Content-Type: application/json" \
  -d '{"where": {"status": "published"}, "limit": 10}'
```

### Step 3: Auth API Endpoints

| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/auth/me` | Current user info |
| POST | `/api/auth/:strategy/login` | Login (e.g., `/api/auth/password/login`) |
| POST | `/api/auth/register` | Register new user |
| POST | `/api/auth/logout` | Logout |
| GET | `/api/auth/:strategy/redirect` | OAuth redirect |
| GET | `/api/auth/:strategy/callback` | OAuth callback |

**Example:**

```bash
# Check current user
curl http://localhost:7654/api/auth/me \
  -H "Authorization: Bearer $TOKEN"

# Login
curl -X POST http://localhost:7654/api/auth/password/login \
  -H "Content-Type: application/json" \
  -d '{"email": "user@test.com", "password": "pass123"}'

# Register
curl -X POST http://localhost:7654/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{"email": "new@test.com", "password": "pass123"}'
```

### Step 4: Media API Endpoints

| Method | Path | Description |
|--------|------|-------------|
| POST | `/api/media/upload` | Upload file |
| GET | `/api/media/:path` | Serve/download file |

**Example:**

```bash
# Upload file
curl -X POST http://localhost:7654/api/media/upload \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@image.png"

# Serve file
curl http://localhost:7654/api/media/uploads/image.png
```

### Step 5: Flow Endpoints

| Method | Path | Description |
|--------|------|-------------|
| GET | `/flow` | List all flows |
| GET | `/flow/:name` | Get flow details |
| GET | `/flow/:name/run` | Manually run flow |
| * | Custom trigger path | HTTP trigger endpoints |

**Example:**

```bash
# List flows
curl http://localhost:7654/flow

# Run flow manually
curl http://localhost:7654/flow/my-flow/run
```

### Step 6: Programmatic Route Discovery

Access route information from your code:

```typescript
import { App } from "bknd";

const app = new App({ /* config */ });
await app.build();

// Get Hono server instance
const server = app.server;

// Routes are registered on the Hono instance
// Use bknd debug routes for listing
```

### Step 7: Discover Entity Schema

Query the system to understand available entities:

```typescript
import { Api } from "bknd";

const api = new Api({ host: "http://localhost:7654" });

// List available entities by checking which respond
const entities = ["posts", "users", "comments", "categories"];

for (const entity of entities) {
  const { ok } = await api.data.readMany(entity, { limit: 1 });
  if (ok) {
    console.log(`Entity exists: ${entity}`);
  }
}
```

### Step 8: Response Format Discovery

All endpoints return consistent response format:

**Success (list):**

```json
{
  "data": [
    { "id": 1, "title": "Post 1" },
    { "id": 2, "title": "Post 2" }
  ],
  "meta": {
    "total": 50,
    "limit": 20,
    "offset": 0
  }
}
```

**Success (single):**

```json
{
  "data": { "id": 1, "title": "Post 1" }
}
```

**Error:**

```json
{
  "error": {
    "message": "Record not found",
    "code": "NOT_FOUND"
  }
}
```

## UI Approach: Admin Panel

### Step 1: Access Admin Panel

Navigate to: `http://localhost:7654/admin`

### Step 2: Browse Entities

1. Click **Data** in sidebar
2. View list of all entities
3. Click entity to see:
   - All fields with types
   - Relationships
   - Sample data

### Step 3: View Entity Structure

Admin panel shows:
- Field names and types
- Required vs optional fields
- Default values
- Relation configurations

### Step 4: Test Queries

Admin panel provides:
- Data browser for each entity
- Filter/sort interface
- Create/edit forms
- Relationship navigation

## Query Parameter Reference

### Data Endpoints

| Parameter | Example | Description |
|-----------|---------|-------------|
| `limit` | `?limit=10` | Max records to return |
| `offset` | `?offset=20` | Skip N records |
| `sort[field]` | `?sort[created_at]=desc` | Sort by field |
| `where[field]` | `?where[status]=published` | Filter by field |
| `with[]` | `?with[]=author` | Include relation |
| `join[]` | `?join[]=author` | Join relation (same result) |
| `select[]` | `?select[]=id&select[]=title` | Select specific fields |

### Complex Queries (POST)

```bash
curl -X POST http://localhost:7654/api/data/posts/query \
  -H "Content-Type: application/json" \
  -d '{
    "where": {
      "status": "published",
      "views": { "$gt": 100 }
    },
    "sort": { "created_at": "desc" },
    "limit": 10,
    "offset": 0,
    "with": ["author", "category"]
  }'
```

## SDK Method to Endpoint Mapping

```typescript
import { Api } from "bknd";
const api = new Api({ host: "http://localhost:7654" });

// Method                        → Endpoint
api.data.readMany("posts")       // GET  /api/data/posts
api.data.readOne("posts", 1)     // GET  /api/data/posts/1
api.data.createOne("posts", {})  // POST /api/data/posts
api.data.updateOne("posts", 1, {})// PATCH /api/data/posts/1
api.data.deleteOne("posts", 1)   // DELETE /api/data/posts/1

api.auth.login("password", {})   // POST /api/auth/password/login
api.auth.register({})            // POST /api/auth/register
api.auth.logout()                // POST /api/auth/logout
api.auth.me()                    // GET  /api/auth/me

api.media.upload(file)           // POST /api/media/upload
```

## Testing Endpoints

### Quick Health Check

```bash
# Check if API is running
curl http://localhost:7654/api/auth/me
# Returns user info or 401
```

### Explore Available Data

```bash
# Try common entity names
for entity in posts users comments products orders; do
  echo "Testing $entity..."
  curl -s -o /dev/null -w "%{http_code}" http://localhost:7654/api/data/$entity
  echo ""
done
```

### Debug Script

```typescript
async function discoverApi(host: string) {
  const api = new Api({ host });

  console.log("API Discovery Report");
  console.log("===================");

  // Test auth
  const { ok: authOk } = await api.auth.me();
  console.log(`Auth endpoint: ${authOk ? "working" : "requires auth"}`);

  // Test common entities
  const testEntities = ["posts", "users", "comments", "products"];
  for (const entity of testEntities) {
    const { ok, meta } = await api.data.readMany(entity, { limit: 1 });
    if (ok) {
      console.log(`Entity "${entity}": ${meta?.total ?? "?"} records`);
    }
  }
}

discoverApi("http://localhost:7654");
```

## Common Pitfalls

### Wrong Base Path

**Problem:** 404 errors on API calls

**Fix:** Use correct base paths:

```bash
# WRONG
curl http://localhost:7654/data/posts
curl http://localhost:7654/posts

# CORRECT
curl http://localhost:7654/api/data/posts
```

### Auth Strategy in Path

**Problem:** Login fails

**Fix:** Include strategy name:

```bash
# WRONG
curl -X POST http://localhost:7654/api/auth/login

# CORRECT (password strategy)
curl -X POST http://localhost:7654/api/auth/password/login
```

### Query vs GET Params

**Problem:** Complex queries don't work via GET

**Fix:** Use POST for complex queries:

```bash
# Limited filtering via GET
curl "http://localhost:7654/api/data/posts?where[status]=published"

# Complex filtering via POST
curl -X POST http://localhost:7654/api/data/posts/query \
  -H "Content-Type: application/json" \
  -d '{"where": {"$or": [{"status": "published"}, {"featured": true}]}}'
```

### Entity Name Mismatch

**Problem:** 404 on entity endpoints

**Fix:** Use exact entity names (case-sensitive, usually lowercase):

```bash
# WRONG
curl http://localhost:7654/api/data/Posts
curl http://localhost:7654/api/data/post

# CORRECT
curl http://localhost:7654/api/data/posts
```

### Missing Content-Type

**Problem:** POST/PATCH returns 400

**Fix:** Include Content-Type header:

```bash
# WRONG
curl -X POST http://localhost:7654/api/data/posts \
  -d '{"title": "Test"}'

# CORRECT
curl -X POST http://localhost:7654/api/data/posts \
  -H "Content-Type: application/json" \
  -d '{"title": "Test"}'
```

## Endpoint Quick Reference

| Module | Base Path | Key Operations |
|--------|-----------|----------------|
| **Data** | `/api/data` | CRUD for all entities |
| **Auth** | `/api/auth` | Login, register, logout, me |
| **Media** | `/api/media` | Upload, serve files |
| **Flows** | `/flow` | List, view, run flows |
| **Admin** | `/admin` | Admin UI |

## DOs and DON'Ts

**DO:**
- Use `bknd debug routes` to list all endpoints
- Check admin panel for visual schema exploration
- Use POST `/query` endpoint for complex filters
- Include Content-Type header on POST/PATCH
- Test endpoints with curl before implementing

**DON'T:**
- Forget `/api/` prefix on API paths
- Mix up entity names (case matters)
- Use GET for complex queries with nested operators
- Assume entity names - verify they exist first
- Forget auth strategy in login path (`/api/auth/password/login`)

## Related Skills

- **bknd-client-setup** - Set up SDK in frontend
- **bknd-crud-read** - Query data with filtering
- **bknd-custom-endpoint** - Create custom API endpoints
- **bknd-login-flow** - Implement authentication
- **bknd-local-setup** - Set up local development

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.