vibecircle dev

VibeCircle Bot API

Quick Start

1. Get an API Token

Go to Settings > API Tokens in the VibeCircle app, or call:

curl -X POST https://pg-me.know.tw/api/api-tokens \
  -H "Cookie: session_token=YOUR_SESSION" \
  -H "Content-Type: application/json" \
  -d '{"label": "My Bot", "expiresInDays": 90}'

The response includes a token field (e.g. vbc_a1b2c3d4...). Save it immediately — it is only shown once.

2. Authenticate

Include the token in all requests:

Authorization: Bearer vbc_your_token_here

3. Send a Message

# Create or get a DM thread
curl -X POST https://pg-me.know.tw/api/dm/threads \
  -H "Authorization: Bearer vbc_..." \
  -H "Content-Type: application/json" \
  -d '{"participantId": "USER_CUID"}'

# Send a text message
curl -X POST https://pg-me.know.tw/api/dm/threads/THREAD_ID/messages \
  -H "Authorization: Bearer vbc_..." \
  -H "Content-Type: application/json" \
  -d '{"body": "Hello from bot!"}'

4. Send a Photo

# Step 1: Request upload URL
curl -X POST https://pg-me.know.tw/api/media/upload-url \
  -H "Authorization: Bearer vbc_..." \
  -H "Content-Type: application/json" \
  -d '{"filename": "photo.jpg", "mimeType": "image/jpeg", "sizeBytes": 123456}'

# Response: {"url": "https://s3.../presigned-url", "objectKey": "uploads/user123/abc.jpg"}

# Step 2: Upload file to the presigned URL
curl -X PUT "PRESIGNED_URL" \
  -H "Content-Type: image/jpeg" \
  --data-binary @photo.jpg

# Step 3: Register the upload
curl -X POST https://pg-me.know.tw/api/media/complete \
  -H "Authorization: Bearer vbc_..." \
  -H "Content-Type: application/json" \
  -d '{"objectKey": "uploads/user123/abc.jpg", "mimeType": "image/jpeg", "sizeBytes": 123456}'

# Response: {"id": "MEDIA_ID", ...}

# Step 4: Send message with the image
curl -X POST https://pg-me.know.tw/api/dm/threads/THREAD_ID/messages \
  -H "Authorization: Bearer vbc_..." \
  -H "Content-Type: application/json" \
  -d '{"body": "Check this out!", "mediaObjectId": "MEDIA_ID"}'

Interactive Docs

Full API reference with "Try it out" is available at:

https://pg-me.know.tw/api/docs

Endpoint Reference

All endpoints are under /api. Protected endpoints require Authorization: Bearer vbc_... header.

Auth (Public)

| Method | Path | Description | |--------|------|-------------| | POST | /auth/magic-link | Send magic link email {email} | | GET | /auth/verify?token=X&email=Y | Verify magic link, set session cookie | | GET | /auth/session | Get current session (returns {user} or null) | | POST | /auth/logout | Logout, clear session |

API Tokens (Protected)

| Method | Path | Description | |--------|------|-------------| | GET | /api-tokens | List active tokens | | POST | /api-tokens | Create token {label, expiresInDays?} | | DELETE | /api-tokens/:tokenId | Revoke token |

Users (Protected)

| Method | Path | Description | |--------|------|-------------| | GET | /users/me | Get own profile | | PATCH | /users/me | Update profile {name?, image?} | | GET | /users/search?email=X | Search users by email | | GET | /users/:userId | Get user profile |

DM (Protected)

| Method | Path | Description | |--------|------|-------------| | GET | /dm/threads | List DM threads | | POST | /dm/threads | Create thread {participantId, isE2ee?} | | GET | /dm/threads/:threadId/messages | List messages ?cursor=&limit= | | POST | /dm/threads/:threadId/messages | Send message {body?, mediaObjectId?} |

Media (Protected)

| Method | Path | Description | |--------|------|-------------| | POST | /media/upload-url | Get presigned upload URL {filename, mimeType, sizeBytes} | | POST | /media/complete | Register completed upload {objectKey, mimeType, sizeBytes, ...} |

Friends (Protected)

| Method | Path | Description | |--------|------|-------------| | GET | /friends?status=ACCEPTED | List friends | | POST | /friends/request | Send friend request {friendId} | | POST | /friends/:id/accept | Accept request | | POST | /friends/:id/reject | Reject request | | PATCH | /friends/:id/tier | Update tier {tier: CLOSE_FRIEND\|FRIEND\|ACQUAINTANCE} | | DELETE | /friends/:id | Remove friend |

Feed (Protected)

| Method | Path | Description | |--------|------|-------------| | GET | /feed | Get feed (presences + pins from friends) |

Spotify (Protected)

| Method | Path | Description | |--------|------|-------------| | GET | /spotify/connect | Redirect to Spotify OAuth | | GET | /spotify/callback | OAuth callback | | DELETE | /spotify | Unlink Spotify |

Pins (Protected)

| Method | Path | Description | |--------|------|-------------| | GET | /pins | List pins | | POST | /pins | Create pin {spotifyTrackId, trackName, artistName, albumName, ...} | | DELETE | /pins/:id | Delete pin |

Presence (Protected)

| Method | Path | Description | |--------|------|-------------| | GET | /presence/:userId | Get user's current presence | | PATCH | /presence/settings | Update presence visibility {audienceTier} |


Realtime Events (Pusher/Soketi)

Bot can subscribe to private-user-{userId} channel for live events:

| Event | Payload | Description | |-------|---------|-------------| | new-message | {threadId, message} | New DM message received | | friend-request | {friendshipId, from} | Incoming friend request | | friend-accepted | {friendshipId} | Friend request accepted |

Pusher auth endpoint: POST /api/pusher/auth


Error Responses

All errors return JSON:

{"error": "Error message"}

Common status codes:

  • 400 — Bad request / validation error
  • 401 — Unauthorized (missing or invalid token)
  • 403 — Forbidden
  • 404 — Not found