Welcome to the BackWood API documentation. This guide will help you integrate with our backend services.
All API endpoints follow a consistent error handling pattern:
{
"status": "error" | "fail",
"message": "Human readable error message",
"errors": [
// Optional array of specific error details
],
"stack": "Stack trace (development only)"
}
// API error handling utility
const handleApiError = (error) => {
if (error.response) {
// Server responded with error
const { status, data } = error.response;
switch (status) {
case 401:
// Handle authentication error
navigation.navigate('Login');
break;
case 403:
Alert.alert('Access Denied', data.message);
break;
case 422:
// Handle validation errors
const errors = data.errors?.join('\n');
Alert.alert('Validation Error', errors || data.message);
break;
default:
Alert.alert('Error', data.message || 'Something went wrong');
}
} else if (error.request) {
// Network error
Alert.alert('Network Error', 'Please check your internet connection');
} else {
// Other errors
Alert.alert('Error', error.message || 'Something went wrong');
}
};
All authenticated endpoints require a Bearer token in the Authorization header.
Register a new user account and sends welcome email with verification code.
{
"email": "user@example.com",
"password": "StrongPass1!",
"firstName": "John",
"lastName": "Doe",
"phone": "+1234567890"
}
{
"message": "User created successfully. Please verify your email.",
"token": "jwt_token",
"user": {
"id": "user_id",
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe",
"phone": "+1234567890",
"status": "PENDING",
"emailVerified": false,
"phoneVerified": false,
"kycVerified": false
}
}
Login to get authentication token.
{
"email": "user@example.com",
"password": "StrongPass1!"
}
Invalidate current token.
// React Native Example
const logout = async () => {
try {
await axios.post('/api/auth/logout', {}, {
headers: { Authorization: `Bearer ${token}` }
});
// Clear local storage
await AsyncStorage.removeItem('token');
navigation.replace('Login');
} catch (error) {
handleApiError(error);
}
};
Email verification system with templated emails.
Send a verification code to user's email.
{
"userId": "user_id",
"type": "EMAIL"
}
{
"message": "Verification code sent to your email"
}
Verify email using received code.
{
"userId": "user_id",
"type": "EMAIL",
"code": "123456"
}
{
"message": "Email verified successfully"
}
Available email templates:
{
"firstName": "User's first name",
"verificationCode": "6-digit code",
"appName": "Application name from env",
"year": "Current year"
}
Send a message to another user, optionally about a specific listing.
{
"receiverId": "user_id",
"content": "Hello, is this item still available?",
"conversationId": "optional_conversation_id",
"listingId": "optional_listing_id"
}
{
"status": "success",
"message": {
"id": "message_id",
"content": "Hello, is this item still available?",
"sender": {
"id": "sender_id",
"firstName": "John",
"lastName": "Doe",
"profileImage": "url"
},
"listing": {
"id": "listing_id",
"title": "Item Title",
"price": 100
},
"createdAt": "2024-01-01T00:00:00Z",
"read": false
}
}
Get conversation history with another user.
// React Native Example
const fetchConversation = async (userId) => {
try {
const response = await axios.get(`/api/messages/conversation/${userId}`, {
headers: { Authorization: `Bearer ${token}` },
params: {
page: currentPage,
limit: 20
}
});
setMessages(response.data.messages);
setPagination(response.data.pagination);
} catch (error) {
handleApiError(error);
}
};
Get number of unread messages.
// React Native Example with WebSocket
useEffect(() => {
// Initial fetch
fetchUnreadCount();
// Listen for new messages
socket.on('newMessage', () => {
fetchUnreadCount();
});
return () => socket.off('newMessage');
}, []);
Get all conversations for the authenticated user
{
"status": "success",
"conversations": [
{
"id": "conversation_id",
"otherUser": {
"id": "user_id",
"firstName": "John",
"lastName": "Doe",
"profileImage": "url"
},
"lastMessage": {
"content": "Hello there!",
"createdAt": "2024-01-01T00:00:00Z",
"read": false
},
"lastMessageTime": "2024-01-01T00:00:00Z"
}
],
"pagination": {
"total": 10,
"pages": 1,
"currentPage": 1,
"limit": 20
}
}
When sending messages, you can include an existing conversationId:
{
"receiverId": "user_id",
"content": "Hello there!",
"conversationId": "existing_conversation_id"
}
// Initialize socket with conversation
socket.on('connect', () => {
// Join conversation room
socket.emit('joinConversation', conversationId);
});
// Send message with conversation
socket.emit('message', {
receiverId: otherUserId,
content: messageText,
conversationId: currentConversationId
});
// Listen for messages in conversation
socket.on('message:conversation', (message) => {
if (message.conversationId === currentConversationId) {
// Update conversation messages
setMessages(prev => [...prev, message]);
}
});
Admin login with enhanced security.
{
"email": "admin@example.com",
"password": "AdminPass1!",
"totpCode": "123456" // If 2FA enabled
}
Get all users with filtering and pagination.
// React Native Admin Panel Example
const fetchUsers = async () => {
try {
const response = await axios.get('/api/admin/users', {
headers: { Authorization: `Bearer ${adminToken}` },
params: {
status: filterStatus,
role: filterRole,
search: searchQuery,
page: currentPage,
limit: 20
}
});
setUsers(response.data.users);
setPagination(response.data.pagination);
} catch (error) {
handleApiError(error);
}
};
Update user status or role.
{
"status": "ACTIVE" | "SUSPENDED" | "BANNED",
"role": "USER" | "MODERATOR" | "ADMIN"
}
// React Native WebSocket Setup
import { io } from 'socket.io-client';
const setupWebSocket = (token) => {
const socket = io('YOUR_WEBSOCKET_URL', {
auth: { token }
});
socket.on('connect', () => {
console.log('Connected to WebSocket');
});
socket.on('newMessage', (message) => {
// Update messages in real-time
setMessages(prev => [...prev, message]);
// Show notification
showNotification(message);
});
socket.on('messageRead', ({ messageId }) => {
// Update message read status
setMessages(prev => prev.map(msg =>
msg.id === messageId ? {...msg, read: true} : msg
));
});
return socket;
};
newMessage - Received when a new message arrivesmessageRead - When messages are marked as readuserOnline - When a user comes onlineuserOffline - When a user goes offlinetyping - When someone is typing// api/client.js
import axios from 'axios';
import AsyncStorage from '@react-native-async-storage/async-storage';
const api = axios.create({
baseURL: 'YOUR_API_URL',
timeout: 10000,
headers: {
'Content-Type': 'application/json'
}
});
// Add token to requests
api.interceptors.request.use(async (config) => {
const token = await AsyncStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// Handle token expiration
api.interceptors.response.use(
(response) => response,
async (error) => {
if (error.response?.status === 401) {
await AsyncStorage.removeItem('token');
// Navigate to login
navigation.replace('Login');
}
return Promise.reject(error);
}
);
// hooks/useMessages.js
export const useMessages = (conversationId) => {
const [messages, setMessages] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchMessages = async () => {
try {
setLoading(true);
const response = await api.get(
`/messages/conversation/${conversationId}`
);
setMessages(response.data.messages);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
};
fetchMessages();
}, [conversationId]);
const sendMessage = async (content) => {
try {
const response = await api.post('/messages/send', {
receiverId: conversationId,
content
});
setMessages(prev => [...prev, response.data.message]);
return response.data.message;
} catch (err) {
setError(err);
throw err;
}
};
return { messages, loading, error, sendMessage };
};
Manage user profiles and settings.
Get current user's profile
{
"user": {
"id": "user_id",
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe",
"phone": "+1234567890",
"avatar": "url_to_avatar",
"status": "ACTIVE",
"emailVerified": true,
"phoneVerified": true,
"kycVerified": false,
"createdAt": "2024-01-01T00:00:00Z",
"lastLogin": "2024-01-01T00:00:00Z"
}
}
Update user profile
{
"firstName": "John",
"lastName": "Doe",
"phone": "+1234567890",
"avatar": "base64_image_data"
}
Manage product listings and searches.
Create a new listing
{
"title": "Product Title",
"description": "Detailed description",
"price": 99.99,
"category": "ELECTRONICS",
"condition": "NEW",
"images": ["base64_image_1", "base64_image_2"],
"location": {
"latitude": 123.456,
"longitude": 789.012
},
"tags": ["tag1", "tag2"]
}
Search listings with filters
search - Search termcategory - Filter by categoryminPrice - Minimum pricemaxPrice - Maximum pricecondition - Item conditionradius - Search radius in kmlat - Latitude for location-based searchlng - Longitude for location-based searchpage - Page number (default: 1)limit - Items per page (default: 20)Real-time messaging system using WebSocket.
// Connect to WebSocket
const socket = io(WEBSOCKET_URL, {
auth: { token: userToken }
});
// Listen for new messages
socket.on('newMessage', (message) => {
console.log('New message:', message);
});
// Send a message
socket.emit('sendMessage', {
recipientId: 'user_id',
content: 'Message content',
listingId: 'listing_id' // Optional, for listing-related messages
});
Manage buying and selling offers for listings.
Make an offer on a listing
{
"listingId": "listing_id",
"amount": 95.50,
"message": "Is this still available? I'm interested.",
"type": "BUY"
}
{
"id": "offer_id",
"status": "PENDING",
"createdAt": "2024-01-01T00:00:00Z",
"amount": 95.50,
"message": "Is this still available? I'm interested."
}
Update offer status (accept/reject)
{
"status": "ACCEPTED" | "REJECTED",
"message": "Optional response message"
}
User review and rating system.
Create a review for a user after successful transaction
{
"userId": "user_id",
"rating": 5,
"comment": "Great buyer! Quick payment and good communication.",
"transactionId": "transaction_id"
}
Get reviews for a specific user
page - Page number (default: 1)limit - Reviews per page (default: 10)sort - Sort order (recent/rating)Know Your Customer verification system.
Submit KYC verification documents
{
"documentType": "ID_CARD" | "PASSPORT" | "DRIVERS_LICENSE",
"idImageUrl": "url_to_id_image",
"selfieImageUrl": "url_to_selfie_image"
}
Check KYC verification status
{
"status": "PENDING" | "VERIFIED" | "REJECTED",
"message": "Optional status message",
"submittedAt": "2024-01-01T00:00:00Z",
"verifiedAt": "2024-01-02T00:00:00Z"
}
Guidelines and endpoints for image handling.
Upload images for listings or KYC
{
"image": "base64_encoded_image",
"type": "LISTING" | "KYC_ID" | "KYC_SELFIE",
"metadata": {
"width": 1024,
"height": 768,
"size": 1048576
}
}
Browse and manage listing categories.
Get all available categories
{
"status": "success",
"categories": [
{
"id": "category_id",
"name": "Real Estate",
"slug": "real-estate",
"description": "Properties for rent and sale"
},
{
"name": "Vehicles",
"slug": "vehicles",
"description": "Cars, motorcycles, and other vehicles"
}
]
}
Get listings by category
page - Page number (default: 1)limit - Listings per page (default: 20)sort - Sort order (recent/price)