API Reference
REST API endpoints for Talbino MVP. Base URL: https://api.talbino.com/api/v1
Authentication
All endpoints except auth endpoints require JWT token in header:
Authorization: Bearer `{jwt_token}`
Standard Response Format
Success Response
{
"success": true,
"data": { ... },
"message": "Operation successful"
}
Error Response
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": {
"phone_number": ["Phone number is required"]
}
}
}
HTTP Status Codes
200OK - Success201Created - Resource created400Bad Request - Validation error401Unauthorized - Missing/invalid token403Forbidden - Insufficient permissions404Not Found - Resource not found422Unprocessable Entity - Business logic error429Too Many Requests - Rate limit exceeded500Internal Server Error - Server error
Authentication Endpoints
POST /auth/request-otp
Request OTP code for phone number.
Request:
{
"phone_number": "+201234567890"
}
Response: 200 OK
{
"success": true,
"data": {
"expires_at": "2026-02-26T22:40:00Z",
"message": "OTP sent to +201234567890"
}
}
Errors:
429- Too many OTP requests (max 3 per 10 minutes)400- Invalid phone number format
Rate Limit: 3 requests per 10 minutes per phone number
POST /auth/verify-otp
Verify OTP and get JWT tokens.
Request:
{
"phone_number": "+201234567890",
"otp_code": "123456"
}
Response: 200 OK
{
"success": true,
"data": {
"user": {
"id": "uuid",
"phone_number": "+201234567890",
"name": null,
"avatar_url": null,
"language": "ar",
"is_admin": false,
"has_seller_profile": false,
"created_at": "2026-02-26T22:30:00Z"
},
"tokens": {
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"expires_in": 86400
}
}
}
Errors:
401- Invalid OTP code401- OTP expired401- Too many attempts (max 3)
POST /auth/refresh
Refresh access token using refresh token.
Request:
{
"refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGc..."
}
Response: 200 OK
{
"success": true,
"data": {
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"expires_in": 86400
}
}
POST /auth/logout
Logout and invalidate tokens.
Headers: Authorization: Bearer {token}
Request:
{
"device_token": "fcm_token_here"
}
Response: 200 OK
{
"success": true,
"message": "Logged out successfully"
}
User Endpoints
GET /users/me
Get current user profile.
Headers: Authorization: Bearer {token}
Response: 200 OK
{
"success": true,
"data": {
"id": "uuid",
"phone_number": "+201234567890",
"name": "محمد أحمد",
"avatar_url": "https://s3.../avatar.jpg",
"language": "ar",
"is_admin": false,
"seller_profile": {
"id": "uuid",
"status": "approved",
"business_name": "Ahmed's Electronics",
"location_district": "Nasr City",
"rating_avg": 4.5,
"rating_count": 23
},
"created_at": "2026-02-26T22:30:00Z"
}
}
PUT /users/me
Update current user profile.
Headers: Authorization: Bearer {token}
Request:
{
"name": "محمد أحمد",
"language": "ar"
}
Response: 200 OK
{
"success": true,
"data": { ... }
}
POST /users/me/avatar
Upload user avatar.
Headers:
Authorization: Bearer {token}Content-Type: multipart/form-data
Request:
avatar: [file]
Response: 200 OK
{
"success": true,
"data": {
"avatar_url": "https://s3.../avatar.jpg"
}
}
POST /device-tokens
Register device token for push notifications.
Headers: Authorization: Bearer {token}
Request:
{
"platform": "ios",
"push_token": "fcm_token_here"
}
Response: 201 Created
{
"success": true,
"data": {
"id": "uuid",
"platform": "ios",
"created_at": "2026-02-26T22:30:00Z"
}
}
Buy Request Endpoints
POST /requests
Create a new buy request.
Headers: Authorization: Bearer {token}
Request:
{
"category": "phone",
"product_brand": "Apple",
"product_model": "iPhone 13",
"condition_pref": "like_new",
"budget_min": 8000,
"budget_max": 10000,
"location_district": "Nasr City",
"location_city": "Cairo",
"notes": "Prefer 128GB, any color"
}
Response: 201 Created
{
"success": true,
"data": {
"id": "uuid",
"buyer_id": "uuid",
"category": "phone",
"product_brand": "Apple",
"product_model": "iPhone 13",
"condition_pref": "like_new",
"budget_min": 8000,
"budget_max": 10000,
"location_district": "Nasr City",
"location_city": "Cairo",
"notes": "Prefer 128GB, any color",
"status": "active",
"offer_count": 0,
"created_at": "2026-02-26T22:30:00Z"
}
}
Validation:
category: Required, enum (phone, accessory)budget_min: Required, numeric, > 0budget_max: Required, numeric, >= budget_minlocation_district: Required
GET /requests
List buy requests (for sellers to browse).
Headers: Authorization: Bearer {token}
Query Parameters:
category(optional): Filter by categorylocation_city(optional): Filter by citystatus(optional): Filter by status (default: active)page(optional): Page number (default: 1)per_page(optional): Items per page (default: 20, max: 50)
Response: 200 OK
{
"success": true,
"data": {
"requests": [
{
"id": "uuid",
"category": "phone",
"product_brand": "Apple",
"product_model": "iPhone 13",
"condition_pref": "like_new",
"budget_min": 8000,
"budget_max": 10000,
"location_district": "Nasr City",
"status": "active",
"offer_count": 3,
"created_at": "2026-02-26T22:30:00Z"
}
],
"pagination": {
"current_page": 1,
"per_page": 20,
"total": 45,
"last_page": 3
}
}
}
Authorization: Any authenticated user can browse
GET /requests/my
List current user's buy requests.
Headers: Authorization: Bearer {token}
Query Parameters:
status(optional): Filter by statuspage,per_page
Response: 200 OK (same format as GET /requests)
GET /requests/{id}
Get buy request details.
Headers: Authorization: Bearer {token}
Response: 200 OK
{
"success": true,
"data": {
"id": "uuid",
"buyer": {
"id": "uuid",
"name": "محمد أحمد"
},
"category": "phone",
"product_brand": "Apple",
"product_model": "iPhone 13",
"condition_pref": "like_new",
"budget_min": 8000,
"budget_max": 10000,
"location_district": "Nasr City",
"location_city": "Cairo",
"notes": "Prefer 128GB, any color",
"status": "active",
"offer_count": 3,
"created_at": "2026-02-26T22:30:00Z",
"closed_at": null
}
}
PUT /requests/{id}/close
Close a buy request manually.
Headers: Authorization: Bearer {token}
Authorization: Only request owner
Response: 200 OK
{
"success": true,
"data": {
"id": "uuid",
"status": "closed",
"closed_at": "2026-02-26T23:00:00Z"
}
}
Errors:
403- Not request owner422- Request already closed
Offer Endpoints
POST /offers
Create an offer on a buy request.
Headers: Authorization: Bearer {token}
Request:
{
"request_id": "uuid",
"price": 9500,
"availability": "Immediate",
"condition_notes": "Excellent condition, 95% battery health",
"warranty_notes": "6 months warranty included"
}
Response: 201 Created
{
"success": true,
"data": {
"id": "uuid",
"request_id": "uuid",
"seller_id": "uuid",
"price": 9500,
"availability": "Immediate",
"condition_notes": "Excellent condition, 95% battery health",
"warranty_notes": "6 months warranty included",
"status": "pending",
"created_at": "2026-02-26T22:35:00Z"
}
}
Authorization: Only approved sellers
Validation:
- Request must be active
- Seller must be approved
- Price should be within budget range (warning if outside)
Errors:
403- Seller not approved422- Request not active422- Seller already has pending offer on this request
GET /requests/{request_id}/offers
List offers for a buy request.
Headers: Authorization: Bearer {token}
Authorization: Request owner or offer sellers
Response: 200 OK
{
"success": true,
"data": {
"offers": [
{
"id": "uuid",
"seller": {
"id": "uuid",
"name": "Ahmed's Electronics",
"rating_avg": 4.5,
"rating_count": 23,
"location_district": "Nasr City"
},
"price": 9500,
"availability": "Immediate",
"condition_notes": "Excellent condition",
"warranty_notes": "6 months warranty",
"status": "pending",
"created_at": "2026-02-26T22:35:00Z"
}
]
}
}
GET /offers/my
List current user's offers (for sellers).
Headers: Authorization: Bearer {token}
Query Parameters:
status(optional): Filter by statuspage,per_page
Response: 200 OK
{
"success": true,
"data": {
"offers": [
{
"id": "uuid",
"request": {
"id": "uuid",
"product_brand": "Apple",
"product_model": "iPhone 13",
"budget_max": 10000
},
"price": 9500,
"status": "pending",
"created_at": "2026-02-26T22:35:00Z"
}
],
"pagination": { ... }
}
}
POST /offers/{id}/accept
Accept an offer (buyer only).
Headers: Authorization: Bearer {token}
Authorization: Only request owner
Response: 200 OK
{
"success": true,
"data": {
"deal": {
"id": "uuid",
"request_id": "uuid",
"offer_id": "uuid",
"buyer_id": "uuid",
"seller_id": "uuid",
"status": "accepted",
"created_at": "2026-02-26T22:40:00Z"
}
}
}
Side Effects:
- Creates deal
- Sets offer status to accepted
- Rejects all other offers
- Closes buy request
- Sends push notifications
Errors:
403- Not request owner422- Offer already accepted/rejected422- Request not active
DELETE /offers/{id}
Withdraw an offer (seller only, before acceptance).
Headers: Authorization: Bearer {token}
Authorization: Only offer owner
Response: 200 OK
{
"success": true,
"message": "Offer withdrawn"
}
Errors:
403- Not offer owner422- Offer already accepted
Deal Endpoints
GET /deals/my
List current user's deals (buyer or seller view).
Headers: Authorization: Bearer {token}
Query Parameters:
status(optional): Filter by statusrole(optional): Filter by role (buyer/seller)page,per_page
Response: 200 OK
{
"success": true,
"data": {
"deals": [
{
"id": "uuid",
"request": {
"product_brand": "Apple",
"product_model": "iPhone 13"
},
"offer": {
"price": 9500
},
"buyer": {
"id": "uuid",
"name": "محمد أحمد"
},
"seller": {
"id": "uuid",
"name": "Ahmed's Electronics",
"rating_avg": 4.5
},
"status": "accepted",
"created_at": "2026-02-26T22:40:00Z"
}
],
"pagination": { ... }
}
}
GET /deals/{id}
Get deal details.
Headers: Authorization: Bearer {token}
Authorization: Buyer or seller in deal
Response: 200 OK
{
"success": true,
"data": {
"id": "uuid",
"request": { ... },
"offer": { ... },
"buyer": { ... },
"seller": { ... },
"status": "accepted",
"conversation_id": "uuid",
"created_at": "2026-02-26T22:40:00Z",
"completed_at": null,
"cancelled_at": null
}
}
PUT /deals/{id}/complete
Mark deal as completed (buyer only).
Headers: Authorization: Bearer {token}
Authorization: Only buyer
Response: 200 OK
{
"success": true,
"data": {
"id": "uuid",
"status": "completed",
"completed_at": "2026-02-27T10:00:00Z"
}
}
Side Effects:
- Triggers rating prompt for buyer
PUT /deals/{id}/cancel
Cancel deal (buyer only).
Headers: Authorization: Bearer {token}
Authorization: Only buyer
Request:
{
"reason": "Seller didn't show",
"description": "Optional additional details"
}
Response: 200 OK
{
"success": true,
"data": {
"id": "uuid",
"status": "cancelled",
"cancelled_at": "2026-02-27T10:00:00Z"
}
}
Chat Endpoints
GET /conversations/my
List current user's conversations.
Headers: Authorization: Bearer {token}
Response: 200 OK
{
"success": true,
"data": {
"conversations": [
{
"id": "uuid",
"offer_id": "uuid",
"other_party": {
"id": "uuid",
"name": "Ahmed's Electronics",
"avatar_url": "..."
},
"last_message": {
"text": "هل المنتج متاح؟",
"created_at": "2026-02-26T22:45:00Z"
},
"unread_count": 2,
"created_at": "2026-02-26T22:35:00Z"
}
]
}
}
GET /conversations/{id}/messages
Get messages in a conversation.
Headers: Authorization: Bearer {token}
Authorization: Participant in conversation
Query Parameters:
before(optional): Get messages before this timestamplimit(optional): Max messages (default: 50)
Response: 200 OK
{
"success": true,
"data": {
"messages": [
{
"id": "uuid",
"sender_id": "uuid",
"message_text": "هل المنتج متاح الآن؟",
"read_at": null,
"created_at": "2026-02-26T22:45:00Z"
}
],
"has_more": false
}
}
POST /conversations/{id}/messages
Send a message (via REST, WebSocket preferred for real-time).
Headers: Authorization: Bearer {token}
Request:
{
"message_text": "نعم، المنتج متاح"
}
Response: 201 Created
{
"success": true,
"data": {
"id": "uuid",
"conversation_id": "uuid",
"sender_id": "uuid",
"message_text": "نعم، المنتج متاح",
"created_at": "2026-02-26T22:46:00Z"
}
}
Rating Endpoints
POST /ratings
Submit a rating for a seller.
Headers: Authorization: Bearer {token}
Authorization: Only buyer in completed deal
Request:
{
"deal_id": "uuid",
"rating": 5,
"review_text": "بائع ممتاز، منتج كما وصف"
}
Response: 201 Created
{
"success": true,
"data": {
"id": "uuid",
"deal_id": "uuid",
"seller_id": "uuid",
"rating": 5,
"review_text": "بائع ممتاز، منتج كما وصف",
"created_at": "2026-02-27T10:05:00Z"
}
}
Validation:
- Deal must be completed
- One rating per deal
- Rating must be 1-5
Report Endpoints
POST /reports
Report a seller.
Headers: Authorization: Bearer {token}
Request:
{
"reported_user_id": "uuid",
"deal_id": "uuid",
"reason": "no_show",
"description": "Seller didn't show up at agreed location"
}
Response: 201 Created
{
"success": true,
"data": {
"id": "uuid",
"status": "pending",
"created_at": "2026-02-27T11:00:00Z"
}
}
Validation:
reason: enum (fake_offer, no_show, rude, scam, other)
Seller Profile Endpoints
POST /seller-profiles
Apply to become a seller.
Headers: Authorization: Bearer {token}
Request:
{
"business_name": "Ahmed's Electronics",
"location_district": "Nasr City",
"location_city": "Cairo",
"bio": "Selling quality used phones since 2020"
}
Response: 201 Created
{
"success": true,
"data": {
"id": "uuid",
"user_id": "uuid",
"status": "pending",
"business_name": "Ahmed's Electronics",
"location_district": "Nasr City",
"created_at": "2026-02-26T22:00:00Z"
}
}
Errors:
422- User already has seller profile
GET /seller-profiles/{id}
Get seller profile (public).
Response: 200 OK
{
"success": true,
"data": {
"id": "uuid",
"business_name": "Ahmed's Electronics",
"location_district": "Nasr City",
"bio": "Selling quality used phones since 2020",
"rating_avg": 4.5,
"rating_count": 23,
"created_at": "2026-02-26T22:00:00Z"
}
}
Admin Endpoints
All admin endpoints require is_admin = true.
GET /admin/seller-profiles/pending
List pending seller applications.
Headers: Authorization: Bearer {token}
Authorization: Admin only
Response: 200 OK
{
"success": true,
"data": {
"profiles": [
{
"id": "uuid",
"user": {
"id": "uuid",
"phone_number": "+201234567890",
"name": "Ahmed"
},
"business_name": "Ahmed's Electronics",
"location_district": "Nasr City",
"bio": "...",
"status": "pending",
"created_at": "2026-02-26T22:00:00Z"
}
]
}
}
PUT /admin/seller-profiles/{id}/approve
Approve seller application.
Headers: Authorization: Bearer {token}
Authorization: Admin only
Response: 200 OK
{
"success": true,
"data": {
"id": "uuid",
"status": "approved",
"approved_at": "2026-02-26T23:00:00Z"
}
}
PUT /admin/seller-profiles/{id}/reject
Reject seller application.
Headers: Authorization: Bearer {token}
Authorization: Admin only
Response: 200 OK
{
"success": true,
"data": {
"id": "uuid",
"status": "rejected"
}
}
GET /admin/reports
List all reports.
Headers: Authorization: Bearer {token}
Authorization: Admin only
Query Parameters:
status(optional): Filter by status
Response: 200 OK
{
"success": true,
"data": {
"reports": [
{
"id": "uuid",
"reporter": { ... },
"reported_user": { ... },
"deal": { ... },
"reason": "no_show",
"description": "...",
"status": "pending",
"created_at": "2026-02-27T11:00:00Z"
}
]
}
}
PUT /admin/reports/{id}/resolve
Resolve a report.
Headers: Authorization: Bearer {token}
Authorization: Admin only
Request:
{
"action": "warn",
"notes": "Warned seller about no-show"
}
Response: 200 OK
WebSocket Events
Connect to: wss://api.talbino.com/ws
Authentication
{
"type": "auth",
"token": "jwt_token_here"
}
Subscribe to Chat
{
"type": "subscribe",
"channel": "conversation.`{conversation_id}`"
}
Send Message
{
"type": "message",
"conversation_id": "uuid",
"message_text": "Hello"
}
Receive Message
{
"type": "message",
"data": {
"id": "uuid",
"conversation_id": "uuid",
"sender_id": "uuid",
"message_text": "Hello",
"created_at": "2026-02-26T22:45:00Z"
}
}
Rate Limiting
- Auth endpoints: 10 requests/minute per IP
- OTP requests: 3 requests/10 minutes per phone
- General API: 100 requests/minute per user
- WebSocket: 50 messages/minute per user
Pagination
All list endpoints support pagination:
page: Page number (default: 1)per_page: Items per page (default: 20, max: 50)
Response includes:
{
"pagination": {
"current_page": 1,
"per_page": 20,
"total": 100,
"last_page": 5
}
}
Localization
All text responses support Arabic and English based on:
Accept-Languageheader (ar/en)- User's language preference
- Default: Arabic
Error messages and notifications are localized automatically.