{
  "info": {
    "name": "Xpeditis API",
    "description": "Complete API collection for Xpeditis maritime freight booking platform",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "_postman_id": "xpeditis-api-v1",
    "version": "1.0.0"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{access_token}}",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "base_url",
      "value": "http://localhost:4000/api/v1",
      "type": "string"
    },
    {
      "key": "access_token",
      "value": "",
      "type": "string"
    },
    {
      "key": "refresh_token",
      "value": "",
      "type": "string"
    },
    {
      "key": "user_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "booking_id",
      "value": "",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "Authentication",
      "item": [
        {
          "name": "Register User",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test(\"Status code is 201\", function () {",
                  "    pm.response.to.have.status(201);",
                  "});",
                  "",
                  "pm.test(\"Response has user data\", function () {",
                  "    const jsonData = pm.response.json();",
                  "    pm.expect(jsonData).to.have.property('user');",
                  "    pm.expect(jsonData).to.have.property('accessToken');",
                  "    pm.environment.set('access_token', jsonData.accessToken);",
                  "    pm.environment.set('user_id', jsonData.user.id);",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"test@example.com\",\n  \"password\": \"TestPassword123!\",\n  \"firstName\": \"Test\",\n  \"lastName\": \"User\",\n  \"organizationName\": \"Test Organization\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/auth/register",
              "host": ["{{base_url}}"],
              "path": ["auth", "register"]
            }
          }
        },
        {
          "name": "Login",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test(\"Status code is 200\", function () {",
                  "    pm.response.to.have.status(200);",
                  "});",
                  "",
                  "pm.test(\"Response has tokens\", function () {",
                  "    const jsonData = pm.response.json();",
                  "    pm.expect(jsonData).to.have.property('accessToken');",
                  "    pm.expect(jsonData).to.have.property('refreshToken');",
                  "    pm.environment.set('access_token', jsonData.accessToken);",
                  "    pm.environment.set('refresh_token', jsonData.refreshToken);",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "auth": {
              "type": "noauth"
            },
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"test@example.com\",\n  \"password\": \"TestPassword123!\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/auth/login",
              "host": ["{{base_url}}"],
              "path": ["auth", "login"]
            }
          }
        },
        {
          "name": "Refresh Token",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test(\"Status code is 200\", function () {",
                  "    pm.response.to.have.status(200);",
                  "});",
                  "",
                  "const jsonData = pm.response.json();",
                  "pm.environment.set('access_token', jsonData.accessToken);"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "auth": {
              "type": "noauth"
            },
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"refreshToken\": \"{{refresh_token}}\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/auth/refresh",
              "host": ["{{base_url}}"],
              "path": ["auth", "refresh"]
            }
          }
        }
      ]
    },
    {
      "name": "Rates",
      "item": [
        {
          "name": "Search Rates",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test(\"Status code is 200\", function () {",
                  "    pm.response.to.have.status(200);",
                  "});",
                  "",
                  "pm.test(\"Response has quotes\", function () {",
                  "    const jsonData = pm.response.json();",
                  "    pm.expect(jsonData).to.have.property('quotes');",
                  "    pm.expect(jsonData.quotes).to.be.an('array');",
                  "});",
                  "",
                  "pm.test(\"Response time < 2000ms\", function () {",
                  "    pm.expect(pm.response.responseTime).to.be.below(2000);",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"origin\": \"NLRTM\",\n  \"destination\": \"CNSHA\",\n  \"departureDate\": \"2025-11-01\",\n  \"containers\": [\n    {\n      \"type\": \"40HC\",\n      \"quantity\": 1\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/rates/search",
              "host": ["{{base_url}}"],
              "path": ["rates", "search"]
            }
          }
        }
      ]
    },
    {
      "name": "Bookings",
      "item": [
        {
          "name": "Create Booking",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test(\"Status code is 201\", function () {",
                  "    pm.response.to.have.status(201);",
                  "});",
                  "",
                  "pm.test(\"Response has booking data\", function () {",
                  "    const jsonData = pm.response.json();",
                  "    pm.expect(jsonData).to.have.property('id');",
                  "    pm.expect(jsonData).to.have.property('bookingNumber');",
                  "    pm.environment.set('booking_id', jsonData.id);",
                  "});",
                  "",
                  "pm.test(\"Booking number format is correct\", function () {",
                  "    const jsonData = pm.response.json();",
                  "    pm.expect(jsonData.bookingNumber).to.match(/^WCM-\\d{4}-[A-Z0-9]{6}$/);",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"rateQuoteId\": \"rate-quote-id\",\n  \"shipper\": {\n    \"name\": \"Test Shipper Inc.\",\n    \"address\": \"123 Test St\",\n    \"city\": \"Rotterdam\",\n    \"country\": \"Netherlands\",\n    \"email\": \"shipper@test.com\",\n    \"phone\": \"+31612345678\"\n  },\n  \"consignee\": {\n    \"name\": \"Test Consignee Ltd.\",\n    \"address\": \"456 Dest Ave\",\n    \"city\": \"Shanghai\",\n    \"country\": \"China\",\n    \"email\": \"consignee@test.com\",\n    \"phone\": \"+8613812345678\"\n  },\n  \"containers\": [\n    {\n      \"type\": \"40HC\",\n      \"description\": \"Electronics\",\n      \"weight\": 15000\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/bookings",
              "host": ["{{base_url}}"],
              "path": ["bookings"]
            }
          }
        },
        {
          "name": "Get Booking by ID",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test(\"Status code is 200\", function () {",
                  "    pm.response.to.have.status(200);",
                  "});",
                  "",
                  "pm.test(\"Response has booking details\", function () {",
                  "    const jsonData = pm.response.json();",
                  "    pm.expect(jsonData).to.have.property('id');",
                  "    pm.expect(jsonData).to.have.property('status');",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "GET",
            "url": {
              "raw": "{{base_url}}/bookings/{{booking_id}}",
              "host": ["{{base_url}}"],
              "path": ["bookings", "{{booking_id}}"]
            }
          }
        },
        {
          "name": "List Bookings",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test(\"Status code is 200\", function () {",
                  "    pm.response.to.have.status(200);",
                  "});",
                  "",
                  "pm.test(\"Response is paginated\", function () {",
                  "    const jsonData = pm.response.json();",
                  "    pm.expect(jsonData).to.have.property('data');",
                  "    pm.expect(jsonData).to.have.property('total');",
                  "    pm.expect(jsonData).to.have.property('page');",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "GET",
            "url": {
              "raw": "{{base_url}}/bookings?page=1&pageSize=20",
              "host": ["{{base_url}}"],
              "path": ["bookings"],
              "query": [
                {
                  "key": "page",
                  "value": "1"
                },
                {
                  "key": "pageSize",
                  "value": "20"
                }
              ]
            }
          }
        },
        {
          "name": "Export Bookings (CSV)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"format\": \"csv\",\n  \"bookingIds\": []\n}"
            },
            "url": {
              "raw": "{{base_url}}/bookings/export",
              "host": ["{{base_url}}"],
              "path": ["bookings", "export"]
            }
          }
        }
      ]
    }
  ]
}
