# 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 ` - **API Key**: `X-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 ``` **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.**