# 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
