17 KiB
Looking API Reference
Complete REST API documentation for the Looking backend
This document provides detailed information about all API endpoints, including request/response formats, authentication requirements, and error codes.
📋 Table of Contents
- Base URL
- Authentication
- Common Response Codes
- Authentication Endpoints
- Profile Endpoints
- User Endpoints
- Geocache Endpoints
- Error Handling
🌐 Base URL
Development: http://localhost:3069
Production: https://api.pfosi.mifi.dev
All endpoints are prefixed with the base URL.
🔐 Authentication
Most endpoints require JWT authentication via the Authorization header.
Header Format
Authorization: Bearer <jwt_token>
Permission Levels
| Permission | Description |
|---|---|
| view | Read-only access to profiles |
| add | Create new profiles |
| edit | Modify existing profiles |
| update | Update profile details |
| delete | Remove profiles |
| manage | Approve submissions, manage content |
| super | Full admin access, user management |
Obtaining a Token
Use the /auth/login endpoint (see Authentication Endpoints).
📊 Common Response Codes
| Code | Status | Description |
|---|---|---|
| 200 | OK | Request successful |
| 201 | Created | Resource created successfully |
| 400 | Bad Request | Invalid request data |
| 401 | Unauthorized | Missing or invalid token |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource not found |
| 500 | Internal Server Error | Server error |
🔑 Authentication Endpoints
POST /auth/login
Authenticate user and receive JWT token.
Request:
POST /auth/login
Content-Type: application/json
{
"username": "admin",
"password": "password123"
}
Success Response (200):
{
"status": 200,
"authorized": true,
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "507f1f77bcf86cd799439011",
"username": "admin",
"name": {
"first": "John",
"last": "Doe"
},
"email": "admin@example.com",
"can": ["add", "edit", "delete", "manage", "super", "update", "view"]
}
}
Failure Response (401):
{
"status": 401,
"authorized": false,
"message": "Invalid username or password"
}
POST /auth/logout
Logout user (client-side token removal, no server-side action needed).
Request:
POST /auth/logout
Authorization: Bearer <token>
Response (200):
{
"message": "Logged out successfully"
}
GET /auth/session
Validate existing JWT token and get user info.
Request:
GET /auth/session
Authorization: Bearer <token>
Success Response (200):
{
"valid": true,
"decoded": {
"uid": "507f1f77bcf86cd799439011",
"username": "admin",
"can": ["add", "edit", "delete", "manage", "super", "update", "view"],
"iat": 1640000000,
"exp": 1640003600
}
}
Failure Response (401):
{
"valid": false,
"message": "Token expired or invalid"
}
POST /auth/session
Create anonymous session token (limited permissions).
Request:
POST /auth/session
Response (200):
{
"status": 200,
"authorized": false,
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
PUT /auth/session
Refresh existing JWT token (extend expiration).
Request:
PUT /auth/session
Authorization: Bearer <token>
Response (200):
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": "15m"
}
POST /auth/reset
Request password reset email.
Request:
POST /auth/reset
Content-Type: application/json
{
"username": "admin"
}
Response (200):
{
"message": "Password reset email sent",
"email": "ad***@example.com"
}
GET /auth/reset/:id/:token
Verify password reset token validity.
Request:
GET /auth/reset/507f1f77bcf86cd799439011/abc123def456
Response (200):
{
"valid": true,
"userId": "507f1f77bcf86cd799439011",
"expires": "2024-01-15T12:00:00Z"
}
PUT /auth/reset/:id/:token
Reset password with valid token.
Request:
PUT /auth/reset/507f1f77bcf86cd799439011/abc123def456
Content-Type: application/json
{
"password": "newPassword123",
"confirmPassword": "newPassword123"
}
Response (200):
{
"message": "Password updated successfully",
"success": true
}
👤 Profile Endpoints
GET /profiles
Get all approved profiles.
Request:
GET /profiles
Response (200):
[
{
"_id": "507f1f77bcf86cd799439011",
"order": 1,
"details": {
"name": "John",
"age": 28,
"location": "San Francisco, CA",
"about": "User's story about dating...",
"pic": {
"thumb": "profile/john_thumbnail.png",
"detail": "profile/john_detail.png"
},
"position": ["Top", "Versatile"],
"looking": ["Dates", "Friends"],
"tribes": ["Geek", "Jock"],
"ethnos": ["White", "Latino"]
},
"messages": [
{
"_id": "507f191e810c19729de860ea",
"text": "What brought you to dating apps?",
"isUser": false,
"timestamp": "2024-01-15T10:30:00Z"
},
{
"_id": "507f191e810c19729de860eb",
"text": "I moved to a new city...",
"isUser": true,
"timestamp": "2024-01-15T10:32:00Z"
}
],
"submitted": true,
"approved": true
}
]
GET /profiles/submitted
Get all submitted (pending approval) profiles.
Authentication: Required (view permission)
Request:
GET /profiles/submitted
Authorization: Bearer <token>
Response (200):
[
{
"_id": "507f1f77bcf86cd799439012",
"details": { ... },
"submitted": true,
"approved": false
}
]
GET /profiles/verified
Alias for approved profiles.
Request:
GET /profiles/verified
Response: Same as GET /profiles
GET /profiles/:id
Get single profile by ID.
Request:
GET /profiles/507f1f77bcf86cd799439011
Response (200):
{
"_id": "507f1f77bcf86cd799439011",
"order": 1,
"details": { ... },
"messages": [ ... ],
"submitted": true,
"approved": true
}
Error (404):
{
"message": "Profile not found"
}
POST /profiles
Create new profile.
Authentication: Required (add permission)
Request:
POST /profiles
Authorization: Bearer <token>
Content-Type: application/json
{
"order": 10,
"details": {
"name": "Alex",
"age": 25,
"location": "New York, NY",
"about": "My story...",
"pic": {
"thumb": "data:image/png;base64,iVBORw0KG...", // Base64 or path
"detail": "data:image/png;base64,iVBORw0KG..."
}
},
"messages": [
{
"text": "Question text",
"isUser": false
}
],
"submitted": true,
"approved": false
}
Response (201):
{
"_id": "507f1f77bcf86cd799439013",
"message": "Profile created successfully",
"profile": { ... }
}
PUT /profiles/:id
Update existing profile.
Authentication: Required (update permission)
Request:
PUT /profiles/507f1f77bcf86cd799439011
Authorization: Bearer <token>
Content-Type: application/json
{
"details": {
"about": "Updated story..."
}
}
Response (200):
{
"message": "Profile updated successfully",
"profile": { ... }
}
DELETE /profiles/:id
Delete profile by ID.
Authentication: Required (delete permission)
Request:
DELETE /profiles/507f1f77bcf86cd799439011
Authorization: Bearer <token>
Response (200):
{
"message": "Profile deleted successfully",
"id": "507f1f77bcf86cd799439011"
}
GET /profiles/approve/:id
Approve submitted profile.
Authentication: Required (manage permission)
Request:
GET /profiles/approve/507f1f77bcf86cd799439012
Authorization: Bearer <token>
Response (200):
{
"message": "Profile approved",
"profile": {
"_id": "507f1f77bcf86cd799439012",
"approved": true
}
}
POST /profiles/submission
Submit new profile (public endpoint, no auth required).
Request:
POST /profiles/submission
Content-Type: application/json
{
"details": {
"name": "Anonymous",
"age": 30,
"location": "Los Angeles, CA",
"about": "My dating story...",
"pic": {
"thumb": "data:image/png;base64,...",
"detail": "data:image/png;base64,..."
}
},
"messages": [
{
"text": "Tell us your story",
"isUser": false
},
{
"text": "I've been using apps for 3 years...",
"isUser": true
}
]
}
Response (200):
{
"message": "Story submitted successfully. It will be reviewed before publishing.",
"profile": {
"_id": "507f1f77bcf86cd799439014",
"submitted": true,
"approved": false
}
}
GET /profiles/find/:limit?/:skip?/:min?/:max?/:pos?/:lkng?/:tribes?/:ethnos?
Advanced profile search with filters.
Authentication: Required (view permission)
Parameters:
limit- Number of results (default: all)skip- Number to skip for paginationmin- Minimum agemax- Maximum agepos- Position filter (pipe-separated: "Top|Bottom|Versatile")lkng- Looking for filter (pipe-separated: "Dates|Friends|Relationship")tribes- Tribes filter (pipe-separated: "Geek|Jock|Bear|Otter")ethnos- Ethnicity filter (pipe-separated: "White|Black|Latino|Asian")
Request:
GET /profiles/find/10/0/25/35/Top|Versatile/Dates|Friends/Geek/null
Authorization: Bearer <token>
Response (200):
[
{
"_id": "507f1f77bcf86cd799439011",
"details": {
"age": 28,
"position": ["Top", "Versatile"],
"looking": ["Dates", "Friends"],
"tribes": ["Geek"]
}
}
]
GET /profiles/list/:limit?/:skip?/:min?/:max?/:pos?/:lkng?/:tribes?/:ethnos?
List profiles with minimal data (name, thumbnail only).
Authentication: Required (view permission)
Response (200):
[
{
"_id": "507f1f77bcf86cd799439011",
"order": 1,
"details": {
"name": "John",
"pic": {
"thumb": "profile/john_thumbnail.png"
}
}
}
]
PUT /profiles/:profileId/message/:messageId
Update specific message in profile thread.
Authentication: Required (update permission)
Request:
PUT /profiles/507f1f77bcf86cd799439011/message/507f191e810c19729de860ea
Authorization: Bearer <token>
Content-Type: application/json
{
"text": "Updated question text",
"image": "data:image/png;base64,..."
}
Response (200):
{
"message": "Message updated successfully",
"profile": { ... }
}
👥 User Endpoints
GET /users
Get all users.
Authentication: Required (super permission)
Request:
GET /users
Authorization: Bearer <token>
Response (200):
[
{
"_id": "507f1f77bcf86cd799439011",
"username": "admin",
"name": {
"first": "John",
"last": "Doe"
},
"email": "admin@example.com",
"can": ["add", "edit", "delete", "manage", "super", "update", "view"],
"forceReset": false
}
]
GET /users/:id
Get user by ID.
Authentication: Required (super permission)
Response (200):
{
"_id": "507f1f77bcf86cd799439011",
"username": "admin",
"name": { "first": "John", "last": "Doe" },
"email": "admin@example.com",
"can": ["super"]
}
POST /users
Create new user.
Authentication: Required (super permission)
Request:
POST /users
Authorization: Bearer <token>
Content-Type: application/json
{
"username": "newuser",
"password": "password123",
"confirmPassword": "password123",
"name": {
"first": "Jane",
"last": "Smith"
},
"email": "jane@example.com",
"can": ["view", "add"]
}
Response (201):
{
"message": "User created successfully",
"user": {
"_id": "507f1f77bcf86cd799439015",
"username": "newuser"
}
}
PUT /users/:id
Update user information.
Authentication: Required (super permission or own user)
Request:
PUT /users/507f1f77bcf86cd799439011
Authorization: Bearer <token>
Content-Type: application/json
{
"name": {
"first": "John",
"last": "Updated"
},
"email": "newemail@example.com",
"password": "newPassword123",
"confirmPassword": "newPassword123",
"currentPassword": "oldPassword123"
}
Response (200):
{
"message": "User updated successfully",
"user": { ... }
}
DELETE /users/:id
Delete user.
Authentication: Required (super permission)
Request:
DELETE /users/507f1f77bcf86cd799439011
Authorization: Bearer <token>
Response (200):
{
"message": "User deleted successfully"
}
🗺️ Geocache Endpoints
GET /geocache/populate/:field
Populate geocache for a specific field (e.g., location).
Authentication: Required (manageAppPreferences permission)
Request:
GET /geocache/populate/location
Authorization: Bearer <token>
Response (200):
{
"message": "Geocache populated",
"count": 42,
"results": [
{
"key": "San Francisco, CA",
"formatted": "San Francisco, California, USA",
"loc": {
"type": "Point",
"coordinates": [-122.4194, 37.7749]
}
}
]
}
PUT /geocache/:id
Update geocache entry.
Authentication: Required (manageAppPreferences permission)
Request:
PUT /geocache/507f1f77bcf86cd799439011
Authorization: Bearer <token>
Content-Type: application/json
{
"key": "New York, NY",
"formatted": "New York, New York, USA",
"loc": {
"type": "Point",
"coordinates": [-74.0060, 40.7128]
}
}
Response (200):
{
"message": "Geocache updated",
"geocache": { ... }
}
⚠️ Error Handling
Error Response Format
All errors follow this structure:
{
"message": "Human-readable error message",
"err": {
"code": "ERROR_CODE",
"details": "Additional error information"
}
}
Common Error Messages
| Error | Code | Cause |
|---|---|---|
| User not authorized to perform this action | 403 | Missing required permission |
| Token expired or invalid | 401 | JWT validation failed |
| Profile not found | 404 | Invalid profile ID |
| Invalid username or password | 401 | Login failed |
| Could not update profile | 500 | Database error during update |
| There was an error processing the image | 500 | Image upload/processing failed |
| No profile id or data specified | 500 | Missing required request data |
Authentication Errors
Missing Token:
{
"message": "No authorization token provided",
"err": null
}
Invalid Token:
{
"message": "User not authorized to perform this action",
"err": {
"name": "JsonWebTokenError",
"message": "invalid signature"
}
}
Expired Token:
{
"message": "User not authorized to perform this action",
"err": {
"name": "TokenExpiredError",
"message": "jwt expired",
"expiredAt": "2024-01-15T12:00:00Z"
}
}
Validation Errors
Password Mismatch:
{
"success": false,
"message": "There was an error saving the updated password."
}
Duplicate Username:
{
"message": "There was a duplicate key error",
"err": {
"code": 11000,
"keyPattern": { "username": 1 }
}
}
📚 Related Documentation
- Backend README - Server setup and development
- Database Schema - MongoDB collection schemas
- Environment Variables - Configuration
- Root README - Project overview
- Deployment Guide - Production deployment
Need Help? Check the backend troubleshooting section for common API issues.