Some checks are pending
CD Production (Hetzner k3s) / Promote Images (preprod → prod) (push) Waiting to run
CD Production (Hetzner k3s) / Deploy to k3s (xpeditis-prod) (push) Blocked by required conditions
CD Production (Hetzner k3s) / Smoke Tests (push) Blocked by required conditions
CD Production (Hetzner k3s) / Deployment Summary (push) Blocked by required conditions
CD Production (Hetzner k3s) / Notify Success (push) Blocked by required conditions
CD Production (Hetzner k3s) / Notify Failure (push) Blocked by required conditions
Aligns main with the complete application codebase (cicd branch). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
373 lines
12 KiB
JSON
373 lines
12 KiB
JSON
{
|
|
"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"]
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|