External automation
The premise: your own Claude Code (or your CI/CD, or your custom script, or your future @vibstr/mcp-server install) drives Vibstr programmatically. Seven api_key-authenticated endpoints. BYO Anthropic key. We never mark up AI compute. You pay Anthropic, not us.
If Claude Code integration was the one curl in CLAUDE.md that auto-reports builds, this page is the other six curls that let your agent create plans, file items, list state, and post comments without a logged-in browser tab.
How it works
- Your project has an
api_keyin Vibstr (Settings → PROJECT → Connect Claude Code — the pane name is from the original Claude Code use case but the key works for any caller). Treat it like a password. - Your code POSTs to one of seven endpoints with
api_keyin the request body. - Vibstr validates the key, applies per-project rate limits, audit-logs the mutation, and executes.
- No user JWT needed. The
api_keyis the auth.
The api_key is project-scoped. A leak means an attacker can write to that one project — not your account, not your other projects, not your billing. Rotate from the same Settings pane that minted it.
Per-project rate limit at the time of writing: 60 calls per hour, sliding window. Tracked in vibelog_external_api_calls. Endpoints that invoke Anthropic (currently just vibstr-plan-create when derive_items: true) also charge against the project owner's daily AI cap unless the owner has BYO key set.
All endpoints return JSON. Errors come back as { error: { status, code, message, details? } }. Successful responses are flat objects (no envelope) so the happy path destructures in one line.
The 7 endpoints
Base URL: https://abtludluoynmwdfyvrse.supabase.co/functions/v1
1. vibstr-plan-create
Create a plan. Optionally derive items in the same call (one AI credit, returns the items along with the plan).
curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-plan-create \
-H "Content-Type: application/json" \
-d '{
"api_key": "YOUR_PROJECT_API_KEY",
"title": "1.13.x AI first-responder sidebar",
"body": "## Goal\nTurn AI into a per-item thinking partner...\n\n## Tasks\n- [ ] {type: change, area: drawer} Add item_context param\n- [ ] {type: change, area: drawer} Render sidebar shell",
"status": "active",
"target_build_id": null,
"derive_items": true
}'
Response:
{
"plan": {
"id": 14,
"title": "1.13.x AI first-responder sidebar",
"status": "active",
"created_at": "2026-05-12T03:18:22.000Z"
},
"items": [
{ "id": 283, "item_number": 283, "type": "change", "area": "drawer", "description": "Add item_context param" },
{ "id": 284, "item_number": 284, "type": "change", "area": "drawer", "description": "Render sidebar shell" }
],
"used_byo": false,
"remaining": 27
}
Set derive_items: false (or omit) to just create the plan shell with no AI cost. The target_build_id accepts any build id in this project; pass null to leave it unlinked.
2. vibstr-item-create
Create a single item with the full field set. No AI cost.
curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-item-create \
-H "Content-Type: application/json" \
-d '{
"api_key": "YOUR_PROJECT_API_KEY",
"type": "bug",
"area": "auth",
"description": "Sign-in form re-submits on every keystroke after first failure",
"labels": ["regression", "priority"],
"reported_build": "v1.12.2",
"priority": true,
"plan_id": null
}'
Response:
{
"item": { "id": 297, "item_number": 297, "status": "open", "type": "bug", "area": "auth" }
}
Fields supported: type, area, description, labels, reported_build, priority, assignee_id, due_at, estimate_value, estimate_unit, parent_item_id, plan_id. Type must be one of the project's categories. Area must be one of the project's areas (or null). Labels must reference names in the project's labels dictionary.
3. vibstr-item-bulk-create
Create up to 100 items in one shot. Partial-success reporting — failures don't roll back successes.
curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-item-bulk-create \
-H "Content-Type: application/json" \
-d '{
"api_key": "YOUR_PROJECT_API_KEY",
"items": [
{ "type": "bug", "area": "auth", "description": "..." },
{ "type": "change", "area": "drawer", "description": "..." },
{ "type": "bug", "area": "?invalid?", "description": "..." }
]
}'
Response:
{
"successes": [
{ "id": 298, "item_number": 298 },
{ "id": 299, "item_number": 299 }
],
"failures": [
{ "index": 2, "reason": "area '?invalid?' not in project areas" }
]
}
This is the workhorse for "I derived items from a spec, file them all now." Pair with vibstr-plan-create when you want them linked to a plan in one workflow, but separating create-plan from bulk-create-items lets you derive items locally with your own AI key first, then file them after editing.
4. vibstr-items-list
Read items with the full filter set + pagination.
curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-items-list \
-H "Content-Type: application/json" \
-d '{
"api_key": "YOUR_PROJECT_API_KEY",
"filters": {
"status": "open",
"priority": true,
"labels": ["regression"],
"plan_id": 14
},
"sort": "created_at_desc",
"limit": 50,
"offset": 0
}'
Response:
{
"items": [ /* up to 50 items */ ],
"total": 23,
"has_more": false
}
Filter fields: status, type, area, priority, assignee_id, labels (array — items matching ANY of the listed labels), plan_id, build_id, reported_build, parent_item_id, is_template, due_before, due_after. Sort options: created_at_desc (default), created_at_asc, updated_at_desc, due_at_asc, item_number_asc.
5. vibstr-plans-list
Read plans with derived-item counts joined.
curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-plans-list \
-H "Content-Type: application/json" \
-d '{
"api_key": "YOUR_PROJECT_API_KEY",
"include_archived": false,
"limit": 20
}'
Response:
{
"plans": [
{
"id": 14,
"title": "1.13.x AI first-responder sidebar",
"status": "active",
"derived_count": 8,
"derived_done_count": 5,
"target_build_id": 247,
"updated_at": "2026-05-12T03:18:22.000Z"
}
]
}
6. vibstr-build-create
Log a build + close items via the #NN parser. This is the same machinery the Claude Code integration calls, exposed for callers who want to log builds from outside a Claude Code run (CI/CD, custom scripts, the future @vibstr/mcp-server).
curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-build-create \
-H "Content-Type: application/json" \
-d '{
"api_key": "YOUR_PROJECT_API_KEY",
"version": "1.12.3",
"commit_hash": "a1b2c3d",
"commit_message": "Phase 8 catchup — closes #279 #280 #281 #282 #287\n\nFive themes...",
"prompt": "(optional original prompt)",
"output": "(optional run summary)"
}'
Response:
{
"build": { "id": 247, "build_number": 245, "build_version": "1.12.3" },
"closed_items": [279, 280, 281, 282, 287],
"ai_matches": 0,
"commit_matches": 5
}
The #NN parser is deterministic, charges zero AI credits, and runs first. If you want the AI semantic-match pass to run on top, pass output with enough text for the AI to chew on — same model and prompt as the Claude Code auto-ingest path. Pass output: null to skip the AI pass entirely.
7. vibstr-item-comment-create
Post a comment on an item. The substrate for Phase 10's Slack bridge ("a teammate's Slack reply syncs back as a Vibstr comment") and any future bot integration.
curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-item-comment-create \
-H "Content-Type: application/json" \
-d '{
"api_key": "YOUR_PROJECT_API_KEY",
"item_number": 297,
"body": "Reproduced on Safari 17.4 — keystroke handler re-binds the form action each render."
}'
Response:
{
"comment": { "id": 1842, "item_id": 297, "created_at": "2026-05-12T03:24:11.000Z" }
}
The author of the comment is recorded as the project owner. Future versions will accept an optional as_user_id for properly attributed bot bridges.
The full loop, walked through
A real example: derive items from spec.md via your Claude Code, file them via bulk-create, write code, commit with closes #NN, log a build that auto-closes them. End-to-end.
Step 1. Your Claude Code reads spec.md and proposes 8 items. You review them in the agent's reply. You approve.
Step 2. Agent files them in Vibstr:
curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-item-bulk-create \
-H "Content-Type: application/json" \
-d @items.json
Response gives you item_number 312-319. Agent shows you the new items in Vibstr.
Step 3. Agent (optionally) creates a plan to wrap them:
curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-plan-create \
-H "Content-Type: application/json" \
-d '{ "api_key": "...", "title": "Sprint 14", "body": "...", "derive_items": false }'
Then a follow-up update to link items to the plan (out of scope for 1.12.3; for now, the in-app Plans UI is the link surface).
Step 4. Implement. Make commits:
git commit -m "Add user-pref persistence — closes #312 #313
Wires the localStorage round-trip and the cross-tab broadcast."
Step 5. Push. Your CLAUDE.md already has the auto-ingest curl wired, so the build reports itself. The #NN parser closes items 312 and 313. No further action needed.
Step 6. Repeat steps 4-5 until the plan's progress chip hits 8 / 8 done.
The plan, the items, the commits, the closing builds, and the changelog all live in the same context. You filed zero items by hand; you closed zero items by hand; you wrote zero status comments.
CLAUDE.md snippet
Paste this into YOUR project's CLAUDE.md so your Claude Code learns the integration:
## Vibstr external automation
This project tracks work in Vibstr at `https://vibstr.app`. The project's `api_key` is in your local env as `VIBSTR_API_KEY` (or substitute directly below).
When the user asks to file items, create a plan, or check what's open:
1. **Read state first** before proposing changes. Call `vibstr-items-list` with `{ status: 'open' }` to see what already exists; don't file duplicates.
2. **File items via bulk-create** for anything >1 item:
```bash
curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-item-bulk-create \
-H "Content-Type: application/json" \
-d '{"api_key": "$VIBSTR_API_KEY", "items": [...]}'
```
3. **Vibstr Plan Prompt** (use when asked to "create a Vibstr plan for X"):
- Produce markdown with sections: Goal, Context, Tasks, Target build, Acceptance gate, Out of scope
- Tasks must be `- [ ] {type: <type>, area: <area>} <description>`
- `<type>` must be one of this project's categories (the user can tell you which)
- `<area>` must be one of this project's areas (the user can tell you which)
- Target build follows semver (e.g. `v1.13.0`)
- Acceptance-gate items are smoke tests verifiable by hand
- POST to `vibstr-plan-create` with `derive_items: true` to file the plan AND the items in one call
4. **Builds auto-report** via the curl already in CLAUDE.md after every commit + push. Commit messages should reference `closes #NN` for items the commit ships — the `#NN` parser closes them deterministically.
5. **All endpoints documented**: https://vibstr.app/how-we-ship/external-automation/
Tweak the wording to match your team's voice. The point is to teach your agent the four moves it actually has: read, file, plan, and let builds close themselves.
Path B: @vibstr/mcp-server (coming)
An out-of-band npm package. Install Vibstr as an MCP server in Claude Desktop, Cursor, Zed, or any MCP-capable client. No curl plumbing required — the seven Path A endpoints surface as MCP tools the model can call directly.
Ships in a separate repo on a separate timeline. The Path A endpoints documented here are the underlying transport; the MCP server is the friendly wrapper. Use either, or both — the api_key auth is the same.
Pricing context
We never mark up AI compute. You pay Anthropic, not us. The trial includes a $1 USD platform-AI budget (~100 typical Haiku calls) for the per-item AI sidebar; AI Assist requires a BYO Anthropic key from day 1. After the 14-day trial, all AI features require a BYO key regardless of tier (the Pro $2.99/seat tier covers workflow features — unlimited active projects + team members + Slack + Path A — not AI compute). For external automation — where your agent is calling the API on its own clock — set your Anthropic key under Settings → Account → AI provider. From then on, every AI-charging endpoint uses your key directly, bypasses the trial cap, and bills Anthropic, not Vibstr.
This is the boundary by design: pay us for the workflow; pay Anthropic for the compute. The best practices page has the full reasoning, including why the labels-as-stages position keeps the surface small enough to stay programmable.
The seven endpoints above are the surface. Everything else is composition.