{
  "info": {
    "_postman_id": "42977f86-5bb3-41cb-bd3b-e4d85bf50501",
    "name": "ccarctic Merchant Payment API",
    "description": "Postman collection for merchant integration testing against https://ccarctic.com. Set your API credentials and card test data locally in Postman. Do not share PAN/CVV. The collection saves payment_id/reference_id automatically after payment creation.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{api_key}}",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://ccarctic.com"
    },
    {
      "key": "api_key",
      "value": ""
    },
    {
      "key": "request_signing_enabled",
      "value": "false"
    },
    {
      "key": "request_key",
      "value": ""
    },
    {
      "key": "payment_id",
      "value": ""
    },
    {
      "key": "reference_id",
      "value": ""
    },
    {
      "key": "amount",
      "value": "30"
    },
    {
      "key": "currency",
      "value": "AED"
    },
    {
      "key": "customer_phone",
      "value": "971 501234567"
    },
    {
      "key": "card_number",
      "value": ""
    },
    {
      "key": "cardholder_name",
      "value": "JOHN SMITH"
    },
    {
      "key": "card_cvv",
      "value": ""
    },
    {
      "key": "card_expiry_month",
      "value": "12"
    },
    {
      "key": "card_expiry_year",
      "value": "2030"
    },
    {
      "key": "success_url",
      "value": "https://www.google.com/?result=success"
    },
    {
      "key": "fail_url",
      "value": "https://www.google.com/?result=fail"
    },
    {
      "key": "error_url",
      "value": "https://www.google.com/?result=error"
    },
    {
      "key": "webhook_url",
      "value": "",
      "description": "Optional per-payment webhook URL. Highest priority. Leave blank to use the partner default webhook configured in Dashboard → Integration; if no default exists, no partner webhook is sent."
    }
  ],
  "item": [
    {
      "name": "01 - Authentication",
      "item": [
        {
          "name": "List payments - valid API key",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/payments?limit=10",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "payments"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "10"
                }
              ]
            },
            "description": "First smoke test. Expected: HTTP 200 and only payments belonging to this partner."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 200', function () { pm.response.to.have.status(200); });",
                  "pm.test('JSON response', function () { pm.response.to.be.json; });"
                ]
              }
            }
          ]
        },
        {
          "name": "List payments - invalid API key (expect 401)",
          "request": {
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "INVALID_API_KEY",
                  "type": "string"
                }
              ]
            },
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/payments?limit=10",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "payments"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "10"
                }
              ]
            },
            "description": "Negative authorization test. Expected: HTTP 401."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 401', function () { pm.response.to.have.status(401); });"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "02 - Payments",
      "item": [
        {
          "name": "Create BASIC_CARD deposit",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const signingEnabled = String(pm.collectionVariables.get('request_signing_enabled') || 'false').toLowerCase() === 'true';",
                  "if (!signingEnabled) {",
                  "    pm.request.headers.remove('Signature');",
                  "} else {",
                  "    const requestKey = pm.collectionVariables.get('request_key');",
                  "    if (!requestKey) { throw new Error('request_key is empty while request_signing_enabled=true'); }",
                  "    const rawBody = pm.variables.replaceIn(pm.request.body.raw);",
                  "    const CryptoJS = require('crypto-js');",
                  "    const signature = CryptoJS.HmacSHA256(rawBody, requestKey).toString(CryptoJS.enc.Hex);",
                  "    pm.request.headers.upsert({ key: 'Signature', value: signature });",
                  "}"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 200', function () { pm.response.to.have.status(200); });",
                  "pm.test('JSON response', function () { pm.response.to.be.json; });",
                  "const json = pm.response.json();",
                  "pm.test('Payment result exists', function () { pm.expect(json.result).to.be.an('object'); });",
                  "if (json.result && json.result.id) pm.collectionVariables.set('payment_id', json.result.id);",
                  "if (json.result && json.result.referenceId) pm.collectionVariables.set('reference_id', json.result.referenceId);",
                  "pm.test('Public payment ID format', function () { pm.expect(json.result.id).to.match(/^TR-PROD-[A-Za-z0-9]+$/); });",
                  "pm.test('No provider/internal fields leaked', function () {",
                  "  const body = pm.response.text().toLowerCase();",
                  "  ['terminalname','shopname','externalrefs','routinggroup'].forEach(function(x){",
                  "    pm.expect(body, 'response contains forbidden value: ' + x).to.not.include(x);",
                  "  });",
                  "});",
                  "pm.test('CVV not returned', function () {",
                  "  const cvv = pm.collectionVariables.get('card_cvv');",
                  "  if (cvv) pm.expect(pm.response.text()).to.not.include(cvv);",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"referenceId\": \"postman-{{$timestamp}}\",\n  \"paymentType\": \"DEPOSIT\",\n  \"paymentMethod\": \"BASIC_CARD\",\n  \"amount\": {{amount}},\n  \"currency\": \"{{currency}}\",\n  \"customer\": {\n    \"firstName\": \"John\",\n    \"lastName\": \"Smith\",\n    \"email\": \"john.smith@example.com\",\n    \"phone\": \"{{customer_phone}}\"\n  },\n  \"billingAddress\": {\n    \"countryCode\": \"AE\",\n    \"city\": \"Dubai\",\n    \"addressLine1\": \"Sheikh Zayed Road 1\",\n    \"postalCode\": \"00000\"\n  },\n  \"card\": {\n    \"cardNumber\": \"{{card_number}}\",\n    \"cardholderName\": \"{{cardholder_name}}\",\n    \"cardSecurityCode\": \"{{card_cvv}}\",\n    \"expiryMonth\": \"{{card_expiry_month}}\",\n    \"expiryYear\": \"{{card_expiry_year}}\"\n  },\n  \"successUrl\": \"{{success_url}}\",\n  \"failUrl\": \"{{fail_url}}\",\n  \"errorUrl\": \"{{error_url}}\",\n  \"webhookUrl\": \"{{webhook_url}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/api/v1/payments",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "payments"
              ]
            },
            "description": "Creates a BASIC_CARD DEPOSIT. Fill card_number/card_cvv locally. The request can automatically add Signature when request_signing_enabled=true. Customer phone format: international number without leading +, for example `971 501234567`.\n\nWebhook priority: request `webhookUrl` → partner default in Dashboard → Integration → no partner webhook. The `webhook_url` collection variable is blank by default; blank means use the partner default when configured."
          }
        },
        {
          "name": "Get payment by ID",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/payments/{{payment_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "payments",
                "{{payment_id}}"
              ]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 200', function () { pm.response.to.have.status(200); });",
                  "pm.test('Correct payment id', function () {",
                  "  const json = pm.response.json();",
                  "  pm.expect(json.result.id).to.eql(pm.collectionVariables.get('payment_id'));",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "List latest payments",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/payments?limit=50",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "payments"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "50"
                }
              ]
            }
          }
        }
      ]
    },
    {
      "name": "03 - Webhooks",
      "item": [
        {
          "name": "Get payment webhook delivery status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/payments/{{payment_id}}/webhook",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "payments",
                "{{payment_id}}",
                "webhook"
              ]
            },
            "description": "Shows whether a webhook is configured and the latest delivery status for the selected payment."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 200', function () { pm.response.to.have.status(200); });",
                  "pm.test('JSON response', function () { pm.response.to.be.json; });"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "04 - Negative tests",
      "item": [
        {
          "name": "Get nonexistent payment",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/payments/TR-PROD-NOTFOUND123456789",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "payments",
                "TR-PROD-NOTFOUND123456789"
              ]
            },
            "description": "Negative lookup test. Expected: 404."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 404', function () { pm.response.to.have.status(404); });"
                ]
              }
            }
          ]
        }
      ]
    }
  ]
}
