xpeditis2.0/apps/backend/docs/CARRIER_PORTAL_API.md
2025-12-05 13:55:40 +01:00

728 lines
15 KiB
Markdown

# Carrier Portal API Documentation
**Version**: 1.0
**Base URL**: `http://localhost:4000/api/v1`
**Last Updated**: 2025-12-04
## Table of Contents
1. [Overview](#overview)
2. [Authentication](#authentication)
3. [API Endpoints](#api-endpoints)
- [Carrier Authentication](#carrier-authentication)
- [Carrier Dashboard](#carrier-dashboard)
- [Booking Management](#booking-management)
- [Document Management](#document-management)
4. [Data Models](#data-models)
5. [Error Handling](#error-handling)
6. [Examples](#examples)
---
## Overview
The Carrier Portal API provides endpoints for transportation carriers (transporteurs) to:
- Authenticate and manage their accounts
- View dashboard statistics
- Manage booking requests from clients
- Accept or reject booking requests
- Download shipment documents
- Track their performance metrics
All endpoints require JWT authentication except for the public authentication endpoints.
---
## Authentication
### Authentication Header
All protected endpoints require a Bearer token in the Authorization header:
```
Authorization: Bearer <access_token>
```
### Token Management
- **Access Token**: Valid for 15 minutes
- **Refresh Token**: Valid for 7 days
- **Auto-Login Token**: Valid for 1 hour (for magic link authentication)
---
## API Endpoints
### Carrier Authentication
#### 1. Login
**Endpoint**: `POST /carrier-auth/login`
**Description**: Authenticate a carrier with email and password.
**Request Body**:
```json
{
"email": "carrier@example.com",
"password": "SecurePassword123!"
}
```
**Response** (200 OK):
```json
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"carrier": {
"id": "carrier-uuid",
"companyName": "Transport Express",
"email": "carrier@example.com"
}
}
```
**Errors**:
- `401 Unauthorized`: Invalid credentials
- `401 Unauthorized`: Account is inactive
- `400 Bad Request`: Validation error
---
#### 2. Get Current Carrier Profile
**Endpoint**: `GET /carrier-auth/me`
**Description**: Retrieve the authenticated carrier's profile information.
**Headers**:
```
Authorization: Bearer <access_token>
```
**Response** (200 OK):
```json
{
"id": "carrier-uuid",
"userId": "user-uuid",
"companyName": "Transport Express",
"email": "carrier@example.com",
"role": "CARRIER",
"organizationId": "org-uuid",
"phone": "+33612345678",
"website": "https://transport-express.com",
"city": "Paris",
"country": "France",
"isVerified": true,
"isActive": true,
"totalBookingsAccepted": 45,
"totalBookingsRejected": 5,
"acceptanceRate": 90.0,
"totalRevenueUsd": 125000,
"totalRevenueEur": 112500,
"preferredCurrency": "EUR",
"lastLoginAt": "2025-12-04T10:30:00Z"
}
```
**Errors**:
- `401 Unauthorized`: Invalid or expired token
---
#### 3. Change Password
**Endpoint**: `PATCH /carrier-auth/change-password`
**Description**: Change the carrier's password.
**Headers**:
```
Authorization: Bearer <access_token>
```
**Request Body**:
```json
{
"oldPassword": "OldPassword123!",
"newPassword": "NewPassword123!"
}
```
**Response** (200 OK):
```json
{
"message": "Password changed successfully"
}
```
**Errors**:
- `401 Unauthorized`: Invalid old password
- `400 Bad Request`: Password validation failed
---
#### 4. Request Password Reset
**Endpoint**: `POST /carrier-auth/request-password-reset`
**Description**: Request a password reset (generates temporary password).
**Request Body**:
```json
{
"email": "carrier@example.com"
}
```
**Response** (200 OK):
```json
{
"message": "If this email exists, a password reset will be sent"
}
```
**Note**: For security, the response is the same whether the email exists or not.
---
#### 5. Verify Auto-Login Token
**Endpoint**: `POST /carrier-auth/verify-auto-login`
**Description**: Verify an auto-login token from email magic link.
**Request Body**:
```json
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```
**Response** (200 OK):
```json
{
"userId": "user-uuid",
"carrierId": "carrier-uuid"
}
```
**Errors**:
- `401 Unauthorized`: Invalid or expired token
---
### Carrier Dashboard
#### 6. Get Dashboard Statistics
**Endpoint**: `GET /carrier-dashboard/stats`
**Description**: Retrieve carrier dashboard statistics including bookings count, revenue, and recent activities.
**Headers**:
```
Authorization: Bearer <access_token>
```
**Response** (200 OK):
```json
{
"totalBookings": 50,
"pendingBookings": 5,
"acceptedBookings": 42,
"rejectedBookings": 3,
"acceptanceRate": 93.3,
"totalRevenue": {
"usd": 125000,
"eur": 112500
},
"recentActivities": [
{
"id": "activity-uuid",
"type": "BOOKING_ACCEPTED",
"description": "Booking #12345 accepted",
"createdAt": "2025-12-04T09:15:00Z",
"bookingId": "booking-uuid"
},
{
"id": "activity-uuid-2",
"type": "DOCUMENT_DOWNLOADED",
"description": "Downloaded invoice.pdf",
"createdAt": "2025-12-04T08:30:00Z",
"bookingId": "booking-uuid-2"
}
]
}
```
**Errors**:
- `401 Unauthorized`: Invalid or expired token
- `404 Not Found`: Carrier not found
---
#### 7. Get Carrier Bookings (Paginated)
**Endpoint**: `GET /carrier-dashboard/bookings`
**Description**: Retrieve a paginated list of bookings for the carrier.
**Headers**:
```
Authorization: Bearer <access_token>
```
**Query Parameters**:
- `page` (number, optional): Page number (default: 1)
- `limit` (number, optional): Items per page (default: 10)
- `status` (string, optional): Filter by status (PENDING, ACCEPTED, REJECTED)
**Example Request**:
```
GET /carrier-dashboard/bookings?page=1&limit=10&status=PENDING
```
**Response** (200 OK):
```json
{
"data": [
{
"id": "booking-uuid",
"origin": "Rotterdam",
"destination": "New York",
"status": "PENDING",
"priceUsd": 1500,
"priceEur": 1350,
"primaryCurrency": "USD",
"requestedAt": "2025-12-04T08:00:00Z",
"carrierViewedAt": null,
"documentsCount": 3,
"volumeCBM": 25.5,
"weightKG": 12000,
"palletCount": 10,
"transitDays": 15,
"containerType": "40HC"
}
],
"total": 50,
"page": 1,
"limit": 10
}
```
**Errors**:
- `401 Unauthorized`: Invalid or expired token
- `404 Not Found`: Carrier not found
---
#### 8. Get Booking Details
**Endpoint**: `GET /carrier-dashboard/bookings/:id`
**Description**: Retrieve detailed information about a specific booking.
**Headers**:
```
Authorization: Bearer <access_token>
```
**Path Parameters**:
- `id` (string, required): Booking ID
**Response** (200 OK):
```json
{
"id": "booking-uuid",
"carrierName": "Transport Express",
"carrierEmail": "carrier@example.com",
"origin": "Rotterdam",
"destination": "New York",
"volumeCBM": 25.5,
"weightKG": 12000,
"palletCount": 10,
"priceUSD": 1500,
"priceEUR": 1350,
"primaryCurrency": "USD",
"transitDays": 15,
"containerType": "40HC",
"status": "PENDING",
"documents": [
{
"id": "doc-uuid",
"fileName": "invoice.pdf",
"type": "INVOICE",
"url": "https://storage.example.com/doc.pdf",
"uploadedAt": "2025-12-03T10:00:00Z"
}
],
"confirmationToken": "token-123",
"requestedAt": "2025-12-04T08:00:00Z",
"respondedAt": null,
"notes": "Urgent shipment",
"rejectionReason": null,
"carrierViewedAt": "2025-12-04T10:15:00Z",
"carrierAcceptedAt": null,
"carrierRejectedAt": null,
"carrierRejectionReason": null,
"carrierNotes": null,
"createdAt": "2025-12-04T08:00:00Z",
"updatedAt": "2025-12-04T10:15:00Z"
}
```
**Errors**:
- `401 Unauthorized`: Invalid or expired token
- `403 Forbidden`: Access denied to this booking
- `404 Not Found`: Booking not found
---
### Booking Management
#### 9. Accept Booking
**Endpoint**: `POST /carrier-dashboard/bookings/:id/accept`
**Description**: Accept a booking request.
**Headers**:
```
Authorization: Bearer <access_token>
```
**Path Parameters**:
- `id` (string, required): Booking ID
**Request Body**:
```json
{
"notes": "Ready to proceed. Pickup scheduled for Dec 5th."
}
```
**Response** (200 OK):
```json
{
"message": "Booking accepted successfully"
}
```
**Errors**:
- `401 Unauthorized`: Invalid or expired token
- `403 Forbidden`: Access denied to this booking
- `404 Not Found`: Booking not found
- `400 Bad Request`: Booking cannot be accepted (wrong status)
---
#### 10. Reject Booking
**Endpoint**: `POST /carrier-dashboard/bookings/:id/reject`
**Description**: Reject a booking request with a reason.
**Headers**:
```
Authorization: Bearer <access_token>
```
**Path Parameters**:
- `id` (string, required): Booking ID
**Request Body**:
```json
{
"reason": "CAPACITY_NOT_AVAILABLE",
"notes": "Sorry, we don't have capacity for this shipment at the moment."
}
```
**Response** (200 OK):
```json
{
"message": "Booking rejected successfully"
}
```
**Errors**:
- `401 Unauthorized`: Invalid or expired token
- `403 Forbidden`: Access denied to this booking
- `404 Not Found`: Booking not found
- `400 Bad Request`: Rejection reason required
- `400 Bad Request`: Booking cannot be rejected (wrong status)
---
### Document Management
#### 11. Download Document
**Endpoint**: `GET /carrier-dashboard/bookings/:bookingId/documents/:documentId/download`
**Description**: Download a document associated with a booking.
**Headers**:
```
Authorization: Bearer <access_token>
```
**Path Parameters**:
- `bookingId` (string, required): Booking ID
- `documentId` (string, required): Document ID
**Response** (200 OK):
```json
{
"document": {
"id": "doc-uuid",
"fileName": "invoice.pdf",
"type": "INVOICE",
"url": "https://storage.example.com/doc.pdf",
"size": 245678,
"mimeType": "application/pdf",
"uploadedAt": "2025-12-03T10:00:00Z"
}
}
```
**Errors**:
- `401 Unauthorized`: Invalid or expired token
- `403 Forbidden`: Access denied to this document
- `404 Not Found`: Document or booking not found
---
## Data Models
### Carrier Profile
```typescript
interface CarrierProfile {
id: string;
userId: string;
organizationId: string;
companyName: string;
email: string;
phone?: string;
website?: string;
city?: string;
country?: string;
isVerified: boolean;
isActive: boolean;
totalBookingsAccepted: number;
totalBookingsRejected: number;
acceptanceRate: number;
totalRevenueUsd: number;
totalRevenueEur: number;
preferredCurrency: 'USD' | 'EUR';
lastLoginAt?: Date;
}
```
### Booking
```typescript
interface Booking {
id: string;
carrierId: string;
carrierName: string;
carrierEmail: string;
origin: string;
destination: string;
volumeCBM: number;
weightKG: number;
palletCount: number;
priceUSD: number;
priceEUR: number;
primaryCurrency: 'USD' | 'EUR';
transitDays: number;
containerType: string;
status: 'PENDING' | 'ACCEPTED' | 'REJECTED' | 'CANCELLED';
documents: Document[];
confirmationToken: string;
requestedAt: Date;
respondedAt?: Date;
notes?: string;
rejectionReason?: string;
carrierViewedAt?: Date;
carrierAcceptedAt?: Date;
carrierRejectedAt?: Date;
carrierRejectionReason?: string;
carrierNotes?: string;
createdAt: Date;
updatedAt: Date;
}
```
### Document
```typescript
interface Document {
id: string;
fileName: string;
type: 'INVOICE' | 'PACKING_LIST' | 'CERTIFICATE' | 'OTHER';
url: string;
size?: number;
mimeType?: string;
uploadedAt: Date;
}
```
### Activity
```typescript
interface CarrierActivity {
id: string;
carrierId: string;
bookingId?: string;
activityType: 'BOOKING_ACCEPTED' | 'BOOKING_REJECTED' | 'DOCUMENT_DOWNLOADED' | 'PROFILE_UPDATED';
description: string;
metadata?: Record<string, any>;
createdAt: Date;
}
```
---
## Error Handling
### Error Response Format
All error responses follow this structure:
```json
{
"statusCode": 400,
"message": "Validation failed",
"error": "Bad Request",
"timestamp": "2025-12-04T10:30:00Z",
"path": "/api/v1/carrier-auth/login"
}
```
### Common HTTP Status Codes
- `200 OK`: Request successful
- `201 Created`: Resource created successfully
- `400 Bad Request`: Validation error or invalid request
- `401 Unauthorized`: Authentication required or invalid credentials
- `403 Forbidden`: Insufficient permissions
- `404 Not Found`: Resource not found
- `500 Internal Server Error`: Server error
---
## Examples
### Complete Authentication Flow
```bash
# 1. Login
curl -X POST http://localhost:4000/api/v1/carrier-auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "carrier@example.com",
"password": "SecurePassword123!"
}'
# Response:
# {
# "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
# "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
# "carrier": { "id": "carrier-uuid", ... }
# }
# 2. Get Dashboard Stats
curl -X GET http://localhost:4000/api/v1/carrier-dashboard/stats \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
# 3. Get Pending Bookings
curl -X GET "http://localhost:4000/api/v1/carrier-dashboard/bookings?status=PENDING&page=1&limit=10" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
# 4. Accept a Booking
curl -X POST http://localhost:4000/api/v1/carrier-dashboard/bookings/booking-uuid/accept \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-d '{
"notes": "Ready to proceed with shipment"
}'
```
### Using Auto-Login Token
```bash
# Verify auto-login token from email magic link
curl -X POST http://localhost:4000/api/v1/carrier-auth/verify-auto-login \
-H "Content-Type: application/json" \
-d '{
"token": "auto-login-token-from-email"
}'
```
---
## Rate Limiting
All API endpoints are rate-limited to prevent abuse:
- **Authentication endpoints**: 5 requests per minute per IP
- **Dashboard/Booking endpoints**: 30 requests per minute per user
- **Global limit**: 100 requests per minute per user
Rate limit headers are included in all responses:
```
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 29
X-RateLimit-Reset: 60
```
---
## Security
### Best Practices
1. **Always use HTTPS** in production
2. **Store tokens securely** (e.g., httpOnly cookies, secure storage)
3. **Implement token refresh** before access token expires
4. **Validate all input** on client side before sending to API
5. **Handle errors gracefully** without exposing sensitive information
6. **Log out properly** by clearing all stored tokens
### CORS Configuration
The API allows requests from:
- `http://localhost:3000` (development)
- `https://your-production-domain.com` (production)
---
## Changelog
### Version 1.0 (2025-12-04)
- Initial release
- Authentication endpoints
- Dashboard endpoints
- Booking management
- Document management
- Complete carrier portal workflow
---
## Support
For API support or questions:
- **Email**: support@xpeditis.com
- **Documentation**: https://docs.xpeditis.com
- **Status Page**: https://status.xpeditis.com
---
**Document created**: 2025-12-04
**Author**: Xpeditis Development Team
**Version**: 1.0