Skip to content

Authentication ​

OpenBrain SaaS uses Laravel Sanctum personal access tokens for the REST API and MCP (/mcp).

Token abilities ​

AbilityRESTMCP tools
memory:ingestPOST /api/memories, PUT /api/memories, POST /api/memories/batchmemory_ingest, memory_upsert, memory_ingest_batch
memory:searchPOST /api/memories/search, GET /api/memories/{id}memory_search, memory_get, memory_recent, memory_stats, memory_changes
memory:adminPATCH /api/memories/{id}, DELETE /api/memories/{id}memory_update, memory_delete
organization:{uuid}Binds the token to one tenantSame

The wildcard ability * grants all scopes (intended for local development only).

Organization context ​

  • Prefer embedding the org in the token: organization:{uuid}.
  • Optionally send X-Organization-Id — REST and MCP both honor it. The header must match the token’s organization: ability when both are present. Unknown and unauthorized organizations return the same 403.
  • A user principal must have a live membership in the resolved organization, even when the token is org-scoped. Tokens without an organization: ability resolve only when the user belongs to exactly one organization.
  • Search-only tokens cannot call memory_upsert or memory_ingest_batch. Those tools require memory:ingest.

Creating tokens ​

php
$user->createToken('agent-ingest', [
    'organization:'.$organizationId,
    'memory:ingest',
    'memory:search',
]);

Issue separate tokens for search-only automation vs ingest-heavy agents vs admin (update/delete) workflows.

Organization roles (OBS-106) ​

RoleDashboard (/app)API keysBilling
ownerFull tenant accessCreate tokens with any abilitiesYes
memberMemories + API keysCreate tokens (ability checkboxes)No
readonlyView/search UICreate search-only tokensNo

Owners invite teammates from the Team page. Invitees receive a one-time email link to /invitations/accept/{token} (email must match; the link expires). Owners can view and revoke every API key scoped to the current organization; other members see and can revoke only their own.

Audit log (OB-047) ​

Successful ingest, upsert, update, delete, and batch operations write org-scoped rows to memory_audit_events (actor user/token, action, thought id, metadata such as outcome/dedupe — never raw content). Owners can review events in the dashboard Audit log.

REST requests ​

http
Authorization: Bearer {token}
X-Organization-Id: {uuid}   # optional when token includes organization:{uuid}
Content-Type: application/json

MCP ​

  • Production: Sanctum Bearer token required on every /mcp request. MCP OAuth is unsupported.
  • Organization header: MCP reads X-Organization-Id from the HTTP request. Resource URIs also select an organization; a header and URI that disagree are denied.
  • Local: Unauthenticated MCP is allowed only when APP_ENV=local and OPENBRAIN_DEFAULT_ORGANIZATION_ID is set. Resource URIs (brain://{organizationId}/…) may only use that configured organization ID; other organization IDs are denied.

Billing on writes ​

When OPENBRAIN_BILLING_ENFORCED=true and Stripe is configured, writes (ingest, upsert, batch, update, delete) require an active subscription or trial and return 402 with code: "entitlement_required" (MCP: tool error) when unpaid. Reads (search, get, recent, export, stats, changes, MCP read tools and resources) stay available. Metered reads (search, export, stats, changes, recent) still count toward the search quota; get does not.

If enforcement is on but STRIPE_SECRET is empty, writes fail closed with 503 and code: "service_unavailable" rather than being allowed. Metered operations also return 503 when the organization's subscription price is not one this deployment recognizes, because no plan quota can be applied. See Billing and usage for per-plan caps.

Rate limits ​

Memory operations are limited per resolved organization + credential (Sanctum PAT ID, authenticated session user, or system principal), with a 60-second decay. Limits apply consistently to REST, MCP, dashboard, and webhook operations:

VariableDefaultApplies to
OPENBRAIN_RATE_LIMIT_INGEST60ingest, upsert, batch
OPENBRAIN_RATE_LIMIT_SEARCH120search, export, stats, changes, recent, get
OPENBRAIN_RATE_LIMIT_ADMIN30update, delete

Exceeded limits return HTTP 429 with code: "rate_limited" and Retry-After.