{
  "info": {
    "name": "SwiftColis External API",
    "_postman_id": "swiftcolis-external-api-v1",
    "description": "Collection complète de l'API externe SwiftColis v1.\n\nAuthentification : ajoutez votre clé API dans la variable `api_key` de la collection (format `prefix.secret`).\n\nBase URL : configurez `base_url` selon votre environnement.\n- Production : https://api.swiftcolis.com\n- Développement : http://localhost:4000",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "version": "1.0.0"
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://api.swiftcolis.com",
      "type": "string",
      "description": "URL de base de l'API. Changez en http://localhost:4000 pour le développement."
    },
    {
      "key": "api_key",
      "value": "votre_prefix.votre_secret",
      "type": "string",
      "description": "Clé API au format prefix.secret — générée depuis votre tableau de bord marchand."
    },
    {
      "key": "tracking_code",
      "value": "SC-A7B3K9",
      "type": "string",
      "description": "Code de suivi utilisé dans les requêtes de suivi."
    }
  ],
  "auth": {
    "type": "apikey",
    "apikey": [
      {
        "key": "key",
        "value": "x-api-key",
        "type": "string"
      },
      {
        "key": "value",
        "value": "{{api_key}}",
        "type": "string"
      },
      {
        "key": "in",
        "value": "header",
        "type": "string"
      }
    ]
  },
  "item": [
    {
      "name": "Colis",
      "description": "Endpoints pour créer et consulter vos colis via l'API externe.",
      "item": [
        {
          "name": "Créer un colis",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "if (pm.response.code === 201) {",
                  "  const data = pm.response.json();",
                  "  pm.collectionVariables.set('tracking_code', data.trackingCode);",
                  "  pm.test('Colis créé avec succès', () => {",
                  "    pm.expect(data).to.have.property('trackingCode');",
                  "    pm.expect(data).to.have.property('id');",
                  "    pm.expect(data.status).to.equal('in_pickup');",
                  "  });",
                  "  console.log('Tracking code enregistré :', data.trackingCode);",
                  "} else {",
                  "  pm.test('Création du colis', () => {",
                  "    pm.expect(pm.response.code).to.equal(201);",
                  "  });",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"recipientName\": \"Ahmed Trabelsi\",\n  \"recipientPhone\": \"98123456\",\n  \"recipientAddress\": \"15 Rue de la Paix, Tunis\",\n  \"governorate\": \"Tunis\",\n  \"delegation\": \"Tunis Médina\",\n  \"codAmount\": 150.5,\n  \"description\": \"Vêtements\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/external/v1/colis",
              "host": ["{{base_url}}"],
              "path": ["external", "v1", "colis"]
            },
            "description": "Crée un nouveau colis pour le marchand authentifié.\n\nRetourne l'ID, le code de suivi et les détails du colis créé.\n\n**Champs requis :** recipientName, recipientPhone ( XX XXX XXX), recipientAddress, governorate, delegation, codAmount, description.\n\nLe colis est créé au statut `in_pickup`."
          },
          "response": [
            {
              "name": "201 - Colis créé",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"recipientName\": \"Ahmed Trabelsi\",\n  \"recipientPhone\": \"98123456\",\n  \"recipientAddress\": \"15 Rue de la Paix, Tunis\",\n  \"governorate\": \"Tunis\",\n  \"delegation\": \"Tunis Médina\",\n  \"codAmount\": 150.5,\n  \"description\": \"Vêtements\"\n}"
                },
                "url": {
                  "raw": "{{base_url}}/external/v1/colis",
                  "host": ["{{base_url}}"],
                  "path": ["external", "v1", "colis"]
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"id\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"trackingCode\": \"SC-A7B3K9\",\n  \"recipientName\": \"Ahmed Trabelsi\",\n  \"recipientPhone\": \"98123456\",\n  \"recipientAddress\": \"15 Rue de la Paix, Tunis\",\n  \"governorate\": \"Tunis\",\n  \"delegation\": \"Tunis Médina\",\n  \"codAmount\": 150.5,\n  \"productPrice\": 120.0,\n  \"deliveryFee\": 30.5,\n  \"status\": \"in_pickup\",\n  \"createdAt\": \"2026-04-18T14:30:00.000Z\"\n}"
            },
            {
              "name": "401 - Clé API invalide",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "body": {
                  "mode": "raw",
                  "raw": "{}"
                },
                "url": {
                  "raw": "{{base_url}}/external/v1/colis",
                  "host": ["{{base_url}}"],
                  "path": ["external", "v1", "colis"]
                }
              },
              "status": "Unauthorized",
              "code": 401,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 401,\n  \"message\": \"Unauthorized\"\n}"
            },
            {
              "name": "422 - Validation échouée",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "body": {
                  "mode": "raw",
                  "raw": "{}"
                },
                "url": {
                  "raw": "{{base_url}}/external/v1/colis",
                  "host": ["{{base_url}}"],
                  "path": ["external", "v1", "colis"]
                }
              },
              "status": "Unprocessable Entity",
              "code": 422,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 422,\n  \"message\": [\n    \"recipientName should not be empty\",\n    \"recipientPhone must be in Tunisian format:  XX XXX XXX\"\n  ],\n  \"error\": \"Unprocessable Entity\"\n}"
            }
          ]
        },
        {
          "name": "Créer un colis (champs complets)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "if (pm.response.code === 201) {",
                  "  const data = pm.response.json();",
                  "  pm.collectionVariables.set('tracking_code', data.trackingCode);",
                  "  pm.test('Colis créé avec succès', () => {",
                  "    pm.expect(data).to.have.property('trackingCode');",
                  "  });",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"recipientName\": \"Ahmed Trabelsi\",\n  \"recipientPhone\": \"98123456\",\n  \"recipientPhone2\": \"22334455\",\n  \"recipientAddress\": \"15 Rue de la Paix, Tunis\",\n  \"governorate\": \"Tunis\",\n  \"delegation\": \"Tunis Médina\",\n  \"codAmount\": 150.5,\n  \"description\": \"Vêtements — 2 pièces\",\n  \"weight\": 1.5,\n  \"fragile\": false,\n  \"numberOfPieces\": 2,\n  \"isExchange\": false\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/external/v1/colis",
              "host": ["{{base_url}}"],
              "path": ["external", "v1", "colis"]
            },
            "description": "Crée un colis avec tous les champs disponibles (obligatoires + optionnels).\n\n**Champs optionnels :** recipientPhone2, weight, fragile, numberOfPieces, isExchange, exchangeDescription, internalNotes, supplierNotes, recipientLat, recipientLng."
          },
          "response": []
        },
        {
          "name": "Lister les colis",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Réponse paginée valide', () => {",
                  "  const data = pm.response.json();",
                  "  pm.expect(data).to.have.property('data');",
                  "  pm.expect(data).to.have.property('total');",
                  "  pm.expect(data.data).to.be.an('array');",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/external/v1/colis?skip=0&take=20",
              "host": ["{{base_url}}"],
              "path": ["external", "v1", "colis"],
              "query": [
                {
                  "key": "skip",
                  "value": "0",
                  "description": "Nombre d'enregistrements à sauter (pagination)"
                },
                {
                  "key": "take",
                  "value": "20",
                  "description": "Nombre d'enregistrements à retourner (max 100)"
                },
                {
                  "key": "status",
                  "value": "",
                  "description": "Filtrer par statut : in_pickup | collected | in_stock | in_transit | delivered | returned_to_sender",
                  "disabled": true
                },
                {
                  "key": "dateFrom",
                  "value": "",
                  "description": "Date de début (format : 2026-04-01)",
                  "disabled": true
                },
                {
                  "key": "dateTo",
                  "value": "",
                  "description": "Date de fin (format : 2026-04-30)",
                  "disabled": true
                }
              ]
            },
            "description": "Retourne la liste paginée des colis du marchand authentifié.\n\nUtilisez `skip` et `take` pour paginer. Activez les query params optionnels pour filtrer par statut ou période."
          },
          "response": [
            {
              "name": "200 - Liste paginée",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/external/v1/colis?skip=0&take=20",
                  "host": ["{{base_url}}"],
                  "path": ["external", "v1", "colis"],
                  "query": [
                    { "key": "skip", "value": "0" },
                    { "key": "take", "value": "20" }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"data\": [\n    {\n      \"id\": \"550e8400-e29b-41d4-a716-446655440000\",\n      \"trackingCode\": \"SC-A7B3K9\",\n      \"recipientName\": \"Ahmed Trabelsi\",\n      \"status\": \"delivered\",\n      \"codAmount\": 150.5,\n      \"createdAt\": \"2026-04-10T14:30:00.000Z\",\n      \"deliveredAt\": \"2026-04-12T10:15:00.000Z\"\n    }\n  ],\n  \"total\": 1,\n  \"skip\": 0,\n  \"take\": 20\n}"
            }
          ]
        },
        {
          "name": "Lister les colis livrés",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/external/v1/colis?skip=0&take=20&status=delivered",
              "host": ["{{base_url}}"],
              "path": ["external", "v1", "colis"],
              "query": [
                { "key": "skip", "value": "0" },
                { "key": "take", "value": "20" },
                { "key": "status", "value": "delivered" }
              ]
            },
            "description": "Filtre la liste pour ne retourner que les colis avec le statut `delivered`.\n\nRemplacez `delivered` par n'importe quel statut : in_pickup, collected, in_stock, in_transit, returned_to_sender."
          },
          "response": []
        },
        {
          "name": "Suivre un colis par code",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Colis trouvé', () => {",
                  "  pm.expect(pm.response.code).to.equal(200);",
                  "  const data = pm.response.json();",
                  "  pm.expect(data).to.have.property('trackingCode');",
                  "  pm.expect(data).to.have.property('status');",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/external/v1/colis/by-tracking/{{tracking_code}}",
              "host": ["{{base_url}}"],
              "path": ["external", "v1", "colis", "by-tracking", "{{tracking_code}}"]
            },
            "description": "Récupère les détails complets d'un colis via son code de suivi.\n\nLe code doit appartenir au marchand authentifié par la clé API. Un code d'un autre marchand retourne 404."
          },
          "response": [
            {
              "name": "200 - Détails du colis",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/external/v1/colis/by-tracking/SC-A7B3K9",
                  "host": ["{{base_url}}"],
                  "path": ["external", "v1", "colis", "by-tracking", "SC-A7B3K9"]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"id\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"trackingCode\": \"SC-A7B3K9\",\n  \"recipientName\": \"Ahmed Trabelsi\",\n  \"recipientPhone\": \"98123456\",\n  \"recipientAddress\": \"15 Rue de la Paix, Tunis\",\n  \"governorate\": \"Tunis\",\n  \"delegation\": \"Tunis Médina\",\n  \"codAmount\": 150.5,\n  \"productPrice\": 120.0,\n  \"deliveryFee\": 30.5,\n  \"status\": \"in_stock\",\n  \"isPrepaid\": false,\n  \"description\": \"Vêtements\",\n  \"createdAt\": \"2026-04-10T14:30:00.000Z\"\n}"
            },
            {
              "name": "404 - Code introuvable",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/external/v1/colis/by-tracking/SC-INVALID",
                  "host": ["{{base_url}}"],
                  "path": ["external", "v1", "colis", "by-tracking", "SC-INVALID"]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"statusCode\": 404,\n  \"message\": \"Colis not found\"\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Vérification",
      "description": "Requêtes utilitaires pour vérifier la connectivité et l'authentification.",
      "item": [
        {
          "name": "Vérifier la clé API (liste vide)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Clé API valide', () => {",
                  "  pm.expect(pm.response.code).to.equal(200);",
                  "  const data = pm.response.json();",
                  "  pm.expect(data).to.have.property('data');",
                  "  console.log('✅ Clé API valide — accès confirmé');",
                  "});",
                  "pm.test('Réponse paginée', () => {",
                  "  const data = pm.response.json();",
                  "  pm.expect(data).to.have.property('total');",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/external/v1/colis?skip=0&take=1",
              "host": ["{{base_url}}"],
              "path": ["external", "v1", "colis"],
              "query": [
                { "key": "skip", "value": "0" },
                { "key": "take", "value": "1" }
              ]
            },
            "description": "Utilise l'endpoint liste avec take=1 pour vérifier que votre clé API est valide et que vous pouvez vous connecter à l'API.\n\n- HTTP 200 → clé valide ✅\n- HTTP 401 → clé invalide ou manquante ❌"
          },
          "response": []
        }
      ]
    }
  ]
}
