Agent Skills: API Discovery

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.

UncategorizedID: cameronapak/bknd-skills/bknd-api-discovery

Install this agent skill to your local

pnpm dlx add-skill https://github.com/cameronapak/bknd-skills/tree/HEAD/skills/bknd-api-discovery

Skill Files

Browse the full folder contents for bknd-api-discovery.

Download Skill

Loading file tree…

skills/bknd-api-discovery/SKILL.md

Skill Metadata

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:

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

# 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:

# 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:

# 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:

# 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:

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:

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):

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

Success (single):

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

Error:

{
  "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)

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

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

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

Explore Available Data

# 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

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:

# 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:

# 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:

# 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):

# 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:

# 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