← back to Ventura Claw
API.md
1110 lines
# VenturaClaw API Reference
Production endpoint: `https://venturaclaw.com`
---
## Authentication & Sessions
VenturaClaw uses HMAC-signed cookies for session management. All protected endpoints require a valid `cc_session` cookie.
### POST /api/auth/login
**Public** — Create a user session
**Request:**
```json
{
"email": "admin@venturaclaw.com",
"password": "admin"
}
```
**Response (200 OK):**
```json
{
"ok": true,
"role": "admin",
"name": "Admin"
}
```
**Response (401 Unauthorized):**
```json
{
"error": "invalid"
}
```
**Side effects:**
- Sets `cc_session` cookie (7 days, httpOnly, sameSite=lax)
- Logs failed login attempts to audit trail
**curl:**
```bash
curl -X POST https://venturaclaw.com/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@venturaclaw.com","password":"admin"}' \
-c cookies.txt
```
---
### POST /api/auth/logout
**Session required** — Destroy the current session
**Request:** (empty body)
**Response (200 OK):**
```json
{
"ok": true
}
```
**Side effects:**
- Clears `cc_session` cookie
**curl:**
```bash
curl -X POST https://venturaclaw.com/api/auth/logout \
-b cookies.txt
```
---
### GET /api/me
**Session required** — Get current user identity
**Response (200 OK):**
```json
{
"user": {
"sub": 1,
"email": "admin@venturaclaw.com",
"role": "admin",
"name": "Admin",
"iat": 1714982400000
}
}
```
---
## Connectors
VenturaClaw connectors are pre-built integrations (Stripe, Cloudflare, Shopify, 56+ total). Users authenticate connectors individually by storing credentials.
### GET /api/connectors
**Session required** — List all available connectors with configuration status
**Query params:** (none)
**Response (200 OK):**
```json
{
"connectors": [
{
"id": "stripe",
"name": "Stripe",
"category": "payments",
"description": "Process payments, issue refunds, manage customers",
"icon": "stripe",
"real_impl": true,
"configured": true,
"sensitive": true,
"website": "https://stripe.com"
},
{
"id": "slack",
"name": "Slack",
"category": "communication",
"description": "Send messages to Slack channels",
"icon": "slack",
"real_impl": true,
"configured": false,
"sensitive": false
}
],
"support_email": "info@agentabrams.com"
}
```
**Fields:**
- `real_impl`: true if a handler exists in `/connectors/` directory
- `configured`: true if current user has stored credentials for this connector
- `sensitive`: actions queued for approval unless connector is trusted
**curl:**
```bash
curl https://venturaclaw.com/api/connectors \
-b cookies.txt \
-H "Accept: application/json"
```
---
### GET /api/connectors/:id/health
**Session required** — Probe a connector's live status
**Path params:**
- `id` (string): connector ID (e.g. `stripe`, `slack`)
**Response (200 OK):**
```json
{
"status": "ok",
"connector": "stripe",
"checked_at": "2026-05-05T18:42:30Z",
"message": "API responding"
}
```
**Response (500 error):**
```json
{
"status": "error",
"connector": "stripe",
"message": "Stripe API key invalid or missing"
}
```
**Side effects:**
- Makes test call to vendor API using stored credentials
- Does NOT write or modify any data
**curl:**
```bash
curl https://venturaclaw.com/api/connectors/stripe/health \
-b cookies.txt
```
---
## User Connections (Credentials)
Users save API keys, OAuth tokens, and other credentials for connectors. All stored credentials are masked on retrieval (first 4 + last 4 chars only).
### GET /api/me/connections
**Session required** — List all connectors + field schemas + which are filled by current user
**Response (200 OK):**
```json
{
"connections": [
{
"id": "stripe",
"name": "Stripe",
"category": "payments",
"docsUrl": "https://docs.stripe.com",
"fields": [
{
"key": "api_key",
"label": "Secret Key",
"type": "password",
"required": true
},
{
"key": "publishable_key",
"label": "Publishable Key",
"type": "text",
"required": false
}
],
"filled": true,
"filled_fields": {
"api_key": "sk_l…nqx2",
"publishable_key": "pk_l…txy8"
}
},
{
"id": "cloudflare",
"name": "Cloudflare",
"category": "infrastructure",
"filled": false,
"filled_fields": null
}
]
}
```
**curl:**
```bash
curl https://venturaclaw.com/api/me/connections \
-b cookies.txt
```
---
### POST /api/me/connections/:id
**Session required** — Save or update credentials for a connector
**Path params:**
- `id` (string): connector ID
**Request body:**
```json
{
"api_key": "sk_live_...",
"publishable_key": "pk_live_..."
}
```
Fields accepted are defined by the connector's schema in GET /api/me/connections. Extra fields are silently ignored.
**Response (200 OK):**
```json
{
"ok": true
}
```
**Response (400 Bad Request):**
```json
{
"error": "no recognized fields"
}
```
**Response (404 Not Found):**
```json
{
"error": "no real impl for this connector yet"
}
```
**Side effects:**
- Persists credentials to `data/credentials.json`
- Logs event to audit trail with field names (not values)
**curl:**
```bash
curl -X POST https://venturaclaw.com/api/me/connections/stripe \
-b cookies.txt \
-H "Content-Type: application/json" \
-d '{"api_key":"sk_live_...","publishable_key":"pk_live_..."}'
```
---
### DELETE /api/me/connections/:id
**Session required** — Remove credentials for a connector
**Response (200 OK):**
```json
{
"ok": true
}
```
**Side effects:**
- Deletes credentials from `data/credentials.json`
- Logs removal to audit trail
**curl:**
```bash
curl -X DELETE https://venturaclaw.com/api/me/connections/stripe \
-b cookies.txt
```
---
### POST /api/me/connections/import
**Session required** — Bulk import credentials from pasted text or JSON
Supports three formats:
1. **env** — KEY=VALUE lines (e.g., from `~/.env` or secrets-manager `.env`)
2. **claude-json** — Pasted `~/.claude.json` (extracts mcpServers env blocks)
3. **json** — Raw JSON object with env vars
Recognizes 45+ standard environment variables (STRIPE_SECRET_KEY, CLOUDFLARE_API_TOKEN, etc.) and maps them to connector IDs and field names.
**Request:**
```json
{
"content": "STRIPE_SECRET_KEY=sk_live_...\nCLOUDFLARE_API_TOKEN=v1.abc...",
"format": "auto"
}
```
**Response (200 OK):**
```json
{
"ok": true,
"format": "env",
"envKeysSeen": 5,
"serverCount": 0,
"populated": [
{
"connector": "stripe",
"fields": ["api_key"]
},
{
"connector": "cloudflare",
"fields": ["api_key"]
}
],
"unmatched": ["UNKNOWN_VAR"]
}
```
**Recognized env vars:**
- Stripe: `STRIPE_SECRET_KEY`, `STRIPE_PUBLISHABLE_KEY`, `STRIPE_API_KEY`
- Cloudflare: `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_TOKEN`
- Shopify: `SHOPIFY_ACCESS_TOKEN`, `SHOPIFY_TOKEN`, `SHOPIFY_STORE`
- Slack: `SLACK_BOT_TOKEN`, `SLACK_TOKEN`
- [+40 more — see ENV_KEY_TO_CONNECTOR in server.js]
**Side effects:**
- Merges recognized credentials into user's namespace
- Adds `_imported_at` and `_import_source` metadata
- Logs import event with connector count and format
**curl:**
```bash
curl -X POST https://venturaclaw.com/api/me/connections/import \
-b cookies.txt \
-H "Content-Type: application/json" \
-d @- << 'EOF'
{
"content": "STRIPE_SECRET_KEY=sk_live_...\nCLOUDFLARE_API_TOKEN=...",
"format": "auto"
}
EOF
```
---
## OAuth Configuration (Admin)
VenturaClaw supports 10 OAuth providers (Google, Slack, Stripe Connect, Notion, HubSpot, Mailchimp, Discord, and 3 more). An admin registers each vendor's OAuth app once. Users then click "Connect Vendor" to grant permissions.
### GET /api/admin/oauth/providers
**Admin required** — List OAuth providers + setup status + redirect URIs
**Response (200 OK):**
```json
{
"providers": [
{
"id": "google",
"name": "Google (Sheets / Drive / Gmail)",
"icon": "google",
"tint": "#4285F4",
"auth_url": "https://accounts.google.com/o/oauth2/v2/auth",
"token_url": "https://oauth2.googleapis.com/token",
"scope": "https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/gmail.send",
"register_url": "https://console.cloud.google.com/apis/credentials/oauthclient",
"docs_url": "https://developers.google.com/identity/protocols/oauth2/web-server",
"note": "Create OAuth 2.0 Client ID · Application type: Web · Authorized redirect URI: paste below.",
"redirect_uri": "https://venturaclaw.com/oauth/google/callback",
"has_credentials": true,
"registered_at": "2026-05-04T10:30:00Z"
},
{
"id": "slack",
"name": "Slack",
"has_credentials": false,
"registered_at": null
}
],
"redirect_uri_pattern": "https://venturaclaw.com/oauth/<vendor>/callback"
}
```
---
### POST /api/admin/oauth/:vendor/credentials
**Admin required** — Register OAuth app credentials for a vendor
After admin registers an OAuth app with a vendor (Google, Slack, etc.), paste the client_id and client_secret here.
**Path params:**
- `vendor` (string): `google`, `slack`, `stripe`, `notion`, `hubspot`, `mailchimp`, `discord`
**Request:**
```json
{
"client_id": "123456789.apps.googleusercontent.com",
"client_secret": "GOCSPX-abc..."
}
```
**Response (200 OK):**
```json
{
"ok": true,
"vendor": "google"
}
```
**Response (404 Not Found):**
```json
{
"error": "unknown vendor"
}
```
**Side effects:**
- Persists credentials to `data/oauth-apps.json`
- Records timestamp and admin email
- Logs to audit trail
---
### DELETE /api/admin/oauth/:vendor/credentials
**Admin required** — Remove OAuth app credentials for a vendor
**Response (200 OK):**
```json
{
"ok": true
}
```
**Side effects:**
- Deletes vendor entry from `data/oauth-apps.json`
- Logs removal to audit trail
- Does NOT invalidate existing user tokens (they remain in user credentials)
---
### POST /api/admin/oauth/:vendor/sandbox
**Admin required** — Launch isolated Browserbase session for OAuth app registration
Creates a temporary cloud browser (expires in 10 min) pre-aimed at the vendor's OAuth registration page. Admin logs in once, registers the app, copies Client ID/Secret.
**Path params:**
- `vendor` (string): OAuth provider ID
**Response (200 OK):**
```json
{
"ok": true,
"session_id": "abc-123-def",
"live_view": "https://api.browserbase.com/debug/abc-123-def",
"register_url": "https://console.cloud.google.com/apis/credentials/oauthclient",
"redirect_uri": "https://venturaclaw.com/oauth/google/callback",
"hint": "Step 1: paste https://console.cloud.google.com/apis/credentials/oauthclient into the cloud browser's address bar. Step 2: register the app, set redirect URI, copy Client ID/Secret. Step 3: paste them back here."
}
```
**Response (500 error):**
```json
{
"error": "BROWSERBASE_API_KEY not in env (add to ~/Projects/secrets-manager and restart)"
}
```
**Side effects:**
- Calls Browserbase API to create session
- Logs session creation to audit trail
---
### POST /api/admin/browserbase/release/:sessionId
**Admin required** — Release a Browserbase session early
**Path params:**
- `sessionId` (string): session ID returned by /sandbox endpoint
**Response (200 OK):**
```json
{
"ok": true
}
```
**Side effects:**
- Sends REQUEST_RELEASE to Browserbase API
- Logs release to audit trail
---
## OAuth User Flow
### GET /oauth/:vendor/connect
**Session required** — Redirect user to vendor's OAuth consent screen
User clicks "Connect Google" (or other vendor) on the connections page → this endpoint signs a CSRF state token and redirects.
**Path params:**
- `vendor` (string): OAuth provider ID
**Query params:**
- `redirect_after` (optional): where to redirect after OAuth callback completes (default: `/connections`)
**Response (302 Found):**
```
Location: https://accounts.google.com/o/oauth2/v2/auth?
client_id=...&
redirect_uri=https://venturaclaw.com/oauth/google/callback&
state=<signed-24-byte-token>&
response_type=code&
scope=...
```
**Side effects:**
- Creates entry in `data/oauth-state.json` (expires after 30 min)
- Logs to audit trail
---
### GET /oauth/:vendor/callback
**Public** — Vendor redirects here with authorization code
Handles the OAuth code-for-token exchange. On success, stores access_token (and refresh_token if provided) in user credentials.
**Query params (vendor-provided):**
- `code` (string): authorization code from vendor
- `state` (string): CSRF token (validated against oauth-state.json)
- `error` (optional): error from vendor if user denied
**Response (302 Found):**
```
Location: /connections
```
**Response (400 Bad Request):**
```html
<h1>OAuth error</h1>
<pre>invalid_scope</pre>
<p><a href="/connections">← back</a></p>
```
**Stored token structure:**
```json
{
"access_token": "ya29.a0AfH6SMBx...",
"refresh_token": "1//0gF...",
"token_type": "Bearer",
"scope": "https://www.googleapis.com/auth/spreadsheets ...",
"expires_at": "2026-05-06T12:42:30Z",
"_connected_at": "2026-05-05T12:42:30Z",
"_via": "oauth"
}
```
**Side effects:**
- Exchanges code for token at vendor's token_url
- Stores token in `data/credentials.json` under user ID
- Logs successful connection to audit trail
- Deletes state token from oauth-state.json
---
## Chat & Intent Routing
### POST /api/chat
**Session required** — Send a natural-language message to the intent router
Routes the user's message through a regex-based planner first, then escalates to local LLM (Ollama qwen3:14b on Mac Studio 1) if no match. Triggers corresponding connector actions—either immediately (safe, non-sensitive) or queued for admin approval.
**Request:**
```json
{
"message": "post our newest product to all socials"
}
```
**Response (200 OK):**
```json
{
"reply": "Drafting posts for all 10 social platforms. 10 actions queued for approval.",
"toolCalls": [
{
"connector": "instagram",
"name": "Instagram",
"action": "post.create",
"queued": true,
"input": {}
},
{
"connector": "facebook",
"name": "Facebook",
"action": "post.create",
"queued": true,
"input": {}
}
]
}
```
**Example: Slack message**
```json
{
"message": "tell the team 'deploy is ready' in #announcements"
}
```
Response:
```json
{
"reply": "Slack message queued for approval → #announcements: \"deploy is ready\"",
"toolCalls": [
{
"connector": "slack",
"name": "Slack",
"action": "chat.postMessage",
"queued": true,
"input": {
"channel": "announcements",
"text": "deploy is ready"
}
}
]
}
```
**Example: Stripe refund**
```json
{
"message": "refund $50 from charge ch_1234abcd"
}
```
Response:
```json
{
"reply": "Stripe refund queued for approval (ch_1234abcd) — $50.",
"toolCalls": [
{
"connector": "stripe",
"name": "Stripe",
"action": "refund.create",
"queued": true,
"input": {
"charge": "ch_1234abcd",
"amount": 5000
}
}
]
}
```
**Queued vs. Executed:**
- `queued: true` — sensitive actions (payments, comms) → create approval record
- `queued: false` — read-only or low-risk actions → execute immediately if real impl exists
**Side effects:**
- Logs message and tool calls to audit trail
- For queued calls: creates approval records (persisted to `data/approvals.json`)
- For executed calls: may modify external systems (calls real connector implementations)
**curl:**
```bash
curl -X POST https://venturaclaw.com/api/chat \
-b cookies.txt \
-H "Content-Type: application/json" \
-d '{"message":"what is my stripe balance"}'
```
---
## Approvals
### GET /api/approvals
**Session required** — List pending/completed approval records
Admins see all approvals. Regular users see only their own.
**Response (200 OK):**
```json
{
"approvals": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"userId": 2,
"userEmail": "demo@venturaclaw.com",
"connector": "stripe",
"connectorName": "Stripe",
"action": "refund.create",
"input": {
"charge": "ch_1234abcd",
"amount": 5000
},
"message": "refund $50 from charge ch_1234abcd",
"status": "pending",
"createdAt": "2026-05-05T18:30:00Z",
"decidedBy": null,
"decidedAt": null,
"executionResult": null,
"executionError": null,
"executedAt": null
}
]
}
```
---
### POST /api/approvals/:id/decide
**Admin required** — Approve or reject a pending action
Executes the action on approve (if real impl exists), logs comms-compliance checks, and stores decision + result/error.
**Path params:**
- `id` (string): approval UUID
**Request:**
```json
{
"decision": "approve",
"input": {
"channel": "announcements",
"text": "deploy is live"
},
"comms_compliance_override": false
}
```
**Response (200 OK):**
```json
{
"ok": true,
"approval": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "approved",
"decidedBy": "admin@venturaclaw.com",
"decidedAt": "2026-05-05T18:35:00Z",
"executionResult": {
"ok": true,
"ts": "2026-05-05T18:35:01Z"
},
"executedAt": "2026-05-05T18:35:01Z",
"commsCompliancePassed": true
}
}
```
**Response (422 Unprocessable Entity) — Comms compliance violation:**
```json
{
"error": "comms_compliance_violations",
"kind": "dnc_match",
"violations": [
{
"type": "dnc_federal",
"match": "recipient@example.com"
}
],
"message": "1 recipient(s) on Federal DNC list",
"hint": "fix the violations OR resubmit with comms_compliance_override:true (audit-logged)"
}
```
**Decision values:**
- `"approve"` — execute the action (if real impl exists)
- `"reject"` — log rejection and stop
**Comms compliance:**
- Email/SMS/voice actions checked against CAN-SPAM, TCPA, Federal/State DNC, CCPA suppressions
- If violations found: returns 422 unless `comms_compliance_override: true` (logged)
**Side effects:**
- Calls real connector implementation if decision is "approve"
- Stores result or error message
- Logs decision to audit trail with violation summary
---
## Audit Log
### GET /api/audit
**Admin required** — Paginated audit trail of all events
**Query params:**
- `limit` (optional, default 200, max 1000): number of events
**Response (200 OK):**
```json
{
"events": [
{
"ts": "2026-05-05T18:35:01Z",
"kind": "approval_executed",
"id": "550e8400-e29b-41d4-a716-446655440000",
"connector": "slack",
"action": "chat.postMessage",
"by": "admin@venturaclaw.com",
"ok": true
},
{
"ts": "2026-05-05T18:30:00Z",
"kind": "chat",
"userId": 2,
"message": "post to announcements",
"toolCalls": 1
},
{
"ts": "2026-05-05T18:00:00Z",
"kind": "login",
"userId": 2,
"email": "demo@venturaclaw.com",
"role": "user"
}
],
"total": 427
}
```
**Event kinds:**
- `login`, `login_failed`, `logout`
- `connection_saved`, `connection_removed`, `connections_imported`
- `oauth_connected`, `oauth_app_registered`, `oauth_app_removed`
- `chat`, `chat_exec`, `connector_exec`
- `approval_decision`, `approval_executed`
- `comms_compliance_passed`, `comms_compliance_blocked`, `comms_compliance_override`
- `browserbase_sandbox_opened`, `browserbase_released`
---
## Admin: User Management
### GET /api/admin/users
**Admin required** — List all users (passwords redacted)
**Response (200 OK):**
```json
{
"users": [
{
"id": 1,
"email": "admin@venturaclaw.com",
"name": "Admin",
"role": "admin"
},
{
"id": 2,
"email": "demo@venturaclaw.com",
"name": "Demo User",
"role": "user"
}
]
}
```
---
### POST /api/admin/users
**Admin required** — Create a new user
**Request:**
```json
{
"email": "newuser@venturaclaw.com",
"password": "temporary-password",
"name": "New User",
"role": "user"
}
```
**Response (200 OK):**
```json
{
"ok": true,
"user": {
"id": 3,
"email": "newuser@venturaclaw.com",
"name": "New User",
"role": "user"
}
}
```
**Side effects:**
- Persists to `data/users.json`
- Logs creation to audit trail
---
### DELETE /api/admin/users/:id
**Admin required** — Remove a user
**Path params:**
- `id` (integer): user ID
**Response (200 OK):**
```json
{
"ok": true,
"removed": 1
}
```
---
## Comms Compliance (Email, SMS, Voice)
### POST /api/comms/scrub-preview
**Session required** — Preview what fields would be filtered by compliance rules
Does NOT require approval; anyone can test the scrubber.
**Request:**
```json
{
"action": "slack.chat.postMessage",
"input": {
"channel": "announcements",
"text": "new product launch"
}
}
```
**Response (200 OK):**
```json
{
"ok": true,
"kind": "no_violations",
"violations": [],
"message": ""
}
```
**Response (with violations):**
```json
{
"ok": false,
"kind": "dnc_match",
"violations": [
{
"type": "dnc_federal",
"match": "recipient@example.com",
"reason": "Federal Do-Not-Call"
}
],
"message": "1 recipient(s) on Federal DNC list"
}
```
---
### GET /api/comms/suppression
**Admin required** — List current suppression list (DNC, complaints, bounces)
**Response (200 OK):**
```json
{
"entries": [
{
"kind": "dnc_federal",
"value": "recipient@example.com",
"reason": "CAN-SPAM opt-out 2026-04-30",
"added_at": "2026-04-30T10:00:00Z"
}
]
}
```
---
### POST /api/comms/suppression
**Admin required** — Add entry to suppression list
**Request:**
```json
{
"kind": "dnc_federal",
"value": "bounce@example.com",
"reason": "bounced 3x, undeliverable"
}
```
**Response (200 OK):**
```json
{
"ok": true,
"kind": "dnc_federal",
"value": "bounce@example.com",
"added_at": "2026-05-05T18:40:00Z"
}
```
---
## Rate Limits & Quotas
**Currently none.** The following endpoints should implement rate limits:
- `POST /api/chat` — 10 req/min per user (prevents LLM spam)
- `POST /api/approvals/:id/decide` → `execute()` — 1 req/sec per connector (vendor API throttle)
- `POST /api/admin/oauth/:vendor/sandbox` — 3 per hour per admin (Browserbase session-minute quota)
- `POST /api/me/connections/import` — 5 per hour per user (prevents credential-stuffing)
**Recommendation:** Implement via express-rate-limit with Redis backend on production.
---
## Error Handling
All errors follow this shape:
**Validation error (400 Bad Request):**
```json
{
"error": "missing email/password"
}
```
**Auth error (401 Unauthorized):**
```json
{
"error": "unauthorized"
}
```
**Forbidden (403 Forbidden):**
```json
{
"error": "forbidden"
}
```
**Not found (404 Not Found):**
```json
{
"error": "not found"
}
```
**Conflict (409 Conflict):**
```json
{
"error": "email exists"
}
```
**Server error (500 Internal Server Error):**
```json
{
"error": "Stripe API error: invalid_request_error"
}
```
---
## Data Storage
All data persists to JSON files in `/server/data/`:
- `users.json` — user accounts (emails, hashed passwords, roles)
- `credentials.json` — { userId: { connectorId: { field: value } } }
- `oauth-apps.json` — { vendor: { client_id, client_secret, registered_at, registered_by } }
- `oauth-state.json` — { state: { userId, vendor, redirect_after, created_at } } (short-lived CSRF tokens)
- `approvals.json` — approval queue (newest first, max 500 entries)
- `audit.json` — full audit trail (newest first, max 500 entries)
**On production:** Replace JSON store with PostgreSQL (schema + migrations TBD).
---
## Public Domain
VenturaClaw is deployed to `https://venturaclaw.com`. All subdomains/paths require SSL. Robots.txt blocks `/admin` and `/api` from search indexing.
---
## Support
For API issues, contact `info@agentabrams.com` or file an issue in the VenturaClaw project.
Last updated: 2026-05-05