{
  "info": {
    "_postman_id": "a1b2c3d4-0000-4000-8000-wallet000001",
    "name": "Wallet Service",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    {
      "key": "baseUrl",
      "value": "http://localhost:3050",
      "type": "string"
    },
    {
      "key": "apiKey",
      "value": "demo-api-key-1",
      "type": "string",
      "description": "Vaziva partner API key (seeds: demo-api-key-1)"
    },
    {
      "key": "gandalfHolderId",
      "value": "f3c30f2a-18dd-4843-bc6d-bd42583e2df4",
      "type": "string",
      "description": "Holder ID for Gandalf (seeded)"
    },
    {
      "key": "gandalfWalletId",
      "value": "3d1b571d-e46a-4a7d-9c60-c1a4c031030a",
      "type": "string",
      "description": "DEPOSIT_WALLET_GANDALF (seeded)"
    },
    {
      "key": "threddVzvfrProgramId",
      "value": "70ef8508-a620-4ac9-aa0b-0b6b09881f1c",
      "type": "string",
      "description": "Card program: thredd / vzvfr (seeded)"
    },
    {
      "key": "threddVzvesProgramId",
      "value": "81fa9619-b731-5bda-bb1c-1c7c1aa92f2d",
      "type": "string",
      "description": "Card program: thredd / vzves (seeded)"
    },
    {
      "key": "threddKycFullControlGroupId",
      "value": "c1000001-0000-4000-8000-000000000101",
      "type": "string",
      "description": "Control group: thredd / kyc_full (seeded)"
    },
    {
      "key": "threddKycLightControlGroupId",
      "value": "c1000001-0000-4000-8000-000000000102",
      "type": "string",
      "description": "Control group: thredd / kyc_light (seeded)"
    },
    {
      "key": "frodoPublicToken",
      "value": "131790308",
      "type": "string",
      "description": "Seeded Frodo Thredd card public token (vzvfr / kyc_full)"
    },
    {
      "key": "createdCardPublicToken",
      "value": "",
      "type": "string",
      "description": "Public token captured from the latest Create card request"
    },
    {
      "key": "threddProcessorId",
      "value": "75fa83a5-c980-44d0-a80b-a598a10e1afa",
      "type": "string",
      "description": "Card processor: thredd (seeded)"
    },
    {
      "key": "createdCardProgramId",
      "value": "",
      "type": "string",
      "description": "Card program ID captured from the latest Create card program request"
    },
    {
      "key": "createdCardControlGroupId",
      "value": "",
      "type": "string",
      "description": "Card control group ID captured from the latest Create card control group request"
    }
  ],
  "auth": {
    "type": "apikey",
    "apikey": [
      {
        "key": "key",
        "value": "X-Api-Key",
        "type": "string"
      },
      {
        "key": "value",
        "value": "{{apiKey}}",
        "type": "string"
      },
      {
        "key": "in",
        "value": "header",
        "type": "string"
      }
    ]
  },
  "item": [
    {
      "name": "Cards",
      "item": [
        {
          "name": "Create card",
          "item": [
            {
              "name": "Create virtual card for Gandalf (vzvfr / kyc_full)",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 201', () => pm.response.to.have.status(201));",
                      "pm.test('Response has card id', () => {",
                      "    const body = pm.response.json();",
                      "    pm.expect(body.id).to.be.a('string');",
                      "    pm.expect(body.holderId).to.eql(pm.collectionVariables.get('gandalfHolderId'));",
                      "    pm.expect(body.isVirtual).to.eql(true);",
                      "    pm.expect(body.lockStatus).to.eql('unlocked');",
                      "    pm.collectionVariables.set('createdCardId', body.id);",
                      "    if (body.publicToken) {",
                      "        pm.collectionVariables.set('createdCardPublicToken', body.publicToken);",
                      "    }",
                      "});"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/cards",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards"]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"holderId\": \"{{gandalfHolderId}}\",\n  \"cardProgramId\": \"{{threddVzvfrProgramId}}\",\n  \"controlGroupId\": \"{{threddKycFullControlGroupId}}\",\n  \"isVirtual\": true,\n  \"walletId\": \"{{gandalfWalletId}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              }
            },
            {
              "name": "Create virtual card for Gandalf (vzves / kyc_light, no wallet)",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 201', () => pm.response.to.have.status(201));",
                      "pm.test('Response has card id', () => {",
                      "    const body = pm.response.json();",
                      "    pm.expect(body.id).to.be.a('string');",
                      "    pm.expect(body.isVirtual).to.eql(true);",
                      "});"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/cards",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards"]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"holderId\": \"{{gandalfHolderId}}\",\n  \"cardProgramId\": \"{{threddVzvesProgramId}}\",\n  \"controlGroupId\": \"{{threddKycLightControlGroupId}}\",\n  \"isVirtual\": true\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              }
            },
            {
              "name": "Create physical card for Gandalf (vzvfr / kyc_full, with address)",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 201', () => pm.response.to.have.status(201));",
                      "pm.test('Response has card id', () => {",
                      "    const body = pm.response.json();",
                      "    pm.expect(body.id).to.be.a('string');",
                      "    pm.expect(body.isVirtual).to.eql(false);",
                      "});"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/cards",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards"]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"holderId\": \"{{gandalfHolderId}}\",\n  \"cardProgramId\": \"{{threddVzvfrProgramId}}\",\n  \"controlGroupId\": \"{{threddKycFullControlGroupId}}\",\n  \"isVirtual\": false,\n  \"walletId\": \"{{gandalfWalletId}}\",\n  \"address\": {\n    \"line1\": \"1 Rue du Palais\",\n    \"city\": \"Minas Tirith\",\n    \"postalCode\": \"75001\",\n    \"countryCode\": \"FRA\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              }
            },
            {
              "name": "[Error] Create physical card — missing address",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 400', () => pm.response.to.have.status(400));"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/cards",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards"]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"holderId\": \"{{gandalfHolderId}}\",\n  \"cardProgramId\": \"{{threddVzvfrProgramId}}\",\n  \"controlGroupId\": \"{{threddKycFullControlGroupId}}\",\n  \"isVirtual\": false\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              }
            },
            {
              "name": "[Error] Create card — wrong API key",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 401', () => pm.response.to.have.status(401));"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "auth": {
                  "type": "apikey",
                  "apikey": [
                    {
                      "key": "key",
                      "value": "X-Api-Key",
                      "type": "string"
                    },
                    {
                      "key": "value",
                      "value": "wrong-api-key",
                      "type": "string"
                    },
                    {
                      "key": "in",
                      "value": "header",
                      "type": "string"
                    }
                  ]
                },
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/cards",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards"]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"holderId\": \"{{gandalfHolderId}}\",\n  \"cardProgramId\": \"{{threddVzvfrProgramId}}\",\n  \"controlGroupId\": \"{{threddKycFullControlGroupId}}\",\n  \"isVirtual\": true\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              }
            }
          ]
        },
        {
          "name": "Get card",
          "item": [
            {
              "name": "Get card by public token (Frodo)",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 200', () => pm.response.to.have.status(200));",
                      "pm.test('Response is the requested card', () => {",
                      "    const body = pm.response.json();",
                      "    pm.expect(body.publicToken).to.eql(pm.collectionVariables.get('frodoPublicToken'));",
                      "});"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "GET",
                "url": {
                  "raw": "{{baseUrl}}/cards/{{frodoPublicToken}}",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards", "{{frodoPublicToken}}"]
                }
              }
            },
            {
              "name": "Get card PIN (Frodo)",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 200', () => pm.response.to.have.status(200));",
                      "pm.test('Response contains pin', () => {",
                      "    const body = pm.response.json();",
                      "    pm.expect(body.pin).to.be.a('string');",
                      "});"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "GET",
                "url": {
                  "raw": "{{baseUrl}}/cards/{{frodoPublicToken}}/pin",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards", "{{frodoPublicToken}}", "pin"]
                }
              }
            },
            {
              "name": "[Error] Get card — wrong API key",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 401', () => pm.response.to.have.status(401));"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "auth": {
                  "type": "apikey",
                  "apikey": [
                    { "key": "key", "value": "X-Api-Key", "type": "string" },
                    { "key": "value", "value": "wrong-api-key", "type": "string" },
                    { "key": "in", "value": "header", "type": "string" }
                  ]
                },
                "method": "GET",
                "url": {
                  "raw": "{{baseUrl}}/cards/{{frodoPublicToken}}",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards", "{{frodoPublicToken}}"]
                }
              }
            }
          ]
        },
        {
          "name": "Activate card",
          "item": [
            {
              "name": "Activate card",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 200/201', () => pm.expect([200, 201]).to.include(pm.response.code));",
                      "pm.test('activatedAt is set', () => {",
                      "    const body = pm.response.json();",
                      "    pm.expect(body.activatedAt).to.not.eql(null);",
                      "});"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "POST",
                "url": {
                  "raw": "{{baseUrl}}/cards/{{frodoPublicToken}}/activate",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards", "{{frodoPublicToken}}", "activate"]
                }
              }
            }
          ]
        },
        {
          "name": "Lock / unlock card",
          "item": [
            {
              "name": "Lock card (locked)",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 200', () => pm.response.to.have.status(200));",
                      "pm.test('Card is locked', () => {",
                      "    const body = pm.response.json();",
                      "    pm.expect(body.lockStatus).to.eql('locked');",
                      "});"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "PATCH",
                "header": [
                  { "key": "Content-Type", "value": "application/json" }
                ],
                "url": {
                  "raw": "{{baseUrl}}/cards/{{frodoPublicToken}}/lock-status",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards", "{{frodoPublicToken}}", "lock-status"]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"lockStatus\": \"locked\"\n}",
                  "options": { "raw": { "language": "json" } }
                }
              }
            },
            {
              "name": "Unlock card",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 200', () => pm.response.to.have.status(200));",
                      "pm.test('Card is unlocked', () => {",
                      "    const body = pm.response.json();",
                      "    pm.expect(body.lockStatus).to.eql('unlocked');",
                      "});"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "PATCH",
                "header": [
                  { "key": "Content-Type", "value": "application/json" }
                ],
                "url": {
                  "raw": "{{baseUrl}}/cards/{{frodoPublicToken}}/lock-status",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards", "{{frodoPublicToken}}", "lock-status"]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"lockStatus\": \"unlocked\"\n}",
                  "options": { "raw": { "language": "json" } }
                }
              }
            },
            {
              "name": "Report card lost",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 200', () => pm.response.to.have.status(200));",
                      "pm.test('Card is lost', () => {",
                      "    const body = pm.response.json();",
                      "    pm.expect(body.lockStatus).to.eql('lost');",
                      "});"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "PATCH",
                "header": [
                  { "key": "Content-Type", "value": "application/json" }
                ],
                "url": {
                  "raw": "{{baseUrl}}/cards/{{frodoPublicToken}}/lock-status",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards", "{{frodoPublicToken}}", "lock-status"]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"lockStatus\": \"lost\"\n}",
                  "options": { "raw": { "language": "json" } }
                }
              }
            },
            {
              "name": "[Error] Lock card — invalid status",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 400', () => pm.response.to.have.status(400));"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "PATCH",
                "header": [
                  { "key": "Content-Type", "value": "application/json" }
                ],
                "url": {
                  "raw": "{{baseUrl}}/cards/{{frodoPublicToken}}/lock-status",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards", "{{frodoPublicToken}}", "lock-status"]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"lockStatus\": \"broken\"\n}",
                  "options": { "raw": { "language": "json" } }
                }
              }
            }
          ]
        },
        {
          "name": "Update card allow flags",
          "item": [
            {
              "name": "Allow flags — disable ATM + online",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 200', () => pm.response.to.have.status(200));",
                      "pm.test('Flags updated', () => {",
                      "    const body = pm.response.json();",
                      "    pm.expect(body.allowAtm).to.eql(false);",
                      "    pm.expect(body.allowOnline).to.eql(false);",
                      "});"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "PATCH",
                "header": [
                  { "key": "Content-Type", "value": "application/json" }
                ],
                "url": {
                  "raw": "{{baseUrl}}/cards/{{frodoPublicToken}}/allow",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards", "{{frodoPublicToken}}", "allow"]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"allowAtm\": false,\n  \"allowOnline\": false\n}",
                  "options": { "raw": { "language": "json" } }
                }
              }
            },
            {
              "name": "Allow flags — enable contactless + international",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 200', () => pm.response.to.have.status(200));",
                      "pm.test('Flags updated', () => {",
                      "    const body = pm.response.json();",
                      "    pm.expect(body.allowContactless).to.eql(true);",
                      "    pm.expect(body.allowInternational).to.eql(true);",
                      "});"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "PATCH",
                "header": [
                  { "key": "Content-Type", "value": "application/json" }
                ],
                "url": {
                  "raw": "{{baseUrl}}/cards/{{frodoPublicToken}}/allow",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards", "{{frodoPublicToken}}", "allow"]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"allowContactless\": true,\n  \"allowInternational\": true\n}",
                  "options": { "raw": { "language": "json" } }
                }
              }
            },
            {
              "name": "Allow flags — full update (all true)",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 200', () => pm.response.to.have.status(200));",
                      "pm.test('All flags enabled', () => {",
                      "    const body = pm.response.json();",
                      "    pm.expect(body.allowAtm).to.eql(true);",
                      "    pm.expect(body.allowContactless).to.eql(true);",
                      "    pm.expect(body.allowOnline).to.eql(true);",
                      "    pm.expect(body.allowInternational).to.eql(true);",
                      "});"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "PATCH",
                "header": [
                  { "key": "Content-Type", "value": "application/json" }
                ],
                "url": {
                  "raw": "{{baseUrl}}/cards/{{frodoPublicToken}}/allow",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards", "{{frodoPublicToken}}", "allow"]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"allowAtm\": true,\n  \"allowContactless\": true,\n  \"allowOnline\": true,\n  \"allowInternational\": true\n}",
                  "options": { "raw": { "language": "json" } }
                }
              }
            },
            {
              "name": "[Error] Allow flags — invalid type",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 400', () => pm.response.to.have.status(400));"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "PATCH",
                "header": [
                  { "key": "Content-Type", "value": "application/json" }
                ],
                "url": {
                  "raw": "{{baseUrl}}/cards/{{frodoPublicToken}}/allow",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards", "{{frodoPublicToken}}", "allow"]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"allowAtm\": \"yes\"\n}",
                  "options": { "raw": { "language": "json" } }
                }
              }
            }
          ]
        },
        {
          "name": "Update card control groups",
          "item": [
            {
              "name": "Update control group (kyc_light)",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 200', () => pm.response.to.have.status(200));",
                      "pm.test('Control group updated', () => {",
                      "    const body = pm.response.json();",
                      "    pm.expect(body.controlGroupId).to.eql(pm.collectionVariables.get('threddKycLightControlGroupId'));",
                      "});"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "PATCH",
                "header": [
                  { "key": "Content-Type", "value": "application/json" }
                ],
                "url": {
                  "raw": "{{baseUrl}}/cards/{{frodoPublicToken}}/control-groups",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards", "{{frodoPublicToken}}", "control-groups"]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"controlGroupId\": \"{{threddKycLightControlGroupId}}\"\n}",
                  "options": { "raw": { "language": "json" } }
                }
              }
            },
            {
              "name": "Update control group (kyc_full)",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 200', () => pm.response.to.have.status(200));",
                      "pm.test('Control group updated', () => {",
                      "    const body = pm.response.json();",
                      "    pm.expect(body.controlGroupId).to.eql(pm.collectionVariables.get('threddKycFullControlGroupId'));",
                      "});"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "PATCH",
                "header": [
                  { "key": "Content-Type", "value": "application/json" }
                ],
                "url": {
                  "raw": "{{baseUrl}}/cards/{{frodoPublicToken}}/control-groups",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards", "{{frodoPublicToken}}", "control-groups"]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"controlGroupId\": \"{{threddKycFullControlGroupId}}\"\n}",
                  "options": { "raw": { "language": "json" } }
                }
              }
            },
            {
              "name": "[Error] Update control group — invalid uuid",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status 400', () => pm.response.to.have.status(400));"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "PATCH",
                "header": [
                  { "key": "Content-Type", "value": "application/json" }
                ],
                "url": {
                  "raw": "{{baseUrl}}/cards/{{frodoPublicToken}}/control-groups",
                  "host": ["{{baseUrl}}"],
                  "path": ["cards", "{{frodoPublicToken}}", "control-groups"]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"controlGroupId\": \"not-a-uuid\"\n}",
                  "options": { "raw": { "language": "json" } }
                }
              }
            }
          ]
        }
      ]
    },
    {
      "name": "Card Programs",
      "item": [
        {
          "name": "Create card program",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 201', () => pm.response.to.have.status(201));",
                  "pm.test('Response has card program id', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.id).to.be.a('string');",
                  "    pm.expect(body.partnerId).to.be.a('string');",
                  "    pm.expect(body.name).to.eql('My new EUR program');",
                  "    pm.collectionVariables.set('createdCardProgramId', body.id);",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-programs",
              "host": ["{{baseUrl}}"],
              "path": ["card-programs"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"cardProcessorId\": \"{{threddProcessorId}}\",\n  \"cardProductReference\": \"b0010000-0000-4000-8000-000000000099\",\n  \"defaultCardDesignReference\": \"b0020000-0000-4000-8000-000000000099\",\n  \"allowedCardDesignReferences\": [\n    \"b0020000-0000-4000-8000-000000000099\",\n    \"b0020000-0000-4000-8000-000000000098\"\n  ],\n  \"name\": \"My new EUR program\",\n  \"currencyCode\": \"EUR\",\n  \"countryCode\": \"FR\",\n  \"allowVirtual\": true,\n  \"allowPhysical\": true,\n  \"allowAtm\": false,\n  \"allowContactless\": true,\n  \"allowOnline\": true,\n  \"allowInternational\": true\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "Create card program with explicit ID",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 201', () => pm.response.to.have.status(201));",
                  "pm.test('Response uses the requested id', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.id).to.eql('a1a2a3a4-0000-4000-8000-000000000777');",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-programs",
              "host": ["{{baseUrl}}"],
              "path": ["card-programs"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"id\": \"a1a2a3a4-0000-4000-8000-000000000777\",\n  \"cardProcessorId\": \"{{threddProcessorId}}\",\n  \"cardProductReference\": \"b0010000-0000-4000-8000-000000000097\",\n  \"defaultCardDesignReference\": \"b0020000-0000-4000-8000-000000000097\",\n  \"name\": \"Program with explicit id\",\n  \"currencyCode\": \"EUR\",\n  \"countryCode\": \"FR\",\n  \"allowVirtual\": true,\n  \"allowPhysical\": false\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "[Error] Create card program — unknown processor",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 404', () => pm.response.to.have.status(404));"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-programs",
              "host": ["{{baseUrl}}"],
              "path": ["card-programs"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"cardProcessorId\": \"00000000-0000-4000-8000-000000000000\",\n  \"cardProductReference\": \"b0010000-0000-4000-8000-000000000096\",\n  \"defaultCardDesignReference\": \"b0020000-0000-4000-8000-000000000096\",\n  \"name\": \"Bad processor\",\n  \"currencyCode\": \"EUR\",\n  \"countryCode\": \"FR\"\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "[Error] Create card program — missing name",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 400', () => pm.response.to.have.status(400));"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-programs",
              "host": ["{{baseUrl}}"],
              "path": ["card-programs"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"cardProcessorId\": \"{{threddProcessorId}}\",\n  \"cardProductReference\": \"b0010000-0000-4000-8000-000000000095\",\n  \"defaultCardDesignReference\": \"b0020000-0000-4000-8000-000000000095\",\n  \"currencyCode\": \"EUR\",\n  \"countryCode\": \"FR\"\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "List card programs (paginated)",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));",
                  "pm.test('Response is paginated', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.data).to.be.an('array');",
                  "    pm.expect(body.total).to.be.a('number');",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/card-programs?limit=20&offset=0",
              "host": ["{{baseUrl}}"],
              "path": ["card-programs"],
              "query": [
                { "key": "limit", "value": "20" },
                { "key": "offset", "value": "0" }
              ]
            }
          }
        },
        {
          "name": "Get card program by ID",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));",
                  "pm.test('Response is the requested program', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.id).to.eql(pm.collectionVariables.get('createdCardProgramId'));",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/card-programs/{{createdCardProgramId}}",
              "host": ["{{baseUrl}}"],
              "path": ["card-programs", "{{createdCardProgramId}}"]
            }
          }
        },
        {
          "name": "[Error] Get card program — not found",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 404', () => pm.response.to.have.status(404));"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/card-programs/00000000-0000-4000-8000-0000000000ff",
              "host": ["{{baseUrl}}"],
              "path": ["card-programs", "00000000-0000-4000-8000-0000000000ff"]
            }
          }
        },
        {
          "name": "Update card program",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));",
                  "pm.test('Response reflects the update', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.name).to.eql('My updated EUR program');",
                  "    pm.expect(body.allowAtm).to.eql(true);",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "PATCH",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-programs/{{createdCardProgramId}}",
              "host": ["{{baseUrl}}"],
              "path": ["card-programs", "{{createdCardProgramId}}"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"My updated EUR program\",\n  \"allowAtm\": true,\n  \"allowInternational\": false\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "Delete card program",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 204', () => pm.response.to.have.status(204));"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/card-programs/{{createdCardProgramId}}",
              "host": ["{{baseUrl}}"],
              "path": ["card-programs", "{{createdCardProgramId}}"]
            }
          }
        }
      ]
    },
    {
      "name": "Card Control Groups",
      "item": [
        {
          "name": "Create card control group",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 201', () => pm.response.to.have.status(201));",
                  "pm.test('Response has control group id', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.id).to.be.a('string');",
                  "    pm.expect(body.cardProgramId).to.eql(pm.collectionVariables.get('threddVzvfrProgramId'));",
                  "    pm.expect(body.name).to.eql('my_control_group');",
                  "    pm.collectionVariables.set('createdCardControlGroupId', body.id);",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-control-groups",
              "host": ["{{baseUrl}}"],
              "path": ["card-control-groups"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"cardProgramId\": \"{{threddVzvfrProgramId}}\",\n  \"name\": \"my_control_group\",\n  \"issuerConfiguration\": {\n    \"limitsGroup\": 2672,\n    \"usageGroup\": 1040,\n    \"mccGroup\": 1000182\n  }\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "Create card control group with explicit ID",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 201', () => pm.response.to.have.status(201));",
                  "pm.test('Response uses the requested id', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.id).to.eql('c2c2c2c2-0000-4000-8000-000000000777');",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-control-groups",
              "host": ["{{baseUrl}}"],
              "path": ["card-control-groups"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"id\": \"c2c2c2c2-0000-4000-8000-000000000777\",\n  \"cardProgramId\": \"{{threddVzvfrProgramId}}\",\n  \"name\": \"control_group_with_explicit_id\"\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "[Error] Create control group — unknown program",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 404', () => pm.response.to.have.status(404));"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-control-groups",
              "host": ["{{baseUrl}}"],
              "path": ["card-control-groups"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"cardProgramId\": \"00000000-0000-4000-8000-000000000000\",\n  \"name\": \"orphan_group\"\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "[Error] Create control group — missing name",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 400', () => pm.response.to.have.status(400));"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-control-groups",
              "host": ["{{baseUrl}}"],
              "path": ["card-control-groups"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"cardProgramId\": \"{{threddVzvfrProgramId}}\"\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "List card control groups (paginated)",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));",
                  "pm.test('Response is paginated', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.data).to.be.an('array');",
                  "    pm.expect(body.total).to.be.a('number');",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/card-control-groups?limit=20&offset=0",
              "host": ["{{baseUrl}}"],
              "path": ["card-control-groups"],
              "query": [
                { "key": "limit", "value": "20" },
                { "key": "offset", "value": "0" },
                {
                  "key": "cardProgramId",
                  "value": "{{threddVzvfrProgramId}}",
                  "disabled": true
                }
              ]
            }
          }
        },
        {
          "name": "Get card control group by ID",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));",
                  "pm.test('Response is the requested control group', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.id).to.eql(pm.collectionVariables.get('createdCardControlGroupId'));",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/card-control-groups/{{createdCardControlGroupId}}",
              "host": ["{{baseUrl}}"],
              "path": ["card-control-groups", "{{createdCardControlGroupId}}"]
            }
          }
        },
        {
          "name": "[Error] Get card control group — not found",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 404', () => pm.response.to.have.status(404));"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/card-control-groups/00000000-0000-4000-8000-0000000000ff",
              "host": ["{{baseUrl}}"],
              "path": [
                "card-control-groups",
                "00000000-0000-4000-8000-0000000000ff"
              ]
            }
          }
        },
        {
          "name": "Update card control group",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));",
                  "pm.test('Response reflects the update', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.name).to.eql('my_control_group_updated');",
                  "    pm.expect(body.issuerConfiguration.limitsGroup).to.eql(3000);",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "PATCH",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-control-groups/{{createdCardControlGroupId}}",
              "host": ["{{baseUrl}}"],
              "path": ["card-control-groups", "{{createdCardControlGroupId}}"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"my_control_group_updated\",\n  \"issuerConfiguration\": {\n    \"limitsGroup\": 3000\n  }\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "Delete card control group",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 204', () => pm.response.to.have.status(204));"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/card-control-groups/{{createdCardControlGroupId}}",
              "host": ["{{baseUrl}}"],
              "path": ["card-control-groups", "{{createdCardControlGroupId}}"]
            }
          }
        }
      ]
    },
    {
      "name": "Card Payment Processing (Thredd EHI)",
      "description": "Examples of inbound Thredd EHI (External Host Interface) webhooks the processor sends to `POST /card-payment-processing/thredd`.\n\nThis endpoint is an unauthenticated machine-to-machine webhook (no `X-Api-Key`), so requests in this folder override the collection auth with **No Auth**.\n\nThe handler always replies with HTTP 200 and an `Acknowledgement` of `\"1\"`; the decision is carried by `Responsestatus` (a Thredd response code, e.g. `00` approved, `05` do not honour, `54` expired/unknown card, `57` transaction not permitted to cardholder).\n\nHow the request is interpreted:\n- **Operation** comes from `Txn_Type` (+ `MTID`): `A` = authorization (or presentment when `MTID` is `1240`), `P`/`N` = presentment/settlement, `D` = reversal.\n- **Channel** comes from `Proc_Code` (first two digits `01` = ATM) and `POS_Data_DE22` (PAN entry `01`/`81` = web/online, `07`/`08`/`91`/`92` = contactless).\n- **International** is derived by comparing `Merch_Country` to the card program country.\n- **Amounts** use `Bill_Amt` (+ pads/fees) with `Bill_Ccy` as the ISO 4217 numeric code (e.g. `978` = EUR).\n\nThe examples target the seeded Frodo card (`{{frodoPublicToken}}`, program vzvfr: FR / EUR, `allowAtm=false`, `allowContactless=true`, `allowOnline=true`). Approvals on the wallet path still depend on the available balance, so those tests only assert that the request was acknowledged.\n\n@see https://docs.thredd.com/ehi-json/Content/Requirements/GetTransaction_Message.htm",
      "auth": { "type": "noauth" },
      "item": [
        {
          "name": "Authorization — online purchase (approved path)",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));",
                  "pm.test('Webhook acknowledged', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.Acknowledgement).to.eql('1');",
                  "    pm.expect(body.Responsestatus).to.be.a('string');",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-payment-processing/thredd",
              "host": ["{{baseUrl}}"],
              "path": ["card-payment-processing", "thredd"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"Token\": \"{{frodoPublicToken}}\",\n  \"TXn_ID\": \"100000001\",\n  \"Trans_link\": \"100000001\",\n  \"Ret_Ref_No_DE37\": \"000000100001\",\n  \"Txn_GPS_Date\": \"2026-06-08 10:15:00\",\n  \"Txn_Type\": \"A\",\n  \"MTID\": \"0100\",\n  \"Bill_Amt\": \"10.00\",\n  \"Bill_Ccy\": \"978\",\n  \"Merch_Name_DE43\": \"ACME STORE PARIS\",\n  \"MCC_Code\": \"5411\",\n  \"Merch_Country\": \"FR\",\n  \"Proc_Code\": \"000000\",\n  \"POS_Data_DE22\": \"0100000000\",\n  \"Txn_Stat_Code\": \"I\",\n  \"SendingAttemptCount\": \"0\",\n  \"Note\": \"\"\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "Authorization — contactless purchase (approved path)",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));",
                  "pm.test('Webhook acknowledged', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.Acknowledgement).to.eql('1');",
                  "    pm.expect(body.Responsestatus).to.be.a('string');",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-payment-processing/thredd",
              "host": ["{{baseUrl}}"],
              "path": ["card-payment-processing", "thredd"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"Token\": \"{{frodoPublicToken}}\",\n  \"TXn_ID\": \"100000002\",\n  \"Trans_link\": \"100000002\",\n  \"Ret_Ref_No_DE37\": \"000000100002\",\n  \"Txn_GPS_Date\": \"2026-06-08 10:20:00\",\n  \"Txn_Type\": \"A\",\n  \"MTID\": \"0100\",\n  \"Bill_Amt\": \"4.50\",\n  \"Bill_Ccy\": \"978\",\n  \"Merch_Name_DE43\": \"BOULANGERIE DU COIN\",\n  \"MCC_Code\": \"5812\",\n  \"Merch_Country\": \"FR\",\n  \"Proc_Code\": \"000000\",\n  \"POS_Data_DE22\": \"0700000000\",\n  \"Txn_Stat_Code\": \"I\",\n  \"SendingAttemptCount\": \"0\",\n  \"Note\": \"\"\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "Authorization — ATM withdrawal (declined: channel not permitted)",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));",
                  "pm.test('Declined — transaction not permitted to cardholder (57)', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.Acknowledgement).to.eql('1');",
                  "    pm.expect(body.Responsestatus).to.eql('57');",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-payment-processing/thredd",
              "host": ["{{baseUrl}}"],
              "path": ["card-payment-processing", "thredd"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"Token\": \"{{frodoPublicToken}}\",\n  \"TXn_ID\": \"100000003\",\n  \"Trans_link\": \"100000003\",\n  \"Ret_Ref_No_DE37\": \"000000100003\",\n  \"Txn_GPS_Date\": \"2026-06-08 10:25:00\",\n  \"Txn_Type\": \"A\",\n  \"MTID\": \"0100\",\n  \"Bill_Amt\": \"50.00\",\n  \"Bill_Ccy\": \"978\",\n  \"Merch_Name_DE43\": \"ATM BNP PARIS\",\n  \"MCC_Code\": \"6011\",\n  \"Merch_Country\": \"FR\",\n  \"Proc_Code\": \"010000\",\n  \"POS_Data_DE22\": \"0500000000\",\n  \"Txn_Stat_Code\": \"I\",\n  \"SendingAttemptCount\": \"0\",\n  \"Note\": \"\"\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "Authorization — incorrect PIN (declined)",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));",
                  "pm.test('Declined — transaction not permitted to cardholder (57)', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.Acknowledgement).to.eql('1');",
                  "    pm.expect(body.Responsestatus).to.eql('57');",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-payment-processing/thredd",
              "host": ["{{baseUrl}}"],
              "path": ["card-payment-processing", "thredd"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"Token\": \"{{frodoPublicToken}}\",\n  \"TXn_ID\": \"100000004\",\n  \"Trans_link\": \"100000004\",\n  \"Ret_Ref_No_DE37\": \"000000100004\",\n  \"Txn_GPS_Date\": \"2026-06-08 10:30:00\",\n  \"Txn_Type\": \"A\",\n  \"MTID\": \"0100\",\n  \"Bill_Amt\": \"25.00\",\n  \"Bill_Ccy\": \"978\",\n  \"Merch_Name_DE43\": \"SUPERMARCHE PARIS\",\n  \"MCC_Code\": \"5411\",\n  \"Merch_Country\": \"FR\",\n  \"Proc_Code\": \"000000\",\n  \"POS_Data_DE22\": \"0500000000\",\n  \"Txn_Stat_Code\": \"I\",\n  \"SendingAttemptCount\": \"0\",\n  \"Note\": \"Incorrect PIN\"\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "Authorization — SCA required (declined)",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));",
                  "pm.test('Declined — transaction not permitted to cardholder (57)', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.Acknowledgement).to.eql('1');",
                  "    pm.expect(body.Responsestatus).to.eql('57');",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-payment-processing/thredd",
              "host": ["{{baseUrl}}"],
              "path": ["card-payment-processing", "thredd"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"Token\": \"{{frodoPublicToken}}\",\n  \"TXn_ID\": \"100000005\",\n  \"Trans_link\": \"100000005\",\n  \"Ret_Ref_No_DE37\": \"000000100005\",\n  \"Txn_GPS_Date\": \"2026-06-08 10:35:00\",\n  \"Txn_Type\": \"A\",\n  \"MTID\": \"0100\",\n  \"Bill_Amt\": \"120.00\",\n  \"Bill_Ccy\": \"978\",\n  \"Merch_Name_DE43\": \"ONLINE SHOP EU\",\n  \"MCC_Code\": \"5999\",\n  \"Merch_Country\": \"FR\",\n  \"Proc_Code\": \"000000\",\n  \"POS_Data_DE22\": \"0100000000\",\n  \"Txn_Stat_Code\": \"I\",\n  \"SendingAttemptCount\": \"0\",\n  \"Note\": \"Requires SCA\"\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "Presentment — settlement",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));",
                  "pm.test('Webhook acknowledged', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.Acknowledgement).to.eql('1');",
                  "    pm.expect(body.Responsestatus).to.be.a('string');",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-payment-processing/thredd",
              "host": ["{{baseUrl}}"],
              "path": ["card-payment-processing", "thredd"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"Token\": \"{{frodoPublicToken}}\",\n  \"TXn_ID\": \"100000001\",\n  \"Trans_link\": \"100000001\",\n  \"Ret_Ref_No_DE37\": \"000000100001\",\n  \"Txn_GPS_Date\": \"2026-06-08 12:00:00\",\n  \"Txn_Type\": \"P\",\n  \"MTID\": \"1240\",\n  \"Bill_Amt\": \"10.00\",\n  \"Bill_Ccy\": \"978\",\n  \"Merch_Name_DE43\": \"ACME STORE PARIS\",\n  \"MCC_Code\": \"5411\",\n  \"Merch_Country\": \"FR\",\n  \"Proc_Code\": \"000000\",\n  \"POS_Data_DE22\": \"0100000000\",\n  \"Txn_Stat_Code\": \"C\"\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "Reversal",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));",
                  "pm.test('Webhook acknowledged', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.Acknowledgement).to.eql('1');",
                  "    pm.expect(body.Responsestatus).to.be.a('string');",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-payment-processing/thredd",
              "host": ["{{baseUrl}}"],
              "path": ["card-payment-processing", "thredd"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"Token\": \"{{frodoPublicToken}}\",\n  \"TXn_ID\": \"100000001\",\n  \"Trans_link\": \"100000001\",\n  \"Ret_Ref_No_DE37\": \"000000100001\",\n  \"Txn_GPS_Date\": \"2026-06-08 13:00:00\",\n  \"Txn_Type\": \"D\",\n  \"MTID\": \"0420\",\n  \"Bill_Amt\": \"10.00\",\n  \"Bill_Ccy\": \"978\",\n  \"Merch_Name_DE43\": \"ACME STORE PARIS\",\n  \"MCC_Code\": \"5411\",\n  \"Merch_Country\": \"FR\",\n  \"Proc_Code\": \"000000\",\n  \"POS_Data_DE22\": \"0100000000\",\n  \"Txn_Stat_Code\": \"R\"\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "[Error] Unknown card token (declined: expired card)",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));",
                  "pm.test('Declined — expired/unknown card (54)', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.Acknowledgement).to.eql('1');",
                  "    pm.expect(body.Responsestatus).to.eql('54');",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-payment-processing/thredd",
              "host": ["{{baseUrl}}"],
              "path": ["card-payment-processing", "thredd"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"Token\": \"000000000\",\n  \"TXn_ID\": \"100000099\",\n  \"Trans_link\": \"100000099\",\n  \"Ret_Ref_No_DE37\": \"000000100099\",\n  \"Txn_GPS_Date\": \"2026-06-08 10:40:00\",\n  \"Txn_Type\": \"A\",\n  \"MTID\": \"0100\",\n  \"Bill_Amt\": \"10.00\",\n  \"Bill_Ccy\": \"978\",\n  \"Merch_Name_DE43\": \"ACME STORE PARIS\",\n  \"MCC_Code\": \"5411\",\n  \"Merch_Country\": \"FR\",\n  \"Proc_Code\": \"000000\",\n  \"POS_Data_DE22\": \"0100000000\",\n  \"Txn_Stat_Code\": \"I\",\n  \"SendingAttemptCount\": \"0\",\n  \"Note\": \"\"\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "[Error] Unknown operation (do not honour)",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));",
                  "pm.test('Do not honour (05)', () => {",
                  "    const body = pm.response.json();",
                  "    pm.expect(body.Acknowledgement).to.eql('1');",
                  "    pm.expect(body.Responsestatus).to.eql('05');",
                  "});"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "url": {
              "raw": "{{baseUrl}}/card-payment-processing/thredd",
              "host": ["{{baseUrl}}"],
              "path": ["card-payment-processing", "thredd"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"Token\": \"{{frodoPublicToken}}\",\n  \"TXn_ID\": \"100000100\",\n  \"Trans_link\": \"100000100\",\n  \"Ret_Ref_No_DE37\": \"000000100100\",\n  \"Txn_GPS_Date\": \"2026-06-08 10:45:00\",\n  \"Txn_Type\": \"X\",\n  \"MTID\": \"9999\",\n  \"Bill_Amt\": \"10.00\",\n  \"Bill_Ccy\": \"978\",\n  \"Merch_Name_DE43\": \"ACME STORE PARIS\",\n  \"MCC_Code\": \"5411\",\n  \"Merch_Country\": \"FR\",\n  \"Proc_Code\": \"000000\",\n  \"POS_Data_DE22\": \"0100000000\"\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        }
      ]
    }
  ]
}
