BroomVA

API Overview

Base URL, authentication, rate limits, error format, and versioning for the BroomVA API.

API Overview

The BroomVA API provides programmatic access to the platform's chat, organization management, billing, and agent services. All endpoints are served from the primary application at broomva.tech.

Base URL

https://broomva.tech/api

All API paths in this documentation are relative to this base URL. For example, the chat endpoint is POST /api/chat.

For local development, the chat application runs on port 3001:

http://localhost:3001/api

Authentication

The API uses Bearer token authentication. Include your token in the Authorization header of every request:

curl -H "Authorization: Bearer $TOKEN" https://broomva.tech/api/...

Obtaining a token

There are three ways to get an API token:

  1. Device-code flow (RFC 8628) -- use broomva auth login from the CLI. The flow issues POST /api/auth/device/code to get a user code, then polls POST /api/auth/device/token until the user approves. The token is stored in ~/.broomva/config.json and can be printed with broomva auth token. See CLI Authentication for the full protocol.

  2. API token endpoint -- sign in to broomva.tech and visit /api/auth/api-token to generate a long-lived token. This is the simplest method for scripts.

  3. Organization API keys -- create organization-scoped API keys from the console. These do not expire unless explicitly revoked. They provide admin-level access scoped to the creating organization.

Token format

Tokens are JWTs signed by the platform's auth system (Better Auth) using signLifeJWT(). They encode:

  • User ID -- the authenticated user
  • Email -- for identity resolution
  • Organization memberships -- resolved at auth time
  • Token expiration -- configurable, default matches JWT_ACCESS_EXPIRY_MS
  • Scopes -- for API keys, the permitted operations

Refresh tokens

When using the device-code flow, the server may return a refresh_token alongside the access_token. Use the refresh token to obtain a new access token without re-authenticating:

curl -X POST https://broomva.tech/api/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{"refresh_token": "eyJ..."}'

Authentication errors

StatusErrorDescription
401unauthorizedMissing or invalid token
403forbiddenValid token but insufficient permissions (RBAC check failed)

The RBAC system uses a 4-tier role hierarchy (owner > admin > member > viewer). When a 403 is returned, it means the user's role in the target organization does not meet the minimum required role for the operation. See Organizations for the full permission matrix.

Rate limits

Rate limits are applied per-organization (or per-user for personal workspaces):

PlanRequests/minuteRequests/day
Free10100
Pro605,000
Team12020,000
EnterpriseCustomCustom

When rate-limited, the API returns a 429 Too Many Requests response with the following headers:

Retry-After: 30
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1711234567

The device-code endpoints have separate rate limits: 10 requests/minute per IP for code generation, and 5 requests/minute per device code + IP for token polling.

Error format

All errors follow a consistent JSON structure:

{
  "error": {
    "code": "validation_error",
    "message": "The 'model' field is required.",
    "details": {
      "field": "model",
      "constraint": "required"
    }
  }
}

Standard error codes

CodeHTTP StatusDescription
unauthorized401Authentication required
forbidden403Insufficient permissions
not_found404Resource does not exist
conflict409Resource already exists (e.g., duplicate slug)
validation_error422Request body validation failed
rate_limited429Too many requests
credits_exhausted402Credit limit reached
internal_error500Unexpected server error

The credits_exhausted error (HTTP 402) is returned when the organization's credit balance is insufficient for the requested operation and the plan's overage policy blocks the request. See Billing for overage policy details per plan.

Content type

All request bodies must be JSON with Content-Type: application/json. Responses are JSON unless the endpoint specifies streaming (in which case text/event-stream is used).

Streaming

Chat endpoints support Server-Sent Events (SSE) for streaming responses. Set the Accept header to text/event-stream or include "stream": true in the request body:

curl -N -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  https://broomva.tech/api/chat \
  -d '{"model": "claude-sonnet-4-20250514", "messages": [{"role": "user", "content": "Hello"}]}'

The SSE stream uses the Vercel AI SDK v6 data stream format, compatible with the ai package's useChat and streamText functions.

Stream event types

The stream emits UiPart objects:

Event typeDescription
text-deltaIncremental text token from the model
tool-callTool invocation request (name, arguments)
tool-resultTool execution result
finishCompletion signal with usage data and finish reason
errorError during generation

Versioning

The API is currently unversioned -- all endpoints are served at /api/. When breaking changes are introduced, the API will adopt path-based versioning (/api/v2/) with a deprecation period for the previous version.

On this page