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 |