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

15 KiB

Carrier Portal API Documentation

Version: 1.0 Base URL: http://localhost:4000/api/v1 Last Updated: 2025-12-04

Table of Contents

  1. Overview
  2. Authentication
  3. API Endpoints
  4. Data Models
  5. Error Handling
  6. 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:

{
  "email": "carrier@example.com",
  "password": "SecurePassword123!"
}

Response (200 OK):

{
  "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):

{
  "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:

{
  "oldPassword": "OldPassword123!",
  "newPassword": "NewPassword123!"
}

Response (200 OK):

{
  "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:

{
  "email": "carrier@example.com"
}

Response (200 OK):

{
  "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:

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Response (200 OK):

{
  "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):

{
  "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):

{
  "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):

{
  "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:

{
  "notes": "Ready to proceed. Pickup scheduled for Dec 5th."
}

Response (200 OK):

{
  "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:

{
  "reason": "CAPACITY_NOT_AVAILABLE",
  "notes": "Sorry, we don't have capacity for this shipment at the moment."
}

Response (200 OK):

{
  "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):

{
  "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

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

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

interface Document {
  id: string;
  fileName: string;
  type: 'INVOICE' | 'PACKING_LIST' | 'CERTIFICATE' | 'OTHER';
  url: string;
  size?: number;
  mimeType?: string;
  uploadedAt: Date;
}

Activity

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:

{
  "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

# 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

# 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:


Document created: 2025-12-04 Author: Xpeditis Development Team Version: 1.0