Organizations and websites
The organization is the tenant root. It owns members (each with a role), websites, and an entitlement plan. Every operational and knowledge row scopes back to one organization, directly or through one of its websites.
The hierarchy
organization
├── members (user + role: viewer / editor / organization_admin / organization_owner)
├── entitlements (plan: free / advanced)
└── websites
├── verification (ownership proof + trust tier)
├── connectors (ingestion tokens)
└── knowledge (the graph -> published node)Registering a user creates an organization in the same call; the registrant becomes its organization_owner. A user can also create additional organizations, becoming the owner of each.
Roles and permissions
Roles form an ordered ladder. A higher role includes every permission of the roles below it. Roles are per organization (admin and super_admin are platform-wide).
| Permission | viewer | editor | organization_admin | organization_owner |
|---|---|---|---|---|
| Read organization, websites, knowledge, entitlements | yes | yes | yes | yes |
| Edit a website, request verification, trigger publish | yes | yes | yes | |
| Create a website | yes | yes | ||
| Manage members (add, change role, remove) | yes | yes | ||
| Issue and rotate connector tokens | yes | yes | ||
| Edit organization settings | yes | yes | ||
| Delete the organization | yes | |||
| Run GDPR erasure of the organization | yes |
The minimum role for each route is enforced in the service layer, which derives the caller's effective role from org_membership. See Authentication for the full ladder including the platform roles.
Organization endpoints
apps/api/src/modules/organization/router.ts. Every route requires a user; the service enforces per-org RBAC and tenant scope.
| Method | Path | Min role |
|---|---|---|
| GET | /v1/organizations | viewer (member) |
| POST | /v1/organizations | any user (caller becomes owner) |
| GET | /v1/organizations/:id | member |
| PATCH | /v1/organizations/:id | organization_admin |
| DELETE | /v1/organizations/:id | organization_owner |
| GET | /v1/organizations/:id/members | member |
| POST | /v1/organizations/:id/members | organization_admin |
| PATCH | /v1/organizations/:id/members/:userId | organization_admin |
| DELETE | /v1/organizations/:id/members/:userId | organization_admin |
| POST | /v1/organizations/:id/erase | organization_owner |
POST /v1/organizations/:id/erase is GDPR Article 17 hard-erasure. It requires a typed confirmation matching the organization slug or name and returns 202.
Errors: validation.failed, auth.tenant_mismatch, auth.forbidden, privacy.erasure_forbidden, privacy.subject_not_found, privacy.erasure_in_progress, internal.error.
# Create an organization (caller becomes owner)
curl -sS -X POST https://api.bainquet.online/v1/organizations \
-H "Authorization: Bearer $ACCESS_JWT" \
-H 'Content-Type: application/json' \
-d '{ "name": "Acme" }'
# Add a member as editor
curl -sS -X POST https://api.bainquet.online/v1/organizations/$ORG_ID/members \
-H "Authorization: Bearer $ACCESS_JWT" \
-H 'Content-Type: application/json' \
-d '{ "email": "teammate@acme.com", "role": "editor" }'Website endpoints
apps/api/src/modules/website/router.ts. Websites are created under an organization.
| Method | Path | Min role |
|---|---|---|
| GET | /v1/organizations/:orgId/websites | viewer |
| POST | /v1/organizations/:orgId/websites | organization_admin |
| GET | /v1/websites/:id | viewer |
| PATCH | /v1/websites/:id | editor |
| DELETE | /v1/websites/:id | organization_admin |
Errors: validation.failed, auth.tenant_mismatch, auth.forbidden, website.not_found.
# List websites in an organization
curl -sS https://api.bainquet.online/v1/organizations/$ORG_ID/websites \
-H "Authorization: Bearer $ACCESS_JWT"
# Create a website
curl -sS -X POST https://api.bainquet.online/v1/organizations/$ORG_ID/websites \
-H "Authorization: Bearer $ACCESS_JWT" \
-H 'Content-Type: application/json' \
-d '{ "domain": "example.com", "name": "Example" }'After creating a website, verify its ownership (Verifying ownership) before issuing a connector token and publishing.
Tenant isolation
Cross-tenant access is blocked: a read of another organization's resource returns 404 (so existence is not leaked), and a mutation returns 403. Every knowledge query is WHERE website_id = $1.
Entitlements and usage
Plan capabilities and usage are read-only endpoints under billing.
| Method | Path | Min role |
|---|---|---|
| GET | /v1/organizations/:id/entitlements | org member (scoped) |
| GET | /v1/organizations/:id/usage | org member (scoped) |
These return plan-derived constants and usage counters. See Free vs AI-enhanced for what each plan includes.
API keys, transfer, and webhooks
These management surfaces are available (organization_admin+, except transfer which is owner-gated):
- API keys:
POST/GET/v1/organizations/:id/api-keys,DELETE /v1/organizations/:id/api-keys/:keyId. Thebnq_live_*secret is shown once. - Organization transfer:
POST /v1/organizations/:id/transfer(owner initiates to a target email),POST /v1/organizations/transfers/:token/accept(recipient accepts),POST /v1/organizations/:id/transfer/cancel. - Website transfer:
POST /v1/websites/:id/transfermoves a website to another org the caller owns. - Webhooks:
POST/GET/v1/websites/:id/webhooks,PATCH/DELETE/v1/websites/:id/webhooks/:webhookId. The signing secret is shown once.
Related
- Authentication: the role ladder.
- Verifying ownership: the next step after creating a website.
- Connector tokens: issuing ingestion tokens.