sojorn/sojorn_docs/reference/API_REFERENCE.md
Patrick Britton 56a9dd032f feat: Add enhanced video moderation with frame extraction and implement placeholder UI methods
- Add VideoProcessor service to PostHandler for frame-based video moderation
- Implement multi-frame extraction and Azure OpenAI Vision analysis for video content
- Enhance VideoStitchingService with filters, speed control, and text overlays
- Add image upload dialogs for group avatar and banner in GroupCreationModal
- Implement navigation placeholders for mentions, hashtags, and URLs in sojornRichText
2026-02-17 13:32:58 -06:00

1248 lines
22 KiB
Markdown

# Sojorn API Reference
## 🚀 Complete REST API Documentation
**Version**: 3.0
**Status**: ✅ **PRODUCTION READY**
**Last Updated**: February 17, 2026
---
## 📋 Overview
The Sojorn API provides comprehensive REST endpoints for all platform features including authentication, posts, groups, beacons, E2EE chat, and more. All endpoints follow RESTful conventions and return JSON responses.
## 🔐 Authentication
### Base URL
```
Production: https://api.sojorn.app
Development: http://localhost:8080
```
### Authentication Methods
- **JWT Bearer Token**: `Authorization: Bearer <token>`
- **API Key**: `X-API-Key: <api-key>` (for service-to-service)
- **Session Cookie**: Automatic cookie-based authentication for web
### Token Endpoints
#### POST /auth/register
Register a new user account.
**Request:**
```json
{
"email": "user@example.com",
"password": "securePassword123",
"handle": "username",
"display_name": "Display Name"
}
```
**Response:**
```json
{
"success": true,
"user": {
"id": "uuid",
"email": "user@example.com",
"handle": "username",
"display_name": "Display Name",
"created_at": "2026-02-17T12:00:00Z"
},
"token": "jwt_token_here",
"refresh_token": "refresh_token_here"
}
```
#### POST /auth/login
Authenticate user and return tokens.
**Request:**
```json
{
"email": "user@example.com",
"password": "securePassword123"
}
```
**Response:**
```json
{
"success": true,
"user": {
"id": "uuid",
"email": "user@example.com",
"handle": "username",
"display_name": "Display Name"
},
"token": "jwt_token_here",
"refresh_token": "refresh_token_here"
}
```
#### POST /auth/refresh
Refresh JWT access token.
**Request:**
```json
{
"refresh_token": "refresh_token_here"
}
```
**Response:**
```json
{
"success": true,
"token": "new_jwt_token_here",
"expires_at": "2026-02-18T12:00:00Z"
}
```
---
## 👤 User Management
### GET /users/me
Get current user profile.
**Headers:**
```
Authorization: Bearer <token>
```
**Response:**
```json
{
"success": true,
"user": {
"id": "uuid",
"email": "user@example.com",
"handle": "username",
"display_name": "Display Name",
"bio": "User bio",
"avatar_url": "https://cdn.sojorn.app/avatars/uuid.jpg",
"follower_count": 150,
"following_count": 75,
"post_count": 42,
"created_at": "2026-02-17T12:00:00Z",
"is_verified": true,
"is_premium": false
}
}
```
### PUT /users/me
Update current user profile.
**Request:**
```json
{
"display_name": "New Display Name",
"bio": "Updated bio",
"avatar_url": "https://cdn.sojorn.app/avatars/new.jpg",
"location": "San Francisco, CA",
"website": "https://example.com"
}
```
**Response:**
```json
{
"success": true,
"user": {
"id": "uuid",
"display_name": "New Display Name",
"bio": "Updated bio",
"avatar_url": "https://cdn.sojorn.app/avatars/new.jpg",
"location": "San Francisco, CA",
"website": "https://example.com"
}
}
```
### GET /users/{handle}
Get user profile by handle.
**Response:**
```json
{
"success": true,
"user": {
"id": "uuid",
"handle": "username",
"display_name": "Display Name",
"bio": "User bio",
"avatar_url": "https://cdn.sojorn.app/avatars/uuid.jpg",
"follower_count": 150,
"following_count": 75,
"post_count": 42,
"is_following": false,
"is_blocked": false,
"created_at": "2026-02-17T12:00:00Z"
}
}
```
---
## 📝 Posts & Content
### GET /posts
Get posts with filtering and pagination.
**Query Parameters:**
- `limit`: Number of posts to return (default: 20, max: 100)
- `offset`: Pagination offset (default: 0)
- `category`: Filter by category
- `author_id`: Filter by author
- `has_video`: Filter by video content (true/false)
- `algorithm`: Use algorithmic ranking (true/false)
**Response:**
```json
{
"success": true,
"posts": [
{
"id": "uuid",
"author_id": "uuid",
"author_handle": "username",
"author_avatar": "https://cdn.sojorn.app/avatars/uuid.jpg",
"body": "Post content here",
"image_url": "https://cdn.sojorn.app/posts/uuid.jpg",
"video_url": "https://cdn.sojorn.app/videos/uuid.mp4",
"thumbnail_url": "https://cdn.sojorn.app/thumbnails/uuid.jpg",
"category": "general",
"visibility": "public",
"like_count": 25,
"comment_count": 8,
"repost_count": 3,
"share_count": 2,
"is_liked": false,
"is_reposted": false,
"is_saved": false,
"created_at": "2026-02-17T12:00:00Z",
"updated_at": "2026-02-17T12:00:00Z"
}
],
"pagination": {
"total": 1000,
"limit": 20,
"offset": 0,
"has_more": true
}
}
```
### POST /posts
Create a new post.
**Request:**
```json
{
"body": "Post content here",
"category": "general",
"visibility": "public",
"image_url": "https://cdn.sojorn.app/posts/uuid.jpg",
"video_url": "https://cdn.sojorn.app/videos/uuid.mp4",
"thumbnail_url": "https://cdn.sojorn.app/thumbnails/uuid.jpg",
"is_nsfw": false,
"tags": ["tag1", "tag2"]
}
```
**Response:**
```json
{
"success": true,
"post": {
"id": "uuid",
"body": "Post content here",
"category": "general",
"visibility": "public",
"image_url": "https://cdn.sojorn.app/posts/uuid.jpg",
"video_url": "https://cdn.sojorn.app/videos/uuid.mp4",
"thumbnail_url": "https://cdn.sojorn.app/thumbnails/uuid.jpg",
"created_at": "2026-02-17T12:00:00Z"
}
}
```
### PUT /posts/{id}
Update an existing post.
**Request:**
```json
{
"body": "Updated post content",
"category": "general",
"visibility": "public",
"is_nsfw": false
}
```
**Response:**
```json
{
"success": true,
"post": {
"id": "uuid",
"body": "Updated post content",
"updated_at": "2026-02-17T12:30:00Z"
}
}
```
### DELETE /posts/{id}
Delete a post.
**Response:**
```json
{
"success": true,
"message": "Post deleted successfully"
}
```
---
## 💬 Comments
### GET /posts/{post_id}/comments
Get comments for a post.
**Query Parameters:**
- `limit`: Number of comments (default: 50)
- `offset`: Pagination offset
**Response:**
```json
{
"success": true,
"comments": [
{
"id": "uuid",
"post_id": "uuid",
"author_id": "uuid",
"author_handle": "username",
"author_avatar": "https://cdn.sojorn.app/avatars/uuid.jpg",
"body": "Comment content",
"like_count": 5,
"reply_count": 2,
"is_liked": false,
"created_at": "2026-02-17T12:00:00Z"
}
],
"pagination": {
"total": 100,
"limit": 50,
"offset": 0,
"has_more": true
}
}
```
### POST /posts/{post_id}/comments
Create a comment on a post.
**Request:**
```json
{
"body": "Comment content",
"parent_id": null
}
```
**Response:**
```json
{
"success": true,
"comment": {
"id": "uuid",
"body": "Comment content",
"created_at": "2026-02-17T12:00:00Z"
}
}
```
---
## 🔄 Reposts & Amplification
### POST /posts/{id}/repost
Create a repost.
**Request:**
```json
{
"type": "standard",
"comment": "Optional comment for quote repost"
}
```
**Response:**
```json
{
"success": true,
"repost": {
"id": "uuid",
"original_post_id": "uuid",
"author_id": "uuid",
"type": "standard",
"comment": null,
"created_at": "2026-02-17T12:00:00Z"
}
}
```
### POST /posts/{id}/boost
Boost a post for amplification.
**Request:**
```json
{
"boost_type": "amplify",
"boost_amount": 1
}
```
**Response:**
```json
{
"success": true,
"message": "Post boosted successfully"
}
```
### GET /posts/{id}/amplification
Get amplification analytics for a post.
**Response:**
```json
{
"success": true,
"analytics": {
"post_id": "uuid",
"total_amplification": 150,
"amplification_rate": 0.75,
"repost_counts": {
"standard": 10,
"quote": 5,
"boost": 3,
"amplify": 2
},
"metrics": [
{
"total_reach": 1000,
"engagement_count": 75,
"engagement_rate": 0.075,
"new_followers": 5,
"shares": 20,
"comments": 15,
"likes": 40,
"last_updated": "2026-02-17T12:00:00Z"
}
]
}
}
```
---
## 📍 Beacons (Local Safety)
### GET /beacons
Get beacons with geospatial filtering.
**Query Parameters:**
- `lat`: Latitude for center point
- `lng`: Longitude for center point
- `radius_km`: Search radius in kilometers (default: 10)
- `category`: Filter by category
- `status`: Filter by status
- `only_official`: Filter for official sources only
**Response:**
```json
{
"success": true,
"beacons": [
{
"id": "uuid",
"title": "Community Event",
"description": "Description of the beacon",
"category": "event",
"status": "active",
"lat": 37.7749,
"lng": -122.4194,
"author_id": "uuid",
"author_handle": "username",
"is_verified": true,
"is_official_source": true,
"organization_name": "City Hall",
"vouch_count": 25,
"report_count": 0,
"confidence_score": 0.95,
"image_url": "https://cdn.sojorn.app/beacons/uuid.jpg",
"action_items": [
"Volunteer at the event",
"Share with neighbors"
],
"neighborhood": "Downtown",
"created_at": "2026-02-17T12:00:00Z"
}
]
}
```
### POST /beacons
Create a new beacon.
**Request:**
```json
{
"title": "Community Event",
"description": "Description of the beacon",
"category": "event",
"lat": 37.7749,
"lng": -122.4194,
"image_url": "https://cdn.sojorn.app/beacons/uuid.jpg",
"action_items": [
"Volunteer at the event",
"Share with neighbors"
],
"neighborhood": "Downtown"
}
```
**Response:**
```json
{
"success": true,
"beacon": {
"id": "uuid",
"title": "Community Event",
"created_at": "2026-02-17T12:00:00Z"
}
}
```
### POST /beacons/{id}/vouch
Vouch for a beacon (positive interaction).
**Response:**
```json
{
"success": true,
"vouch_count": 26,
"confidence_score": 0.96
}
```
### POST /beacons/{id}/report
Report a beacon (negative interaction).
**Request:**
```json
{
"reason": "inaccurate_information",
"comment": "This information is not accurate"
}
```
**Response:**
```json
{
"success": true,
"report_count": 1,
"confidence_score": 0.90
}
```
---
## 👥 Groups
### GET /groups
Get groups with filtering.
**Query Parameters:**
- `limit`: Number of groups (default: 20)
- `offset`: Pagination offset
- `category`: Filter by category
- `is_private`: Filter by privacy setting
**Response:**
```json
{
"success": true,
"groups": [
{
"id": "uuid",
"name": "Group Name",
"description": "Group description",
"category": "general",
"is_private": false,
"member_count": 150,
"post_count": 500,
"avatar_url": "https://cdn.sojorn.app/groups/uuid.jpg",
"banner_url": "https://cdn.sojorn.app/groups/banner/uuid.jpg",
"created_by": "uuid",
"created_at": "2026-02-17T12:00:00Z",
"is_member": false,
"is_admin": false
}
],
"pagination": {
"total": 100,
"limit": 20,
"offset": 0,
"has_more": true
}
}
```
### POST /groups
Create a new group.
**Request:**
```json
{
"name": "Group Name",
"description": "Group description",
"category": "general",
"is_private": false,
"avatar_url": "https://cdn.sojorn.app/groups/uuid.jpg",
"banner_url": "https://cdn.sojorn.app/groups/banner/uuid.jpg"
}
```
**Response:**
```json
{
"success": true,
"group": {
"id": "uuid",
"name": "Group Name",
"created_at": "2026-02-17T12:00:00Z"
}
}
```
---
## 🔐 E2EE Chat
### POST /e2ee/register-device
Register a device for E2EE chat.
**Request:**
```json
{
"device_name": "iPhone 14",
"device_type": "mobile",
"public_key": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"
}
```
**Response:**
```json
{
"success": true,
"device": {
"id": "device_uuid",
"name": "iPhone 14",
"type": "mobile",
"public_key": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----",
"created_at": "2026-02-17T12:00:00Z"
}
}
```
### POST /e2ee/send-message
Send an encrypted message.
**Request:**
```json
{
"recipient_id": "uuid",
"message": "encrypted_message_here",
"is_encrypted": true
}
```
**Response:**
```json
{
"success": true,
"message": {
"id": "uuid",
"sender_id": "uuid",
"recipient_id": "uuid",
"message": "encrypted_message_here",
"is_encrypted": true,
"created_at": "2026-02-17T12:00:00Z"
}
}
```
### GET /e2ee/messages/{user_id}
Get encrypted messages with a user.
**Response:**
```json
{
"success": true,
"messages": [
{
"id": "uuid",
"sender_id": "uuid",
"recipient_id": "uuid",
"message": "encrypted_message_here",
"is_encrypted": true,
"created_at": "2026-02-17T12:00:00Z"
}
]
}
```
---
## 🎬 Video (Quips)
### POST /videos/upload
Upload and process a video.
**Request (multipart/form-data):**
```
video: [video file]
thumbnail: [thumbnail file]
title: "Video Title"
description: "Video description"
duration: 30
```
**Response:**
```json
{
"success": true,
"video": {
"id": "uuid",
"url": "https://cdn.sojorn.app/videos/uuid.mp4",
"thumbnail_url": "https://cdn.sojorn.app/thumbnails/uuid.jpg",
"title": "Video Title",
"description": "Video description",
"duration": 30,
"created_at": "2026-02-17T12:00:00Z"
}
}
```
### POST /videos/process
Process video with effects.
**Request:**
```json
{
"video_id": "uuid",
"filter": "vintage",
"speed": 1.5,
"text_overlays": [
{
"text": "Hello World",
"x": 100,
"y": 100,
"start_time": 5,
"end_time": 10
}
],
"audio_track": {
"url": "https://cdn.sojorn.app/audio/uuid.mp3",
"volume": 0.5,
"fade_in": true,
"fade_out": true
}
}
```
**Response:**
```json
{
"success": true,
"processed_video": {
"url": "https://cdn.sojorn.app/videos/processed/uuid.mp4",
"processing_time": 15.5
}
}
```
---
## 🤖 AI Moderation
### POST /moderation/analyze
Analyze content for moderation.
**Request:**
```json
{
"content": "Content to analyze",
"type": "text",
"image_url": "https://cdn.sojorn.app/images/uuid.jpg",
"video_url": "https://cdn.sojorn.app/videos/uuid.mp4"
}
```
**Response:**
```json
{
"success": true,
"analysis": {
"is_safe": true,
"score": 0.95,
"categories": {
"hate": 0.1,
"greed": 0.05,
"delusion": 0.02
},
"recommendation": "approve",
"confidence": 0.98
}
}
```
---
## 🚫 Blocking System
### GET /users/me/blocked
Get blocked users list.
**Response:**
```json
{
"success": true,
"blocked_users": [
{
"id": "uuid",
"handle": "blocked_user",
"display_name": "Blocked User",
"blocked_at": "2026-02-17T12:00:00Z"
}
],
"total": 5
}
```
### POST /users/{id}/block
Block a user.
**Response:**
```json
{
"success": true,
"message": "User blocked successfully"
}
```
### DELETE /users/{id}/block
Unblock a user.
**Response:**
```json
{
"success": true,
"message": "User unblocked successfully"
}
```
### POST /users/me/blocked/import
Import blocked users from other platforms.
**Request:**
```json
{
"platform": "twitter",
"data": "username1,username2,username3"
}
```
**Response:**
```json
{
"success": true,
"imported": 3,
"skipped": 0,
"failed": 0
}
```
---
## 📊 Analytics & Metrics
### GET /analytics/feed
Get feed analytics.
**Query Parameters:**
- `date_range`: 7d, 30d, 90d
- `category`: Filter by category
**Response:**
```json
{
"success": true,
"analytics": {
"total_posts": 1000,
"total_engagement": 5000,
"engagement_rate": 0.05,
"top_categories": [
{"category": "general", "count": 400},
{"category": "hobby", "count": 300}
],
"daily_stats": [
{
"date": "2026-02-17",
"posts": 50,
"engagement": 250
}
]
}
}
```
---
## 🔍 Search
### GET /search
Search across the platform.
**Query Parameters:**
- `q`: Search query
- `type`: posts, users, groups, beacons
- `limit`: Number of results (default: 20)
- `offset`: Pagination offset
**Response:**
```json
{
"success": true,
"results": {
"posts": [
{
"id": "uuid",
"body": "Post containing search term",
"author_handle": "username",
"created_at": "2026-02-17T12:00:00Z"
}
],
"users": [
{
"id": "uuid",
"handle": "username",
"display_name": "Display Name",
"bio": "Bio containing search term"
}
],
"groups": [
{
"id": "uuid",
"name": "Group Name",
"description": "Description containing search term"
}
],
"beacons": [
{
"id": "uuid",
"title": "Beacon Title",
"description": "Description containing search term"
}
]
}
}
```
---
## 📱 Notifications
### GET /notifications
Get user notifications.
**Query Parameters:**
- `limit`: Number of notifications (default: 50)
- `offset`: Pagination offset
- `type`: Filter by notification type
- `unread_only`: Filter for unread only
**Response:**
```json
{
"success": true,
"notifications": [
{
"id": "uuid",
"type": "like",
"title": "New Like",
"body": "username liked your post",
"data": {
"post_id": "uuid",
"user_id": "uuid"
},
"is_read": false,
"created_at": "2026-02-17T12:00:00Z"
}
],
"unread_count": 5,
"pagination": {
"total": 100,
"limit": 50,
"offset": 0,
"has_more": true
}
}
```
### POST /notifications/{id}/read
Mark notification as read.
**Response:**
```json
{
"success": true,
"message": "Notification marked as read"
}
```
---
## ⚙️ Settings & Preferences
### GET /users/me/settings
Get user settings.
**Response:**
```json
{
"success": true,
"settings": {
"notifications": {
"push_enabled": true,
"email_enabled": true,
"likes": true,
"comments": true,
"follows": true,
"mentions": true
},
"privacy": {
"profile_visibility": "public",
"show_online_status": true,
"allow_tagging": true,
"nsfw_blur_enabled": true
},
"feed": {
"algorithm_enabled": true,
"show_suggested_posts": true,
"hide_sensitive_content": true
}
}
}
```
### PUT /users/me/settings
Update user settings.
**Request:**
```json
{
"notifications": {
"push_enabled": true,
"email_enabled": false,
"likes": true,
"comments": false,
"follows": true,
"mentions": true
},
"privacy": {
"profile_visibility": "public",
"show_online_status": false,
"allow_tagging": true,
"nsfw_blur_enabled": true
}
}
```
**Response:**
```json
{
"success": true,
"settings": {
"notifications": {
"push_enabled": true,
"email_enabled": false,
"likes": true,
"comments": false,
"follows": true,
"mentions": true
},
"privacy": {
"profile_visibility": "public",
"show_online_status": false,
"allow_tagging": true,
"nsfw_blur_enabled": true
}
}
}
```
---
## 🏥 Health & Monitoring
### GET /health
System health check.
**Response:**
```json
{
"status": "healthy",
"timestamp": "2026-02-17T12:00:00Z",
"uptime": "72h30m15s",
"version": "3.0.0",
"environment": "production",
"checks": {
"database": {
"status": "healthy",
"message": "Database connection successful",
"duration": "5ms"
},
"redis": {
"status": "healthy",
"message": "Redis connection successful",
"duration": "2ms"
},
"storage": {
"status": "healthy",
"message": "Cloudflare R2 accessible",
"duration": "150ms"
}
}
}
```
### GET /metrics
Application metrics.
**Response:**
```json
{
"success": true,
"metrics": {
"requests": {
"total": 1000000,
"per_second": 50,
"error_rate": 0.01
},
"database": {
"connections": 25,
"queries_per_second": 100,
"avg_response_time": "25ms"
},
"memory": {
"used_mb": 512,
"available_mb": 1536,
"usage_percent": 25
},
"cpu": {
"usage_percent": 15,
"load_average": [0.5, 0.6, 0.7]
}
}
}
```
---
## 📚 Error Responses
All endpoints return consistent error responses:
```json
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input data",
"details": {
"field": "email",
"issue": "Invalid email format"
}
}
}
```
### Common Error Codes
- `UNAUTHORIZED`: Authentication required or invalid
- `FORBIDDEN`: Insufficient permissions
- `NOT_FOUND`: Resource not found
- `VALIDATION_ERROR`: Invalid input data
- `RATE_LIMITED`: Too many requests
- `INTERNAL_ERROR`: Server error
- `SERVICE_UNAVAILABLE`: Service temporarily unavailable
---
## 📝 Rate Limiting
API endpoints are rate limited to prevent abuse:
- **Authentication**: 5 requests per minute
- **Content Creation**: 10 requests per minute
- **Search**: 30 requests per minute
- **General**: 100 requests per minute
Rate limit headers are included in responses:
```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1645123200
```
---
## 🔑 API Keys
For service-to-service integration, generate API keys in the admin panel:
```bash
# Example API key usage
curl -H "X-API-Key: your-api-key-here" \
-H "Content-Type: application/json" \
https://api.sojorn.app/posts
```
---
## 📞 Support
### Documentation
- **API Reference**: Complete endpoint documentation
- **SDKs**: Official SDKs for popular languages
- **Examples**: Code examples and tutorials
- **Changelog**: API version history and changes
### Support Channels
- **Discord**: API development discussion
- **GitHub**: Issue tracking and feature requests
- **Email**: api-support@sojorn.app
- **Status**: api.sojorn.app/status
---
**🚀 The Sojorn API provides comprehensive, production-ready endpoints for all platform features with proper authentication, rate limiting, and error handling.**