BioFlow / Developers / API docs
A REST API for the page your users keep in their bio: read and edit pages, add blocks, publish, capture contacts, pull analytics, and manage webhooks — all at https://app.getbioflow.com/v1, described by an OpenAPI 3.1 spec, available on Creator and Pro.
Create a key in the developer console — pick its scopes when you create it. bf_live_ keys are production keys; bf_test_ keys are read-only.
Paste-runnable — swap in your key:
curl "https://app.getbioflow.com/v1/pages" \
-H "Authorization: Bearer bf_live_YOUR_KEY"A cursor page of your bio pages — every list endpoint uses the same { data, has_more, next_cursor } envelope:
{
"data": [
{
"id": "pg_abc123",
"title": "My links",
"slug": "maya",
"status": "PUBLISHED",
"block_count": 6,
"public_url": "https://getbioflow.com/maya",
"updated_at": "2026-07-20T12:00:00.000Z"
}
],
"has_more": false,
"next_cursor": null
}Both forms are equivalent — send exactly one per request:
Authorization: Bearer bf_live_YOUR_KEY
x-api-key: bf_live_YOUR_KEYbf_live_ keys can do everything their scopes allow. bf_test_ keys are restricted to read operations — a write with a test key returns 403 test_key_read_only, so test integrations can never touch live data.
| Plan | Monthly quota | Per-key burst |
|---|---|---|
| Free | — (no API access) | — |
| Creator | 10,000 requests/mo | 60 requests/min |
| Pro | 100,000 requests/mo | 120 requests/min |
The quota counts successful /v1 requests per calendar month (UTC); GET /v1/usage is free and shows where you stand. Every response carries IETF draft-11 RateLimit / RateLimit-Policy headers. Bursting past the per-minute limit returns 429 rate_limited; an exhausted month returns 429 quota_exhausted; Free-plan keys get 403 feature_not_enabled. Full plan pricing on /pricing.
List endpoints return { data, has_more, next_cursor }. Pass limit for page size and feed next_cursor back as after until has_more is false. Cursors are opaque — never parse them.
Consequential POSTs (create page, add block, publish, webhook management) accept an Idempotency-Key header — any unique string per logical attempt. Retrying with the same key returns the original result instead of repeating the action; reusing a key with a different body returns 422 idempotency_key_reused.
Every error is application/problem+json with a stable code your integration can branch on (never parse title or detail), a type URI that resolves to the pages below, and a request_id to quote at support.
| Code | Status | Meaning |
|---|---|---|
invalid_request | 400 | The request body or parameters failed validation |
invalid_api_key | 401 | Missing, malformed, unknown, disabled, or expired API key |
insufficient_scope | 403 | The API key was not granted the required scope |
feature_not_enabled | 403 | The workspace plan does not include public API access |
test_key_read_only | 403 | Test-mode keys are restricted to read operations |
resource_not_found | 404 | No resource with that ID exists in this workspace |
stale_snapshot | 409 | The draft changed since it was last read |
idempotency_in_progress | 409 | A request with this Idempotency-Key is still executing |
idempotency_key_reused | 422 | This Idempotency-Key was already used with a different request |
endpoint_verification_failed | 422 | The webhook endpoint did not accept the signed test event |
endpoint_limit_reached | 422 | The workspace webhook endpoint limit was reached |
rate_limited | 429 | Per-key rate limit exceeded |
quota_exhausted | 429 | Monthly API quota exhausted |
internal_error | 500 | Something went wrong on our side |
| Operation | Endpoint | Scope |
|---|---|---|
| Get analytics summary | GET /v1/analytics/summary | analytics:read |
| List contacts | GET /v1/contacts | contacts:read |
| List files | GET /v1/files | files:read |
| List pages | GET /v1/pages | pages:read |
| Create a page | POST /v1/pages | pages:write |
| Delete a page | DELETE /v1/pages/{page_id} | pages:write |
| Get a page | GET /v1/pages/{page_id} | pages:read |
| Update a page draft | PATCH /v1/pages/{page_id} | pages:write |
| Add a block | POST /v1/pages/{page_id}/blocks | pages:write |
| Remove a block | DELETE /v1/pages/{page_id}/blocks/{block_id} | pages:write |
| Publish a page | POST /v1/pages/{page_id}/publish | publish |
| Get API usage | GET /v1/usage | pages:read, pages:write, analytics:read, contacts:read, files:read, publish |
| List webhook endpoints | GET /v1/webhook-endpoints | webhooks:read |
| Create a webhook endpoint | POST /v1/webhook-endpoints | webhooks:write |
| Delete a webhook endpoint | DELETE /v1/webhook-endpoints/{endpoint_id} | webhooks:write |
| Get a webhook endpoint | GET /v1/webhook-endpoints/{endpoint_id} | webhooks:read |
| Update a webhook endpoint | PATCH /v1/webhook-endpoints/{endpoint_id} | webhooks:write |
| List deliveries | GET /v1/webhook-endpoints/{endpoint_id}/deliveries | webhooks:read |
| Resend a delivery | POST /v1/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/resend | webhooks:write |
| Replay failed deliveries | POST /v1/webhook-endpoints/{endpoint_id}/replay | webhooks:write |
| Rotate the signing secret | POST /v1/webhook-endpoints/{endpoint_id}/rotate-secret | webhooks:write |
| Send a test event | POST /v1/webhook-endpoints/{endpoint_id}/test | webhooks:write |
Browse every operation, schema, and example — rendered straight from the OpenAPI 3.1 spec.
Open the reference →Standard Webhooks v1 signing, four event types, retries with replay, and verification snippets.
Read the guide →Dated, factual platform updates — one URL per entry, RSS feed included.
See what shipped →Open source on GitHub: spec-generated types, typed errors, safe retries, pagination, webhook verification. npm package landing shortly.
View the source ↗Let Claude, ChatGPT, or any MCP client operate your workspace — 12 tools behind OAuth 2.1 with safety rails.
Connect an agent →llms.txt, llms-full.txt, markdown twins of every docs page, and the spec download — built for assistants.
Point your agent here →Machine-readable spec: /docs/api/openapi.json · this page as markdown: /docs/api.md
Create a key in the developer console and make your first call in under a minute — the API is included on Creator and Pro.