diff --git a/api-reference/calendar.mdx b/api-reference/calendar.mdx
index a94f9da..a48f077 100644
--- a/api-reference/calendar.mdx
+++ b/api-reference/calendar.mdx
@@ -7,7 +7,9 @@ description: "Google Calendar integration endpoints for OAuth, event management,
Connect a Google Calendar account and manage events, check availability, and schedule directly through the API.
-Most calendar endpoints require a connected Google Calendar account. Use the [connect flow](#connect-calendar) to authorize access before calling event endpoints.
+All calendar endpoints require an authenticated session. The user is identified from the session automatically — you do not pass a `userId` parameter.
+
+Most calendar endpoints also require a connected Google Calendar account. Use the [connect flow](#connect-calendar) to authorize access before calling event endpoints.
## Base URL
@@ -15,6 +17,16 @@ Connect a Google Calendar account and manage events, check availability, and sch
https://agentbot.raveculture.xyz/api/calendar
```
+## Authentication
+
+All calendar endpoints require a valid NextAuth session. Requests without an active session receive a `401 Unauthorized` response (or a redirect to `/login` for browser-based flows).
+
+The authenticated user's identity is derived from the session. You do not need to include a `userId` parameter in any request.
+
+## Token storage
+
+Calendar tokens (access and refresh tokens) are encrypted at rest using AES-256-GCM before being persisted to the database. Tokens are never stored in plaintext.
+
## Connect calendar
```http
@@ -28,7 +40,6 @@ Initiates the Google Calendar OAuth flow. Returns an authorization URL that the
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `action` | string | Yes | Must be `connect` |
-| `userId` | string | Yes | Your user identifier |
### Response
@@ -44,6 +55,7 @@ Redirect the user to `authUrl` to begin the OAuth consent flow. After granting a
| Code | Description |
|------|-------------|
+| 401 | Not authenticated (no active session) |
| 400 | Invalid action |
## OAuth callback
@@ -59,17 +71,18 @@ Handles the OAuth authorization code exchange after Google redirects the user ba
| Parameter | Type | Description |
|-----------|------|-------------|
| `code` | string | Authorization code provided by Google |
-| `state` | string | The `userId` passed during the connect flow |
+| `state` | string | HMAC-signed state token generated during the connect flow. Contains the user ID and a timestamp, verified on callback. Expires after 10 minutes. |
| `error` | string | Error code if the user denied access or an error occurred |
### Behavior
On success, this endpoint:
-1. Exchanges the authorization code for access and refresh tokens.
-2. Retrieves the user's primary calendar ID and timezone.
-3. Stores the connection for future API calls.
-4. Redirects to `/dashboard/calendar?connected=true`.
+1. Verifies the HMAC-signed state parameter and checks it has not expired.
+2. Exchanges the authorization code for access and refresh tokens.
+3. Retrieves the user's primary calendar ID and timezone.
+4. Encrypts and persists the tokens to the database (AES-256-GCM).
+5. Redirects to `/dashboard/calendar?connected=true`.
### Error redirects
@@ -90,6 +103,8 @@ GET /api/calendar?action=auth
Redirects the browser directly to the Google OAuth consent screen. This is an alternative to the POST-based connect flow — use it when you want a simple link-based authorization.
+Requires an active session. If the user is not authenticated, this endpoint redirects to `/login`.
+
### Query parameters
| Parameter | Type | Required | Description |
@@ -99,17 +114,16 @@ Redirects the browser directly to the Google OAuth consent screen. This is an al
## List events
```http
-GET /api/calendar?action=list&userId={userId}
+GET /api/calendar?action=list
```
-Returns calendar events within a date range.
+Returns calendar events within a date range. The user is identified from the session.
### Query parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `action` | string | Yes | Must be `list` |
-| `userId` | string | Yes | Your user identifier |
| `start` | string | No | ISO 8601 start date. Defaults to now. |
| `end` | string | No | ISO 8601 end date. Defaults to 30 days from now. |
@@ -134,22 +148,21 @@ Returns calendar events within a date range.
| Code | Description |
|------|-------------|
-| 401 | Calendar not connected |
+| 401 | Not authenticated or calendar not connected |
## Check availability
```http
-GET /api/calendar?action=availability&userId={userId}
+GET /api/calendar?action=availability
```
-Returns available and busy time slots for a given date. Slots are one hour each, from 09:00 to 23:00.
+Returns available and busy time slots for a given date. Slots are one hour each, from 09:00 to 23:00. The user is identified from the session.
### Query parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `action` | string | Yes | Must be `availability` |
-| `userId` | string | Yes | Your user identifier |
| `date` | string | No | Date in `YYYY-MM-DD` format. Defaults to today. |
### Response
@@ -171,7 +184,7 @@ Returns available and busy time slots for a given date. Slots are one hour each,
| Code | Description |
|------|-------------|
-| 401 | Calendar not connected |
+| 401 | Not authenticated or calendar not connected |
## Create event
@@ -179,14 +192,13 @@ Returns available and busy time slots for a given date. Slots are one hour each,
POST /api/calendar
```
-Creates a new calendar event.
+Creates a new calendar event. The user is identified from the session.
### Request body
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `action` | string | Yes | Must be `create-event` |
-| `userId` | string | Yes | Your user identifier |
| `title` | string | Yes | Event title |
| `start` | string | Yes | ISO 8601 start time |
| `end` | string | Yes | ISO 8601 end time |
@@ -199,7 +211,6 @@ Creates a new calendar event.
```json
{
"action": "create-event",
- "userId": "user_123",
"title": "DJ Set @ Warehouse",
"start": "2026-03-28T22:00:00Z",
"end": "2026-03-29T02:00:00Z",
@@ -227,7 +238,7 @@ Creates a new calendar event.
| Code | Description |
|------|-------------|
-| 401 | Calendar not connected |
+| 401 | Not authenticated or calendar not connected |
| 500 | Internal error |
## Update event
@@ -236,14 +247,13 @@ Creates a new calendar event.
POST /api/calendar
```
-Updates an existing calendar event. Only the fields you include are changed.
+Updates an existing calendar event. Only the fields you include are changed. The user is identified from the session.
### Request body
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `action` | string | Yes | Must be `update-event` |
-| `userId` | string | Yes | Your user identifier |
| `eventId` | string | Yes | ID of the event to update |
| `title` | string | No | Updated event title |
| `description` | string | No | Updated description |
@@ -264,7 +274,7 @@ Updates an existing calendar event. Only the fields you include are changed.
| Code | Description |
|------|-------------|
-| 401 | Calendar not connected |
+| 401 | Not authenticated or calendar not connected |
| 500 | Internal error |
## Delete event
@@ -273,14 +283,13 @@ Updates an existing calendar event. Only the fields you include are changed.
POST /api/calendar
```
-Deletes a calendar event.
+Deletes a calendar event. The user is identified from the session.
### Request body
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `action` | string | Yes | Must be `delete-event` |
-| `userId` | string | Yes | Your user identifier |
| `eventId` | string | Yes | ID of the event to delete |
### Response
@@ -295,7 +304,7 @@ Deletes a calendar event.
| Code | Description |
|------|-------------|
-| 401 | Calendar not connected |
+| 401 | Not authenticated or calendar not connected |
| 500 | Internal error |
## Quick add
@@ -304,14 +313,13 @@ Deletes a calendar event.
POST /api/calendar
```
-Creates an event from a natural language string using Google Calendar's quick-add feature.
+Creates an event from a natural language string using Google Calendar's quick-add feature. The user is identified from the session.
### Request body
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `action` | string | Yes | Must be `quick-add` |
-| `userId` | string | Yes | Your user identifier |
| `text` | string | Yes | Natural language event description (for example, `"Meeting with Sarah tomorrow at 3pm"`) |
### Response
@@ -327,5 +335,5 @@ Creates an event from a natural language string using Google Calendar's quick-ad
| Code | Description |
|------|-------------|
-| 401 | Calendar not connected |
+| 401 | Not authenticated or calendar not connected |
| 500 | Internal error |
diff --git a/api-reference/invite.mdx b/api-reference/invite.mdx
index fc49120..1f140ef 100644
--- a/api-reference/invite.mdx
+++ b/api-reference/invite.mdx
@@ -1,73 +1,203 @@
---
title: Invite API
-description: "Generate and validate invite codes for platform access"
+description: "Create, manage, and verify invite tokens for platform access"
---
# Invite API
-Generate and validate invite codes for gating access to the Agentbot platform. These endpoints are backend-only.
+Create and verify invite tokens for gating access to the Agentbot platform.
-Invite codes are now persisted in the database and survive server restarts. Code generation requires internal API key authentication to prevent invite flooding. Code validation remains public.
+Invite tokens are 64-character hex strings generated from `crypto.randomBytes(32)`. The older 12-character code format is deprecated — see [legacy format](#legacy-invite-format) below.
-## Generate invite code
+## Authentication
+
+| Endpoint | Auth required |
+|----------|---------------|
+| `POST /api/invite` | Session (any authenticated user) |
+| `POST /api/invites/verify` | None |
+| `GET /api/admin/invites` | Session (admin only) |
+| `POST /api/admin/invites` | Session (admin only) |
+
+## Create invite
```http
-POST /api/invite/generate
+POST /api/invite
```
-Generates a new invite code. Requires internal API key authentication via the `Authorization: Bearer ` header.
+Creates an invite token linked to your account. Requires an authenticated session.
-### Errors
+### Request body
-| Code | Description |
-|------|-------------|
-| 401 | Missing or invalid internal API key |
-| 500 | Failed to generate invite code |
+| Field | Type | Required | Description |
+|-------|------|----------|-------------|
+| `name` | string | Yes | Display name for the invite recipient. Validated against injection patterns. |
### Response
```json
{
- "code": "a1b2c3d4e5f6"
+ "success": true,
+ "inviteUrl": "https://agentbot.raveculture.xyz/invite?token=abc123...&name=Alice",
+ "token": "a1b2c3d4...64 hex characters"
}
```
| Field | Type | Description |
|-------|------|-------------|
-| `code` | string | A 12-character hex string generated from 6 random bytes |
+| `success` | boolean | Whether the invite was created |
+| `inviteUrl` | string | Full URL the recipient can use to accept the invite |
+| `token` | string | 64-character hex token |
-## Validate invite code
+### Errors
+
+| Code | Description |
+|------|-------------|
+| 400 | Name is missing or contains invalid characters |
+| 401 | Not authenticated |
+| 404 | User not found |
+| 500 | Failed to create invite |
+
+## Verify invite
```http
-POST /api/invite/validate
+POST /api/invites/verify
```
-Validates and consumes an invite code. The operation is atomic — only one concurrent request can successfully consume a given code. Once validated, the code is marked as used and cannot be reused. No authentication required.
+Verifies an invite token and returns invite details. No authentication required. Tokens must be in the 64-character hex format.
### Request body
| Field | Type | Required | Description |
|-------|------|----------|-------------|
-| `code` | string | Yes | The invite code to validate |
+| `token` | string | Yes | 64-character hex invite token |
### Response (valid)
```json
{
- "valid": true
+ "valid": true,
+ "email": "invitee@example.com",
+ "plan": "solo"
}
```
-### Response (invalid)
+| Field | Type | Description |
+|-------|------|-------------|
+| `valid` | boolean | Whether the token is valid |
+| `email` | string | Email associated with the invite |
+| `plan` | string | Plan tier for the invite (defaults to `solo`) |
+
+### Errors
+
+| Code | Description |
+|------|-------------|
+| 400 | Token is missing, not a string, or not in valid 64-character hex format |
+| 404 | Invite not found or expired |
+| 410 | Invite has already been used |
+| 500 | Verification failed |
+
+## List invites (admin)
+
+```http
+GET /api/admin/invites
+```
+
+Returns all invites with summary counts. Requires an authenticated session with an admin email address.
+
+### Response
```json
{
- "valid": false
+ "invites": [
+ {
+ "code": "a1b2c3d4...64 hex characters",
+ "email": "invitee@example.com",
+ "createdAt": "2026-03-25T21:00:00.000Z",
+ "status": "active"
+ }
+ ],
+ "total": 1,
+ "active": 1
}
```
+| Field | Type | Description |
+|-------|------|-------------|
+| `invites` | array | List of all invites |
+| `invites[].code` | string | 64-character hex invite token |
+| `invites[].email` | string | Email the invite was created for |
+| `invites[].createdAt` | string | ISO 8601 creation timestamp |
+| `invites[].usedAt` | string \| undefined | ISO 8601 timestamp when the invite was used |
+| `invites[].status` | string | One of `active`, `used`, or `expired` |
+| `invites[].userId` | string \| undefined | User ID of the person who redeemed the invite |
+| `total` | number | Total number of invites |
+| `active` | number | Number of currently active invites |
+
### Errors
| Code | Description |
|------|-------------|
-| 400 | Code is missing, invalid, or already used |
+| 403 | Not authorized (requires admin) |
+| 500 | Failed to retrieve invites |
+
+## Create invite (admin)
+
+```http
+POST /api/admin/invites
+```
+
+Creates an invite for a specific email address. Requires an authenticated session with an admin email address.
+
+### Request body
+
+| Field | Type | Required | Description |
+|-------|------|----------|-------------|
+| `email` | string | Yes | Email address to associate with the invite |
+
+### Response
+
+```json
+{
+ "success": true,
+ "code": "a1b2c3d4...64 hex characters",
+ "email": "invitee@example.com",
+ "inviteUrl": "https://agentbot.raveculture.xyz/invite?token=a1b2c3d4..."
+}
+```
+
+| Field | Type | Description |
+|-------|------|-------------|
+| `success` | boolean | Whether the invite was created |
+| `code` | string | 64-character hex invite token |
+| `email` | string | Email the invite was created for |
+| `inviteUrl` | string | Full URL the recipient can use to accept the invite |
+
+### Errors
+
+| Code | Description |
+|------|-------------|
+| 400 | Email is missing |
+| 403 | Not authorized (requires admin) |
+| 500 | Failed to create invite |
+
+---
+
+## Legacy invite format
+
+The previous invite system used 12-character hex codes with `POST /api/invite/generate` and `POST /api/invite/validate`. These endpoints are deprecated. Migrate to the new endpoints above.
+
+### Deprecated: generate invite code
+
+```http
+POST /api/invite/generate
+```
+
+Previously generated a 12-character hex invite code. Replaced by `POST /api/invite` (session auth) and `POST /api/admin/invites` (admin session auth).
+
+### Deprecated: validate invite code
+
+```http
+POST /api/invite/validate
+```
+
+Previously validated and consumed a 12-character invite code. Replaced by `POST /api/invites/verify`, which accepts 64-character hex tokens and returns richer response data including `email` and `plan`.
diff --git a/api-reference/overview.mdx b/api-reference/overview.mdx
index db15cd4..1a5afc9 100644
--- a/api-reference/overview.mdx
+++ b/api-reference/overview.mdx
@@ -284,8 +284,10 @@ curl -X POST https://agentbot.raveculture.xyz/api/ai/chat \
| `/api/underground/wallets/:address/balance` | GET | Get agent wallet USDC balance (backend only, requires auth) |
| `/api/underground/splits` | POST | Create and queue a royalty split (backend only, requires auth) |
| `/api/colony/status` | GET | Get colony tree, soul cognitive state, or diagnostics |
-| `/api/invite/generate` | POST | Generate an invite code (backend only, requires internal API key) |
-| `/api/invite/validate` | POST | Validate and consume an invite code (backend only, no auth) |
+| `/api/invite` | POST | Create an invite token (requires session auth) |
+| `/api/invites/verify` | POST | Verify an invite token (no auth required) |
+| `/api/admin/invites` | GET | List all invites (requires admin session) |
+| `/api/admin/invites` | POST | Create an invite for a specific email (requires admin session) |
| `/api/summarize` | POST | Summarize a URL — returns title, description, headings, paragraphs, word count (web summarizer service) |
| `/api/extract` | POST | Extract links, images, and Open Graph metadata from a URL (web summarizer service) |
| `/api/clawmerchants` | GET | List available ClawMerchants data feeds, or fetch a specific feed by `feed` query parameter |