{
  "info": {
    "name": "Vouchereto Merchant API",
    "description": "Run the \"1. Quickstart\" folder top to bottom with the Sandbox environment. Requests are signed by the collection pre-request script. Docs: https://www.vouchereto.com/docs",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "// Signs every request: Vouchereto-Signature = t=<unix>,v1=HMAC-SHA256(secret, t + '.' + METHOD + ' ' + path_with_query + '\\n' + body)",
          "const key = pm.variables.get('api_key');",
          "if (!key || !/^vch_(test|live)_[0-9A-Za-z]{12}_[0-9A-Za-z]{32}$/.test(key)) throw new Error('Set api_key in the environment (vch_test_…)');",
          "const secret = key.split('_').pop();",
          "const method = pm.request.method.toUpperCase();",
          "const path = pm.variables.replaceIn(pm.request.url.getPathWithQuery());",
          "const body = method === 'GET' || !pm.request.body || !pm.request.body.raw ? '' : pm.variables.replaceIn(pm.request.body.raw);",
          "const t = Math.floor(Date.now() / 1000);",
          "const mac = CryptoJS.HmacSHA256(t + '.' + method + ' ' + path + '\\n' + body, secret).toString(CryptoJS.enc.Hex);",
          "pm.request.headers.upsert({ key: 'Authorization', value: 'Bearer ' + key });",
          "pm.request.headers.upsert({ key: 'Vouchereto-Signature', value: 't=' + t + ',v1=' + mac });",
          "if (method === 'POST' && !pm.request.headers.has('Idempotency-Key')) pm.request.headers.upsert({ key: 'Idempotency-Key', value: pm.variables.replaceIn('{{$guid}}') });"
        ]
      }
    }
  ],
  "variable": [
    {
      "key": "voucher_code",
      "value": ""
    },
    {
      "key": "redemption_id",
      "value": ""
    },
    {
      "key": "checkout_session_id",
      "value": ""
    }
  ],
  "item": [
    {
      "name": "1. Quickstart (sandbox)",
      "item": [
        {
          "name": "Create a sandbox voucher",
          "request": {
            "method": "POST",
            "description": "Test keys only. Returns a real code you can redeem.",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{host}}/v1/sandbox/vouchers",
              "host": [
                "{{host}}"
              ],
              "path": [
                "v1",
                "sandbox",
                "vouchers"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"state\": \"active\",\n  \"amount_minor\": 5000,\n  \"currency\": \"{{currency}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "if (pm.response.code < 300) {",
                  "  const j = pm.response.json();",
                  "  pm.collectionVariables.set('voucher_code', j.code);",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Reserve the voucher",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{host}}/v1/redemptions",
              "host": [
                "{{host}}"
              ],
              "path": [
                "v1",
                "redemptions"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"code\": \"{{voucher_code}}\",\n  \"currency\": \"{{currency}}\",\n  \"customer_ref\": \"postman_customer\",\n  \"ttl_seconds\": 900\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "if (pm.response.code < 300) {",
                  "  const j = pm.response.json();",
                  "  pm.collectionVariables.set('redemption_id', j.id);",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Capture the redemption",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{host}}/v1/redemptions/{{redemption_id}}/capture",
              "host": [
                "{{host}}"
              ],
              "path": [
                "v1",
                "redemptions",
                "{{redemption_id}}",
                "capture"
              ]
            }
          }
        },
        {
          "name": "Retrieve the redemption",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{host}}/v1/redemptions/{{redemption_id}}",
              "host": [
                "{{host}}"
              ],
              "path": [
                "v1",
                "redemptions",
                "{{redemption_id}}"
              ]
            }
          }
        }
      ]
    },
    {
      "name": "2. Redemptions",
      "item": [
        {
          "name": "List redemptions",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{host}}/v1/redemptions?limit=20",
              "host": [
                "{{host}}"
              ],
              "path": [
                "v1",
                "redemptions"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "20"
                }
              ]
            }
          }
        },
        {
          "name": "List captured redemptions",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{host}}/v1/redemptions?status=captured&limit=20",
              "host": [
                "{{host}}"
              ],
              "path": [
                "v1",
                "redemptions"
              ],
              "query": [
                {
                  "key": "status",
                  "value": "captured"
                },
                {
                  "key": "limit",
                  "value": "20"
                }
              ]
            }
          }
        },
        {
          "name": "Cancel a reservation",
          "request": {
            "method": "POST",
            "description": "Reserve a new voucher first: a captured redemption cannot be cancelled (409).",
            "header": [],
            "url": {
              "raw": "{{host}}/v1/redemptions/{{redemption_id}}/cancel",
              "host": [
                "{{host}}"
              ],
              "path": [
                "v1",
                "redemptions",
                "{{redemption_id}}",
                "cancel"
              ]
            }
          }
        }
      ]
    },
    {
      "name": "3. Hosted checkout",
      "item": [
        {
          "name": "Create a checkout session",
          "request": {
            "method": "POST",
            "description": "Open the returned url in a browser and pay with test card 4242 4242 4242 4242.",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{host}}/v1/checkout-sessions",
              "host": [
                "{{host}}"
              ],
              "path": [
                "v1",
                "checkout-sessions"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"amount_minor\": 5000,\n  \"currency\": \"{{currency}}\",\n  \"customer_ref\": \"postman_customer\",\n  \"locale\": \"en\",\n  \"return_url\": \"{{return_url}}\",\n  \"cancel_url\": \"{{return_url}}\",\n  \"metadata\": {\n    \"source\": \"postman\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "if (pm.response.code < 300) {",
                  "  const j = pm.response.json();",
                  "  pm.collectionVariables.set('checkout_session_id', j.id);",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Retrieve the checkout session",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{host}}/v1/checkout-sessions/{{checkout_session_id}}",
              "host": [
                "{{host}}"
              ],
              "path": [
                "v1",
                "checkout-sessions",
                "{{checkout_session_id}}"
              ]
            }
          }
        }
      ]
    },
    {
      "name": "4. Redeem widget",
      "item": [
        {
          "name": "Create a redeem session",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{host}}/v1/redeem-sessions",
              "host": [
                "{{host}}"
              ],
              "path": [
                "v1",
                "redeem-sessions"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"currency\": \"{{currency}}\",\n  \"customer_ref\": \"postman_customer\",\n  \"return_url\": \"{{return_url}}\",\n  \"auto_capture\": false\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        }
      ]
    },
    {
      "name": "5. Settlements",
      "item": [
        {
          "name": "List settlements",
          "request": {
            "method": "GET",
            "description": "Always empty with a test key.",
            "header": [],
            "url": {
              "raw": "{{host}}/v1/settlements",
              "host": [
                "{{host}}"
              ],
              "path": [
                "v1",
                "settlements"
              ]
            }
          }
        }
      ]
    }
  ]
}
