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.
npx claudepluginhub cameronapak/bknd-expert --plugin bknd-research-skillsThis skill uses the workspace's default tool permissions.
Explore and understand Bknd's auto-generated REST API endpoints.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Checks Next.js compilation errors using a running Turbopack dev server after code edits. Fixes actionable issues before reporting complete. Replaces `next build`.
Explore and understand Bknd's auto-generated REST API endpoints.
UI steps: Admin Panel > Data > Entities
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) │
└─────────────────────────────────────────────────────────────┘
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
...
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}'
| 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"}'
| 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
| 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
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
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}`);
}
}
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"
}
}
Navigate to: http://localhost:7654/admin
Admin panel shows:
Admin panel provides:
| 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 |
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"]
}'
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
# Check if API is running
curl http://localhost:7654/api/auth/me
# Returns user info or 401
# 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
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");
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
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
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}]}}'
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
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"}'
| 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 |
DO:
bknd debug routes to list all endpoints/query endpoint for complex filtersDON'T:
/api/ prefix on API paths/api/auth/password/login)