Creator API
The Creator API lets you sell access to your Blenau content without Blenau touching your money. You charge in your own system — Stripe, Gumroad, Whop, Lemon Squeezy, a membership site, anything — and call these endpoints from your backend to grant or revoke access when a payment succeeds, renews or lapses. We call this bring-your-own-billing (BYO-billing).
Everything the Creator API does is scoped to your one workspace — it can never touch other workspaces, your repos, your billing, or admin settings.
Two ways to grant access
Section titled “Two ways to grant access”There are two distinct primitives. Choose deliberately — they have different security properties.
| Members (recommended for selling) | Readers (free sharing) | |
|---|---|---|
| Endpoint | POST /v1/members | POST /v1/readers |
| How the person gets in | Signs in as themselves (their own identity) | Opens a magic link |
| Forwardable? | No — access is identity-bound | Yes — anyone with the link can view |
| Best for | Paid access you don’t want reshared | Free/public shares, previews |
| Capability | manage_members | manage_readers |
Sell with /v1/members. A magic link is a bearer token: whoever holds it can
read, so one purchase forwarded to a group leaks your paid content. A member
instead authenticates as themselves, so access can’t be passed around — revoke
them and it’s gone everywhere.
Share freely with /v1/readers. Magic links are perfect for free previews or
public docs. Blenau warns you whenever a link is minted (it’s forwardable by
design); it never blocks you — the choice is yours.
Authentication
Section titled “Authentication”Every request is authenticated with a workspace API key:
blenau_ak_xxxxxxxxxxxxxxxxxxxxxxxxPass it as a Bearer token (recommended) or an X-API-Key header:
Authorization: Bearer blenau_ak_xxxxxxxxxxxxxxxxxxxxxxxx# orX-API-Key: blenau_ak_xxxxxxxxxxxxxxxxxxxxxxxxAn invalid, unknown or revoked key returns 401. A valid key that lacks the
required capability returns 403.
Capabilities
Section titled “Capabilities”A key carries a set of capabilities. Grant a key only what it needs (least privilege):
| Capability | Lets the key… |
|---|---|
manage_members | create / list / revoke identity-bound members |
manage_permissions | manage groups and assign per-group access to members |
manage_readers | create / list / revoke magic-link readers (legacy) |
A key can hold one capability or several. When you create a key you may pass a
single capability or a capabilities array; the response returns both
(capability is the primary, kept for backwards compatibility).
Managing API keys
Section titled “Managing API keys”Create and manage keys from the Blenau dashboard → Settings → API Keys (admin only).
| Action | What happens |
|---|---|
| Create | Mints a new key with the capabilities you choose. The full secret is shown once — copy it now. |
| Rotate | Issues a new secret; the old one stops working immediately. Name and capabilities are preserved. |
| Revoke | Permanently disables the key. Any call using it returns 401. |
Base URL
Section titled “Base URL”https://api.blenau.comThe access model
Section titled “The access model”What a person can read is defined by groups. A group is a named bundle of
document paths (glob patterns like course/premium/**). Assign a member to a
group and they can read exactly those paths — not one document more.
- Groups are reusable. Sell the same bundle to many members; add a module to the bundle and every member sees it instantly.
- Access level per assignment. Each assignment carries an access level —
read_onlyorread_write. A member’s role isreader, and a reader is always effectively read-only regardless of the level stored: the level only takes effect for workspace editors. For selling read access, leave itread_only. - A group can never be
**/ match-all — a sold bundle must scope to a subtree.
Members — identity-bound access
Section titled “Members — identity-bound access”Require a key with manage_members.
Grant a member — POST /v1/members
Section titled “Grant a member — POST /v1/members”Grants an identity-bound customer access. They receive a login invite (not a magic link) and sign in as themselves. On first sign-in their identity is linked to this grant automatically.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
email | string | yes | The customer’s email. |
name | string | no | Display name. Defaults to the email. |
groups | string[] | no | Group IDs to grant. |
access | string | no | read_only (default) or read_write — the level for those groups. |
send_email | boolean | no | Whether Blenau emails the login invite. Defaults to true. |
Example
curl -X POST https://api.blenau.com/v1/members \ -H "Authorization: Bearer blenau_ak_xxxx" \ -H "Content-Type: application/json" \ -d '{"email":"buyer@example.com","name":"Jane","groups":["<group-id>"]}'Response 200 — note there is no magic link (that’s the point):
{ "id": "5f0e...", "email": "buyer@example.com", "name": "Jane", "status": "active", "pending": true, "identity_bound": true, "groups": ["<group-id>"], "access": "read_only", "email_sent": true}pending: true means they haven’t completed their first sign-in yet.
Errors: 409 email already exists · 402 reader seat cap reached (upgrade) ·
402 billing inactive · 401/403 key invalid or missing manage_members.
Call this from your payment-success webhook so a buyer gets access the moment they pay.
List members — GET /v1/members
Section titled “List members — GET /v1/members”Lists your identity-bound members so your backend can reconcile against billing.
{ "members": [ { "id": "5f0e...", "email": "buyer@example.com", "name": "Jane", "status": "active", "pending": false, "identity_bound": true } ], "count": 1 }Revoke a member — DELETE /v1/members/{identifier}
Section titled “Revoke a member — DELETE /v1/members/{identifier}”{identifier} is the member’s UUID or email. Sets status to revoked, frees the
seat, and cuts access live across the dashboard, assets and search. Reversible
by re-granting; idempotent. 404 if not found.
Call this from your cancellation / payment-failed webhook.
Permissions — per-group access
Section titled “Permissions — per-group access”Require a key with manage_permissions.
Get a member’s access — GET /v1/members/{identifier}/access
Section titled “Get a member’s access — GET /v1/members/{identifier}/access”{ "id": "5f0e...", "email": "buyer@example.com", "access": [ { "group_id": "...", "name": "Premium", "paths": ["course/premium/**"], "access": "read_only" } ] }Set a member’s access — PUT /v1/members/{identifier}/access
Section titled “Set a member’s access — PUT /v1/members/{identifier}/access”Replaces the member’s group assignments. Every group must belong to your workspace.
curl -X PUT https://api.blenau.com/v1/members/buyer@example.com/access \ -H "Authorization: Bearer blenau_ak_xxxx" -H "Content-Type: application/json" \ -d '{"assignments":[{"group_id":"<id>","access":"read_only"}]}'Errors: 400 invalid access level · 404 member or group not found (a group
from another workspace is invisible → 404) · 401/403.
Groups — content bundles
Section titled “Groups — content bundles”Require a key with manage_permissions. Manage the bundles you sell entirely
from your backend.
| Method | Endpoint | Purpose |
|---|---|---|
GET | /v1/groups | List bundles. |
POST | /v1/groups | Create a bundle ({ "name", "paths", "description?" }). |
PUT | /v1/groups/{id} | Update name / paths / description — re-scopes every holder instantly. |
DELETE | /v1/groups/{id} | Delete a bundle (un-assigns everyone who held it — prefer PUT to re-scope). |
paths are glob patterns; a match-all pattern (*, **, **/*, …) is rejected
with 400 — a bundle must scope to a subtree.
Readers — magic-link sharing (legacy)
Section titled “Readers — magic-link sharing (legacy)”Require a key with manage_readers. Use this for free shares. Every response
that mints a link includes a warning field reminding you the link is
forwardable.
POST /v1/readers · DELETE /v1/readers/{identifier} · GET /v1/readers
Section titled “POST /v1/readers · DELETE /v1/readers/{identifier} · GET /v1/readers”Same shapes as before. POST /v1/readers returns a magic_link and a
warning:
{ "id": "5f0e...", "email": "fan@example.com", "status": "active", "groups": [], "magic_link": "https://blenau.com/r?token=...", "warning": "Anyone with this link can view the shared content without signing in — …", "email_sent": true }Rate limits
Section titled “Rate limits”Every endpoint is rate-limited per API key. Exceeding a limit returns
429.
| Endpoint group | Limit |
|---|---|
grant (POST /v1/members, POST /v1/readers), writes (PUT/POST/DELETE groups & access) | 30 / minute |
| list / get / revoke | 60 / minute |
If you’re bulk-syncing a large list, spread calls out or back off on 429.
Your customers grow Blenau too
Section titled “Your customers grow Blenau too”A member you invite is a real Blenau identity. Inside their dashboard they’re offered — subtly, never forced — the option to spin up their own free Blenau workspace. It doesn’t affect their access to your content; it just means the people you bring in can become creators themselves.
A typical integration
Section titled “A typical integration”- Create a key in Settings → API Keys with
manage_members(+manage_permissionsif you define bundles by API). Store the secret. - Define your bundles once with
POST /v1/groups(or in the dashboard). - On payment success,
POST /v1/memberswith the buyer’s email + group IDs. - On cancellation / failed renewal,
DELETE /v1/members/{email}. - Periodically
GET /v1/membersto reconcile against your billing records. - Rotate the key on a schedule; revoke immediately if it leaks.
Because you keep billing in your own system, there’s nothing to migrate and no revenue share — Blenau just enforces who can read your content.