{
  "info": {
    "name": "Absolut Pay — Merchant API v2",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "description": "Generated from public-api/v2/openapi.json and the shared request examples. Local desktop Postman. Confirmed API origin is included; credentials are empty. Business availability is not confirmed; obtain access and activation separately. API origin is independent of the documentation and hosted-payment-page origins. Set the lookup merchant_order_id to the exact value from your Create body. Query and path values are encoded once; outgoing raw UTF-8 body is signed without reserialization. Do not run the whole collection: Create sends one new business request."
  },
  "auth": {
    "type": "noauth"
  },
  "item": [
    {
      "name": "createPayinV2",
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          }
        ],
        "url": "{{api_base_url}}/api/v2/payins",
        "description": "createPayinV2\nSource: POST /api/v2/payins. Parameters are read from the local environment. Disable automatic redirects. After a lost Create response use the corresponding result lookup with the original merchant_order_id; do not create another payment.",
        "body": {
          "mode": "raw",
          "raw": "{\n  \"merchant_order_id\": \"shop-order-0001\",\n  \"amount\": \"15000.00\",\n  \"currency\": \"RUB\",\n  \"method_id\": 1,\n  \"mode\": \"h2h\",\n  \"traffic_type\": \"primary\",\n  \"payer\": {\n    \"id\": \"customer-1001\",\n    \"ip\": \"203.0.113.10\"\n  },\n  \"webhook_url\": \"https://merchant.example.invalid/webhooks/absolut-pay\"\n}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        }
      },
      "protocolProfileBehavior": {
        "followRedirects": false,
        "disableUrlEncoding": true
      },
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Local desktop Postman only. Never execute this signer in the documentation browser.",
              "const CryptoJS = require('crypto-js');",
              "try {",
              "  const config = {\"path\":\"/api/v2/payins\",\"parameters\":[]};",
              "  const base = String(pm.environment.get('api_base_url') || '').replace(/\\/$/, '');",
              "  if (!/^https:\\/\\/[A-Za-z0-9.-]+(?::[0-9]+)?$/.test(base) && !/^http:\\/\\/(?:localhost|127\\.0\\.0\\.1|\\[::1\\])(?::[0-9]+)?$/.test(base)) throw Error('Use an HTTPS API origin or local loopback HTTP origin.');",
              "  const token = pm.environment.get('api_token');",
              "  const secret = pm.environment.get('api_secret');",
              "  if (!token || !secret) throw Error('Set local-only API token and secret; never share or export populated credentials.');",
              "  let target = config.path;",
              "  const query = [];",
              "  for (const p of config.parameters) {",
              "    const value = String(pm.environment.get(p.variable) || '');",
              "    if (!value && p.required) throw Error('Missing required request parameter.');",
              "    if (!value) continue;",
              "    if (p.schema.pattern && !(new RegExp(p.schema.pattern)).test(value)) throw Error('Invalid request parameter.');",
              "    if (p.in === 'path') target = target.replace('{' + p.name + '}', encodeURIComponent(value));",
              "    else query.push(encodeURIComponent(p.name) + '=' + encodeURIComponent(value));",
              "  }",
              "  if (query.length) target += '?' + query.join('&');",
              "  pm.request.url.update(base + target);",
              "  let rawBody = '';",
              "  if (pm.request.body && pm.request.body.mode === 'raw') {",
              "    rawBody = pm.variables.replaceIn(pm.request.body.raw);",
              "    if (/{{[^}]+}}/.test(rawBody)) throw Error('Resolve every body variable before sending.');",
              "    JSON.parse(rawBody);",
              "    pm.request.body.update(rawBody);",
              "  }",
              "  const timestamp = String(Math.floor(Date.now() / 1000));",
              "  const nonce = pm.variables.replaceIn('{{$guid}}');",
              "  const payload = [timestamp, nonce, pm.request.method.toUpperCase(), target, rawBody].join('\\n');",
              "  const signature = CryptoJS.HmacSHA512(CryptoJS.enc.Utf8.parse(payload), CryptoJS.enc.Utf8.parse(secret)).toString(CryptoJS.enc.Hex);",
              "  for (const [key, value] of Object.entries({'X-API-Token': token, 'X-Timestamp': timestamp, 'X-Nonce': nonce, 'X-Signature': signature})) pm.request.headers.upsert({key, value});",
              "} catch (error) {",
              "  pm.execution.skipRequest();",
              "  throw error;",
              "}"
            ]
          }
        }
      ]
    },
    {
      "name": "lookupPayinRequestV2",
      "request": {
        "method": "GET",
        "header": [],
        "url": "{{api_base_url}}/api/v2/payins/result",
        "description": "lookupPayinRequestV2\nSource: GET /api/v2/payins/result. Parameters are read from the local environment. Disable automatic redirects. After a lost Create response use the corresponding result lookup with the original merchant_order_id; do not create another payment."
      },
      "protocolProfileBehavior": {
        "followRedirects": false,
        "disableUrlEncoding": true
      },
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Local desktop Postman only. Never execute this signer in the documentation browser.",
              "const CryptoJS = require('crypto-js');",
              "try {",
              "  const config = {\"path\":\"/api/v2/payins/result\",\"parameters\":[{\"name\":\"merchant_order_id\",\"in\":\"query\",\"required\":true,\"schema\":{\"type\":\"string\",\"minLength\":1,\"maxLength\":128},\"variable\":\"merchant_order_id\"}]};",
              "  const base = String(pm.environment.get('api_base_url') || '').replace(/\\/$/, '');",
              "  if (!/^https:\\/\\/[A-Za-z0-9.-]+(?::[0-9]+)?$/.test(base) && !/^http:\\/\\/(?:localhost|127\\.0\\.0\\.1|\\[::1\\])(?::[0-9]+)?$/.test(base)) throw Error('Use an HTTPS API origin or local loopback HTTP origin.');",
              "  const token = pm.environment.get('api_token');",
              "  const secret = pm.environment.get('api_secret');",
              "  if (!token || !secret) throw Error('Set local-only API token and secret; never share or export populated credentials.');",
              "  let target = config.path;",
              "  const query = [];",
              "  for (const p of config.parameters) {",
              "    const value = String(pm.environment.get(p.variable) || '');",
              "    if (!value && p.required) throw Error('Missing required request parameter.');",
              "    if (!value) continue;",
              "    if (p.schema.pattern && !(new RegExp(p.schema.pattern)).test(value)) throw Error('Invalid request parameter.');",
              "    if (p.in === 'path') target = target.replace('{' + p.name + '}', encodeURIComponent(value));",
              "    else query.push(encodeURIComponent(p.name) + '=' + encodeURIComponent(value));",
              "  }",
              "  if (query.length) target += '?' + query.join('&');",
              "  pm.request.url.update(base + target);",
              "  let rawBody = '';",
              "  if (pm.request.body && pm.request.body.mode === 'raw') {",
              "    rawBody = pm.variables.replaceIn(pm.request.body.raw);",
              "    if (/{{[^}]+}}/.test(rawBody)) throw Error('Resolve every body variable before sending.');",
              "    JSON.parse(rawBody);",
              "    pm.request.body.update(rawBody);",
              "  }",
              "  const timestamp = String(Math.floor(Date.now() / 1000));",
              "  const nonce = pm.variables.replaceIn('{{$guid}}');",
              "  const payload = [timestamp, nonce, pm.request.method.toUpperCase(), target, rawBody].join('\\n');",
              "  const signature = CryptoJS.HmacSHA512(CryptoJS.enc.Utf8.parse(payload), CryptoJS.enc.Utf8.parse(secret)).toString(CryptoJS.enc.Hex);",
              "  for (const [key, value] of Object.entries({'X-API-Token': token, 'X-Timestamp': timestamp, 'X-Nonce': nonce, 'X-Signature': signature})) pm.request.headers.upsert({key, value});",
              "} catch (error) {",
              "  pm.execution.skipRequest();",
              "  throw error;",
              "}"
            ]
          }
        }
      ]
    },
    {
      "name": "getPayinV2",
      "request": {
        "method": "GET",
        "header": [],
        "url": "{{api_base_url}}/api/v2/payins/{{payin_id}}",
        "description": "getPayinV2\nSource: GET /api/v2/payins/{id}. Parameters are read from the local environment. Disable automatic redirects. After a lost Create response use the corresponding result lookup with the original merchant_order_id; do not create another payment."
      },
      "protocolProfileBehavior": {
        "followRedirects": false,
        "disableUrlEncoding": true
      },
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Local desktop Postman only. Never execute this signer in the documentation browser.",
              "const CryptoJS = require('crypto-js');",
              "try {",
              "  const config = {\"path\":\"/api/v2/payins/{id}\",\"parameters\":[{\"name\":\"id\",\"in\":\"path\",\"required\":true,\"schema\":{\"type\":\"string\",\"pattern\":\"^ord_[1-9][0-9]*$\"},\"variable\":\"payin_id\"}]};",
              "  const base = String(pm.environment.get('api_base_url') || '').replace(/\\/$/, '');",
              "  if (!/^https:\\/\\/[A-Za-z0-9.-]+(?::[0-9]+)?$/.test(base) && !/^http:\\/\\/(?:localhost|127\\.0\\.0\\.1|\\[::1\\])(?::[0-9]+)?$/.test(base)) throw Error('Use an HTTPS API origin or local loopback HTTP origin.');",
              "  const token = pm.environment.get('api_token');",
              "  const secret = pm.environment.get('api_secret');",
              "  if (!token || !secret) throw Error('Set local-only API token and secret; never share or export populated credentials.');",
              "  let target = config.path;",
              "  const query = [];",
              "  for (const p of config.parameters) {",
              "    const value = String(pm.environment.get(p.variable) || '');",
              "    if (!value && p.required) throw Error('Missing required request parameter.');",
              "    if (!value) continue;",
              "    if (p.schema.pattern && !(new RegExp(p.schema.pattern)).test(value)) throw Error('Invalid request parameter.');",
              "    if (p.in === 'path') target = target.replace('{' + p.name + '}', encodeURIComponent(value));",
              "    else query.push(encodeURIComponent(p.name) + '=' + encodeURIComponent(value));",
              "  }",
              "  if (query.length) target += '?' + query.join('&');",
              "  pm.request.url.update(base + target);",
              "  let rawBody = '';",
              "  if (pm.request.body && pm.request.body.mode === 'raw') {",
              "    rawBody = pm.variables.replaceIn(pm.request.body.raw);",
              "    if (/{{[^}]+}}/.test(rawBody)) throw Error('Resolve every body variable before sending.');",
              "    JSON.parse(rawBody);",
              "    pm.request.body.update(rawBody);",
              "  }",
              "  const timestamp = String(Math.floor(Date.now() / 1000));",
              "  const nonce = pm.variables.replaceIn('{{$guid}}');",
              "  const payload = [timestamp, nonce, pm.request.method.toUpperCase(), target, rawBody].join('\\n');",
              "  const signature = CryptoJS.HmacSHA512(CryptoJS.enc.Utf8.parse(payload), CryptoJS.enc.Utf8.parse(secret)).toString(CryptoJS.enc.Hex);",
              "  for (const [key, value] of Object.entries({'X-API-Token': token, 'X-Timestamp': timestamp, 'X-Nonce': nonce, 'X-Signature': signature})) pm.request.headers.upsert({key, value});",
              "} catch (error) {",
              "  pm.execution.skipRequest();",
              "  throw error;",
              "}"
            ]
          }
        }
      ]
    },
    {
      "name": "listBanksV2",
      "request": {
        "method": "GET",
        "header": [],
        "url": "{{api_base_url}}/api/v2/banks",
        "description": "Get canonical bank IDs for payout integration and issued requisites\nSource: GET /api/v2/banks. Parameters are read from the local environment. Disable automatic redirects. After a lost Create response use the corresponding result lookup with the original merchant_order_id; do not create another payment."
      },
      "protocolProfileBehavior": {
        "followRedirects": false,
        "disableUrlEncoding": true
      },
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Local desktop Postman only. Never execute this signer in the documentation browser.",
              "const CryptoJS = require('crypto-js');",
              "try {",
              "  const config = {\"path\":\"/api/v2/banks\",\"parameters\":[{\"name\":\"q\",\"in\":\"query\",\"required\":false,\"schema\":{\"type\":\"string\",\"maxLength\":200},\"description\":\"Substring of original_name, up to 200 UTF-8 bytes.\",\"variable\":\"bank_query\"},{\"name\":\"country_code\",\"in\":\"query\",\"required\":false,\"schema\":{\"type\":\"string\",\"pattern\":\"^[A-Z]{2}$\"},\"variable\":\"bank_country_code\"},{\"name\":\"after\",\"in\":\"query\",\"required\":false,\"schema\":{\"type\":\"string\",\"pattern\":\"^bank_[1-9][0-9]*$\",\"maxLength\":24,\"description\":\"Immutable Absolut Pay bank ID from GET /api/v2/banks. Not an NSPK ID or provider code.\"},\"description\":\"Use the previous next_after without changing filters. At most 100 items per page.\",\"variable\":\"bank_after\"}]};",
              "  const base = String(pm.environment.get('api_base_url') || '').replace(/\\/$/, '');",
              "  if (!/^https:\\/\\/[A-Za-z0-9.-]+(?::[0-9]+)?$/.test(base) && !/^http:\\/\\/(?:localhost|127\\.0\\.0\\.1|\\[::1\\])(?::[0-9]+)?$/.test(base)) throw Error('Use an HTTPS API origin or local loopback HTTP origin.');",
              "  const token = pm.environment.get('api_token');",
              "  const secret = pm.environment.get('api_secret');",
              "  if (!token || !secret) throw Error('Set local-only API token and secret; never share or export populated credentials.');",
              "  let target = config.path;",
              "  const query = [];",
              "  for (const p of config.parameters) {",
              "    const value = String(pm.environment.get(p.variable) || '');",
              "    if (!value && p.required) throw Error('Missing required request parameter.');",
              "    if (!value) continue;",
              "    if (p.schema.pattern && !(new RegExp(p.schema.pattern)).test(value)) throw Error('Invalid request parameter.');",
              "    if (p.in === 'path') target = target.replace('{' + p.name + '}', encodeURIComponent(value));",
              "    else query.push(encodeURIComponent(p.name) + '=' + encodeURIComponent(value));",
              "  }",
              "  if (query.length) target += '?' + query.join('&');",
              "  pm.request.url.update(base + target);",
              "  let rawBody = '';",
              "  if (pm.request.body && pm.request.body.mode === 'raw') {",
              "    rawBody = pm.variables.replaceIn(pm.request.body.raw);",
              "    if (/{{[^}]+}}/.test(rawBody)) throw Error('Resolve every body variable before sending.');",
              "    JSON.parse(rawBody);",
              "    pm.request.body.update(rawBody);",
              "  }",
              "  const timestamp = String(Math.floor(Date.now() / 1000));",
              "  const nonce = pm.variables.replaceIn('{{$guid}}');",
              "  const payload = [timestamp, nonce, pm.request.method.toUpperCase(), target, rawBody].join('\\n');",
              "  const signature = CryptoJS.HmacSHA512(CryptoJS.enc.Utf8.parse(payload), CryptoJS.enc.Utf8.parse(secret)).toString(CryptoJS.enc.Hex);",
              "  for (const [key, value] of Object.entries({'X-API-Token': token, 'X-Timestamp': timestamp, 'X-Nonce': nonce, 'X-Signature': signature})) pm.request.headers.upsert({key, value});",
              "} catch (error) {",
              "  pm.execution.skipRequest();",
              "  throw error;",
              "}"
            ]
          }
        }
      ]
    },
    {
      "name": "createPayoutV2",
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          }
        ],
        "url": "{{api_base_url}}/api/v2/payouts",
        "description": "createPayoutV2\nSource: POST /api/v2/payouts. Parameters are read from the local environment. Disable automatic redirects. After a lost Create response use the corresponding result lookup with the original merchant_order_id; do not create another payment.",
        "body": {
          "mode": "raw",
          "raw": "{\n  \"merchant_order_id\": \"YOUR_UNIQUE_PAYOUT_ID\",\n  \"amount\": \"15000.00\",\n  \"currency\": \"RUB\",\n  \"method\": \"sbp\",\n  \"bank_id\": \"bank_1\",\n  \"recipient\": {\n    \"phone_number\": \"+79991112233\",\n    \"customer_name\": \"Тестовый получатель\"\n  },\n  \"webhook_url\": \"https://merchant.example/payouts-hook\",\n  \"metadata\": {}\n}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        }
      },
      "protocolProfileBehavior": {
        "followRedirects": false,
        "disableUrlEncoding": true
      },
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Local desktop Postman only. Never execute this signer in the documentation browser.",
              "const CryptoJS = require('crypto-js');",
              "try {",
              "  const config = {\"path\":\"/api/v2/payouts\",\"parameters\":[]};",
              "  const base = String(pm.environment.get('api_base_url') || '').replace(/\\/$/, '');",
              "  if (!/^https:\\/\\/[A-Za-z0-9.-]+(?::[0-9]+)?$/.test(base) && !/^http:\\/\\/(?:localhost|127\\.0\\.0\\.1|\\[::1\\])(?::[0-9]+)?$/.test(base)) throw Error('Use an HTTPS API origin or local loopback HTTP origin.');",
              "  const token = pm.environment.get('api_token');",
              "  const secret = pm.environment.get('api_secret');",
              "  if (!token || !secret) throw Error('Set local-only API token and secret; never share or export populated credentials.');",
              "  let target = config.path;",
              "  const query = [];",
              "  for (const p of config.parameters) {",
              "    const value = String(pm.environment.get(p.variable) || '');",
              "    if (!value && p.required) throw Error('Missing required request parameter.');",
              "    if (!value) continue;",
              "    if (p.schema.pattern && !(new RegExp(p.schema.pattern)).test(value)) throw Error('Invalid request parameter.');",
              "    if (p.in === 'path') target = target.replace('{' + p.name + '}', encodeURIComponent(value));",
              "    else query.push(encodeURIComponent(p.name) + '=' + encodeURIComponent(value));",
              "  }",
              "  if (query.length) target += '?' + query.join('&');",
              "  pm.request.url.update(base + target);",
              "  let rawBody = '';",
              "  if (pm.request.body && pm.request.body.mode === 'raw') {",
              "    rawBody = pm.variables.replaceIn(pm.request.body.raw);",
              "    if (/{{[^}]+}}/.test(rawBody)) throw Error('Resolve every body variable before sending.');",
              "    JSON.parse(rawBody);",
              "    pm.request.body.update(rawBody);",
              "  }",
              "  const timestamp = String(Math.floor(Date.now() / 1000));",
              "  const nonce = pm.variables.replaceIn('{{$guid}}');",
              "  const payload = [timestamp, nonce, pm.request.method.toUpperCase(), target, rawBody].join('\\n');",
              "  const signature = CryptoJS.HmacSHA512(CryptoJS.enc.Utf8.parse(payload), CryptoJS.enc.Utf8.parse(secret)).toString(CryptoJS.enc.Hex);",
              "  for (const [key, value] of Object.entries({'X-API-Token': token, 'X-Timestamp': timestamp, 'X-Nonce': nonce, 'X-Signature': signature})) pm.request.headers.upsert({key, value});",
              "} catch (error) {",
              "  pm.execution.skipRequest();",
              "  throw error;",
              "}"
            ]
          }
        }
      ]
    },
    {
      "name": "lookupPayoutRequestV2",
      "request": {
        "method": "GET",
        "header": [],
        "url": "{{api_base_url}}/api/v2/payouts/result",
        "description": "lookupPayoutRequestV2\nSource: GET /api/v2/payouts/result. Parameters are read from the local environment. Disable automatic redirects. After a lost Create response use the corresponding result lookup with the original merchant_order_id; do not create another payment."
      },
      "protocolProfileBehavior": {
        "followRedirects": false,
        "disableUrlEncoding": true
      },
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Local desktop Postman only. Never execute this signer in the documentation browser.",
              "const CryptoJS = require('crypto-js');",
              "try {",
              "  const config = {\"path\":\"/api/v2/payouts/result\",\"parameters\":[{\"name\":\"merchant_order_id\",\"in\":\"query\",\"required\":true,\"schema\":{\"type\":\"string\",\"minLength\":1,\"maxLength\":128},\"variable\":\"merchant_order_id\"}]};",
              "  const base = String(pm.environment.get('api_base_url') || '').replace(/\\/$/, '');",
              "  if (!/^https:\\/\\/[A-Za-z0-9.-]+(?::[0-9]+)?$/.test(base) && !/^http:\\/\\/(?:localhost|127\\.0\\.0\\.1|\\[::1\\])(?::[0-9]+)?$/.test(base)) throw Error('Use an HTTPS API origin or local loopback HTTP origin.');",
              "  const token = pm.environment.get('api_token');",
              "  const secret = pm.environment.get('api_secret');",
              "  if (!token || !secret) throw Error('Set local-only API token and secret; never share or export populated credentials.');",
              "  let target = config.path;",
              "  const query = [];",
              "  for (const p of config.parameters) {",
              "    const value = String(pm.environment.get(p.variable) || '');",
              "    if (!value && p.required) throw Error('Missing required request parameter.');",
              "    if (!value) continue;",
              "    if (p.schema.pattern && !(new RegExp(p.schema.pattern)).test(value)) throw Error('Invalid request parameter.');",
              "    if (p.in === 'path') target = target.replace('{' + p.name + '}', encodeURIComponent(value));",
              "    else query.push(encodeURIComponent(p.name) + '=' + encodeURIComponent(value));",
              "  }",
              "  if (query.length) target += '?' + query.join('&');",
              "  pm.request.url.update(base + target);",
              "  let rawBody = '';",
              "  if (pm.request.body && pm.request.body.mode === 'raw') {",
              "    rawBody = pm.variables.replaceIn(pm.request.body.raw);",
              "    if (/{{[^}]+}}/.test(rawBody)) throw Error('Resolve every body variable before sending.');",
              "    JSON.parse(rawBody);",
              "    pm.request.body.update(rawBody);",
              "  }",
              "  const timestamp = String(Math.floor(Date.now() / 1000));",
              "  const nonce = pm.variables.replaceIn('{{$guid}}');",
              "  const payload = [timestamp, nonce, pm.request.method.toUpperCase(), target, rawBody].join('\\n');",
              "  const signature = CryptoJS.HmacSHA512(CryptoJS.enc.Utf8.parse(payload), CryptoJS.enc.Utf8.parse(secret)).toString(CryptoJS.enc.Hex);",
              "  for (const [key, value] of Object.entries({'X-API-Token': token, 'X-Timestamp': timestamp, 'X-Nonce': nonce, 'X-Signature': signature})) pm.request.headers.upsert({key, value});",
              "} catch (error) {",
              "  pm.execution.skipRequest();",
              "  throw error;",
              "}"
            ]
          }
        }
      ]
    },
    {
      "name": "getPayoutV2",
      "request": {
        "method": "GET",
        "header": [],
        "url": "{{api_base_url}}/api/v2/payouts/{{payout_id}}",
        "description": "getPayoutV2\nSource: GET /api/v2/payouts/{id}. Parameters are read from the local environment. Disable automatic redirects. After a lost Create response use the corresponding result lookup with the original merchant_order_id; do not create another payment."
      },
      "protocolProfileBehavior": {
        "followRedirects": false,
        "disableUrlEncoding": true
      },
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Local desktop Postman only. Never execute this signer in the documentation browser.",
              "const CryptoJS = require('crypto-js');",
              "try {",
              "  const config = {\"path\":\"/api/v2/payouts/{id}\",\"parameters\":[{\"name\":\"id\",\"in\":\"path\",\"required\":true,\"schema\":{\"type\":\"string\",\"pattern\":\"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$\",\"description\":\"Permanent UUID v4 issued by Absolut Pay.\"},\"variable\":\"payout_id\"}]};",
              "  const base = String(pm.environment.get('api_base_url') || '').replace(/\\/$/, '');",
              "  if (!/^https:\\/\\/[A-Za-z0-9.-]+(?::[0-9]+)?$/.test(base) && !/^http:\\/\\/(?:localhost|127\\.0\\.0\\.1|\\[::1\\])(?::[0-9]+)?$/.test(base)) throw Error('Use an HTTPS API origin or local loopback HTTP origin.');",
              "  const token = pm.environment.get('api_token');",
              "  const secret = pm.environment.get('api_secret');",
              "  if (!token || !secret) throw Error('Set local-only API token and secret; never share or export populated credentials.');",
              "  let target = config.path;",
              "  const query = [];",
              "  for (const p of config.parameters) {",
              "    const value = String(pm.environment.get(p.variable) || '');",
              "    if (!value && p.required) throw Error('Missing required request parameter.');",
              "    if (!value) continue;",
              "    if (p.schema.pattern && !(new RegExp(p.schema.pattern)).test(value)) throw Error('Invalid request parameter.');",
              "    if (p.in === 'path') target = target.replace('{' + p.name + '}', encodeURIComponent(value));",
              "    else query.push(encodeURIComponent(p.name) + '=' + encodeURIComponent(value));",
              "  }",
              "  if (query.length) target += '?' + query.join('&');",
              "  pm.request.url.update(base + target);",
              "  let rawBody = '';",
              "  if (pm.request.body && pm.request.body.mode === 'raw') {",
              "    rawBody = pm.variables.replaceIn(pm.request.body.raw);",
              "    if (/{{[^}]+}}/.test(rawBody)) throw Error('Resolve every body variable before sending.');",
              "    JSON.parse(rawBody);",
              "    pm.request.body.update(rawBody);",
              "  }",
              "  const timestamp = String(Math.floor(Date.now() / 1000));",
              "  const nonce = pm.variables.replaceIn('{{$guid}}');",
              "  const payload = [timestamp, nonce, pm.request.method.toUpperCase(), target, rawBody].join('\\n');",
              "  const signature = CryptoJS.HmacSHA512(CryptoJS.enc.Utf8.parse(payload), CryptoJS.enc.Utf8.parse(secret)).toString(CryptoJS.enc.Hex);",
              "  for (const [key, value] of Object.entries({'X-API-Token': token, 'X-Timestamp': timestamp, 'X-Nonce': nonce, 'X-Signature': signature})) pm.request.headers.upsert({key, value});",
              "} catch (error) {",
              "  pm.execution.skipRequest();",
              "  throw error;",
              "}"
            ]
          }
        }
      ]
    },
    {
      "name": "getShopBalanceV2",
      "request": {
        "method": "GET",
        "header": [],
        "url": "{{api_base_url}}/api/v2/balance",
        "description": "getShopBalanceV2\nSource: GET /api/v2/balance. Parameters are read from the local environment. Disable automatic redirects. After a lost Create response use the corresponding result lookup with the original merchant_order_id; do not create another payment."
      },
      "protocolProfileBehavior": {
        "followRedirects": false,
        "disableUrlEncoding": true
      },
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Local desktop Postman only. Never execute this signer in the documentation browser.",
              "const CryptoJS = require('crypto-js');",
              "try {",
              "  const config = {\"path\":\"/api/v2/balance\",\"parameters\":[]};",
              "  const base = String(pm.environment.get('api_base_url') || '').replace(/\\/$/, '');",
              "  if (!/^https:\\/\\/[A-Za-z0-9.-]+(?::[0-9]+)?$/.test(base) && !/^http:\\/\\/(?:localhost|127\\.0\\.0\\.1|\\[::1\\])(?::[0-9]+)?$/.test(base)) throw Error('Use an HTTPS API origin or local loopback HTTP origin.');",
              "  const token = pm.environment.get('api_token');",
              "  const secret = pm.environment.get('api_secret');",
              "  if (!token || !secret) throw Error('Set local-only API token and secret; never share or export populated credentials.');",
              "  let target = config.path;",
              "  const query = [];",
              "  for (const p of config.parameters) {",
              "    const value = String(pm.environment.get(p.variable) || '');",
              "    if (!value && p.required) throw Error('Missing required request parameter.');",
              "    if (!value) continue;",
              "    if (p.schema.pattern && !(new RegExp(p.schema.pattern)).test(value)) throw Error('Invalid request parameter.');",
              "    if (p.in === 'path') target = target.replace('{' + p.name + '}', encodeURIComponent(value));",
              "    else query.push(encodeURIComponent(p.name) + '=' + encodeURIComponent(value));",
              "  }",
              "  if (query.length) target += '?' + query.join('&');",
              "  pm.request.url.update(base + target);",
              "  let rawBody = '';",
              "  if (pm.request.body && pm.request.body.mode === 'raw') {",
              "    rawBody = pm.variables.replaceIn(pm.request.body.raw);",
              "    if (/{{[^}]+}}/.test(rawBody)) throw Error('Resolve every body variable before sending.');",
              "    JSON.parse(rawBody);",
              "    pm.request.body.update(rawBody);",
              "  }",
              "  const timestamp = String(Math.floor(Date.now() / 1000));",
              "  const nonce = pm.variables.replaceIn('{{$guid}}');",
              "  const payload = [timestamp, nonce, pm.request.method.toUpperCase(), target, rawBody].join('\\n');",
              "  const signature = CryptoJS.HmacSHA512(CryptoJS.enc.Utf8.parse(payload), CryptoJS.enc.Utf8.parse(secret)).toString(CryptoJS.enc.Hex);",
              "  for (const [key, value] of Object.entries({'X-API-Token': token, 'X-Timestamp': timestamp, 'X-Nonce': nonce, 'X-Signature': signature})) pm.request.headers.upsert({key, value});",
              "} catch (error) {",
              "  pm.execution.skipRequest();",
              "  throw error;",
              "}"
            ]
          }
        }
      ]
    }
  ]
}
