bknd-api-discovery
npx skills add https://github.com/cameronapak/bknd-skills --skill bknd-api-discovery
Agent 安装分布
Skill 文档
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
- Click Data in sidebar
- View list of all entities
- 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 routesto list all endpoints - Check admin panel for visual schema exploration
- Use POST
/queryendpoint 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