{
  "info": {
    "name": "Quality on Demand v1.1 - Authorization Code - Client Secret",
    "description": "Quality on Demand v1.1 (SEP/CAMARA), Authorization Code (network-based) grant variant.\n\nClient authentication: CLIENT_SECRET using HTTP Basic authentication (client_id/client_secret). Private Key JWT is also available separately and is recommended because it will become mandatory in the future.\n\nbase_url defaults to Germany staging (https://stg.api.telekom.com). Change only that one variable to target production or another country (see the base_url variable description).\n\nRequires a manual browser step: run request 1, open the printed URL in a browser on cellular data, then paste the returned 'code' into the auth_code collection variable before running request 2.\n\nCurrently listed for: 🇩🇪 Germany. (Source: this app's live product-catalog grant-type configuration, staging environment - see the /documentation/postman-collections page for the current matrix.)\n\nThis is the Client Secret authentication counterpart. It ships with empty client_id and client_secret variables. CIBA uses HTTP Basic at /bc-authorize and /token. JWT Bearer still signs only its required subscriber grant assertion locally and authenticates the client with HTTP Basic, matching SEPAPIs.cs.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "item": [
    {
      "name": "1) Build Authorize URL (open in browser)",
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "if (!pm.collectionVariables.get('state')) {",
              "    pm.collectionVariables.set('state', pm.variables.replaceIn('{{$guid}}'));",
              "}",
              "if (!pm.collectionVariables.get('nonce')) {",
              "    pm.collectionVariables.set('nonce', pm.variables.replaceIn('{{$guid}}'));",
              "}"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "console.log('Open this URL in a browser, log in / consent, then copy the \"code\" query parameter from the redirect URL into the auth_code collection variable:');",
              "console.log(pm.request.url.toString());"
            ]
          }
        }
      ],
      "request": {
        "method": "GET",
        "header": [],
        "url": {
          "raw": "{{base_url}}/authorize?response_type=code&client_id={{client_id}}&redirect_uri={{redirect_uri}}&scope={{scope}}&state={{state}}&nonce={{nonce}}",
          "host": [
            "{{base_url}}/authorize"
          ],
          "query": [
            {
              "key": "response_type",
              "value": "code"
            },
            {
              "key": "client_id",
              "value": "{{client_id}}"
            },
            {
              "key": "redirect_uri",
              "value": "{{redirect_uri}}"
            },
            {
              "key": "scope",
              "value": "{{scope}}"
            },
            {
              "key": "state",
              "value": "{{state}}"
            },
            {
              "key": "nonce",
              "value": "{{nonce}}"
            }
          ]
        },
        "description": "AUTHORIZATION_CODE requires an interactive browser step that Postman cannot perform on your behalf. This request only composes/displays the authorize URL. Copy it, open it in a real browser (on cellular data, since this is the network-based/no-device-identifier QoD flow), log in and consent, then copy the 'code' query parameter into the auth_code collection variable before running the next request."
      },
      "response": []
    },
    {
      "name": "2) Exchange Code for Token",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "const json = pm.response.json();",
              "if (json.access_token) {",
              "    pm.collectionVariables.set('access_token', json.access_token);",
              "    console.log('access_token captured.');",
              "} else {",
              "    console.error('No access_token in response:', JSON.stringify(json));",
              "}",
              "pm.test('Token response has access_token', function () {",
              "    pm.expect(json.access_token, JSON.stringify(json)).to.be.a('string');",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/x-www-form-urlencoded",
            "type": "text"
          }
        ],
        "body": {
          "mode": "urlencoded",
          "urlencoded": [
            {
              "key": "grant_type",
              "value": "authorization_code",
              "type": "text"
            },
            {
              "key": "code",
              "value": "{{auth_code}}",
              "type": "text"
            },
            {
              "key": "redirect_uri",
              "value": "{{redirect_uri}}",
              "type": "text"
            }
          ]
        },
        "url": {
          "raw": "{{base_url}}/token",
          "host": [
            "{{base_url}}/token"
          ]
        },
        "description": "Exchanges the manually-pasted auth_code (from request 1's browser step) for an access token, authenticating the client with a private_key_jwt client_assertion.\n\nClient authentication is HTTP Basic using {{client_id}} and {{client_secret}}; no client_assertion is sent.",
        "auth": {
          "type": "basic",
          "basic": [
            {
              "key": "username",
              "value": "{{client_id}}",
              "type": "string"
            },
            {
              "key": "password",
              "value": "{{client_secret}}",
              "type": "string"
            }
          ]
        }
      },
      "response": []
    },
    {
      "name": "Quality on Demand v1.1 - Create Session (network-based)",
      "event": [],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Authorization",
            "value": "Bearer {{access_token}}",
            "type": "text"
          },
          {
            "key": "Content-Type",
            "value": "application/json",
            "type": "text"
          },
          {
            "key": "x-correlator",
            "value": "{{$guid}}",
            "type": "text"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{\n  \"duration\": {{duration}},\n  \"applicationServer\": {\n    \"ipv4Address\": \"{{application_server_ipv4}}\"\n  },\n  \"qosProfile\": \"{{qos_profile}}\"\n}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{base_url}}/quality-on-demand/v1/sessions",
          "host": [
            "{{base_url}}/quality-on-demand/v1/sessions"
          ]
        },
        "description": "Creates a QoD session WITHOUT a device identifier in the body - matches CreateQualityOnDemandSessionV11NetworkBased in SEPAPIs.cs, used for the Authorization Code / network-based flow where the subscriber is identified purely from the access token (no phoneNumber field needed or expected)."
      },
      "response": []
    }
  ],
  "variable": [
    {
      "key": "base_url",
      "value": "https://stg.api.telekom.com",
      "type": "string",
      "description": "Single variable driving every request in this collection. Default is Germany staging. Change ONLY this variable to switch environment/country:\n- Germany production: https://api.telekom.com\n- Austria staging: https://at.stg.api.telekom.com | production: https://at.api.telekom.com\n- Poland staging: https://pl.stg.api.telekom.com | production: https://pl.api.telekom.com\n- Greece staging: https://gr.stg.api.telekom.com | production: https://gr.api.telekom.com\nSee the /documentation/endpoints page in the MBAPI app for the full country/environment reference table. Every request and script in this collection builds the full endpoint path directly from base_url (e.g. {{base_url}}/token) rather than through a separate derived variable, because Postman does not resolve nested variable references when read inside pre-request/test scripts via pm.collectionVariables.get() - only base_url itself needs to be correct."
    },
    {
      "key": "scope",
      "value": "quality-on-demand:sessions:create quality-on-demand:sessions:read quality-on-demand:sessions:delete quality-on-demand:sessions:update dpv:FraudPreventionAndDetection",
      "type": "string",
      "description": "QualityOnDemandV11Scope from SEPAPIs.cs - uses dpv:FraudPreventionAndDetection."
    },
    {
      "key": "client_id",
      "value": "",
      "type": "string",
      "description": "REQUIRED. Your registered OAuth client ID (PRIVATE_KEY_JWT client authentication)."
    },
    {
      "key": "client_secret",
      "value": "",
      "type": "string",
      "description": "REQUIRED. Your registered OAuth client secret for this API/application. Fill this in locally; this downloadable collection intentionally ships without a secret."
    },
    {
      "key": "duration",
      "value": "10",
      "type": "string",
      "description": "QoD session duration in seconds (1-86400) - matches this app's StandardTestData.Duration."
    },
    {
      "key": "qos_profile",
      "value": "QOS_L",
      "type": "string",
      "description": "QoS profile name - QOS_L matches this app's CreateQualityOnDemandSessionV11 default."
    },
    {
      "key": "application_server_ipv4",
      "value": "0.0.0.0/0",
      "type": "string",
      "description": "Application server IPv4 address/CIDR - matches this app's CreateQualityOnDemandSessionV11(NetworkBased) default of 0.0.0.0/0."
    },
    {
      "key": "access_token",
      "value": "",
      "type": "string",
      "description": "Auto-populated by the token request. Do not edit manually."
    },
    {
      "key": "redirect_uri",
      "value": "https://yourapp.com/callback",
      "type": "string",
      "description": "Your OAuth redirect URI, registered on your TMF Application."
    },
    {
      "key": "state",
      "value": "",
      "type": "string",
      "description": "Auto-populated (random GUID) by request 1 if left blank."
    },
    {
      "key": "nonce",
      "value": "",
      "type": "string",
      "description": "Auto-populated (random GUID) by request 1 if left blank."
    },
    {
      "key": "auth_code",
      "value": "",
      "type": "string",
      "description": "REQUIRED before request 2 - paste the \"code\" query parameter from the browser redirect here."
    }
  ]
}
