{
  "info": {
    "name": "ImpAcc User Profile API",
    "description": "Authenticate against the ImpAcc user database and read user profile via Laravel Sanctum bearer tokens.\n\n**Setup:**\n1. Open the collection's *Variables* tab and set `citizen_id` and `password` to a real account.\n2. Run **Auth → Login** — the test script saves the returned token into the `token` variable automatically.\n3. The remaining requests use `{{token}}` in their Authorization header.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    { "key": "baseUrl",    "value": "https://uat-usr.impacc.work/api", "type": "string" },
    { "key": "citizen_id", "value": "1234567890123",               "type": "string" },
    { "key": "password",   "value": "user-secret",                 "type": "string" },
    { "key": "device_name","value": "postman",                     "type": "string" },
    { "key": "mToken",     "value": "",                            "type": "string" },
    { "key": "token",      "value": "",                            "type": "string" },
    { "key": "client_id",  "value": "",                            "type": "string" },
    { "key": "public_key", "value": "",                            "type": "string" }
  ],
  "item": [
    {
      "name": "Auth",
      "item": [
        {
          "name": "Login",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept",       "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "url": {
              "raw":  "{{baseUrl}}/login",
              "host": ["{{baseUrl}}"],
              "path": ["login"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"citizen_id\":  \"{{citizen_id}}\",\n  \"password\":    \"{{password}}\",\n  \"device_name\": \"{{device_name}}\"\n}"
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('200 OK', () => pm.response.to.have.status(200));",
                  "const body = pm.response.json();",
                  "pm.test('has token', () => pm.expect(body.token).to.be.a('string'));",
                  "if (body.token) {",
                  "  pm.collectionVariables.set('token', body.token);",
                  "  console.log('Saved token:', body.token.substring(0, 12) + '...');",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "SSO exchange",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept",       "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "url": {
              "raw":  "{{baseUrl}}/sso/exchange",
              "host": ["{{baseUrl}}"],
              "path": ["sso", "exchange"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"mToken\":      \"{{mToken}}\",\n  \"device_name\": \"{{device_name}}\"\n}"
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('200 OK', () => pm.response.to.have.status(200));",
                  "const body = pm.response.json();",
                  "pm.test('has token', () => pm.expect(body.token).to.be.a('string'));",
                  "if (body.token) pm.collectionVariables.set('token', body.token);"
                ]
              }
            }
          ]
        },
        {
          "name": "Logout",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept",        "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{token}}" }
            ],
            "url": {
              "raw":  "{{baseUrl}}/logout",
              "host": ["{{baseUrl}}"],
              "path": ["logout"]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('200 OK', () => pm.response.to.have.status(200));",
                  "pm.collectionVariables.set('token', '');"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "Profile",
      "item": [
        {
          "name": "Get my profile",
          "request": {
            "method": "GET",
            "header": [
              { "key": "Accept",        "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{token}}" }
            ],
            "url": {
              "raw":  "{{baseUrl}}/profile",
              "host": ["{{baseUrl}}"],
              "path": ["profile"]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('200 OK', () => pm.response.to.have.status(200));",
                  "const body = pm.response.json();",
                  "pm.test('has user.citizen_id', () => pm.expect(body.user.citizen_id).to.be.a('string'));",
                  "pm.test('has permissions block', () => pm.expect(body.user.permissions.applications).to.be.an('array'));"
                ]
              }
            }
          ]
        },
        {
          "name": "Get my permissions",
          "request": {
            "method": "GET",
            "header": [
              { "key": "Accept",        "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{token}}" }
            ],
            "url": {
              "raw":  "{{baseUrl}}/permissions",
              "host": ["{{baseUrl}}"],
              "path": ["permissions"]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('200 OK', () => pm.response.to.have.status(200));",
                  "const body = pm.response.json();",
                  "pm.test('has group_ids', () => pm.expect(body.permissions.group_ids).to.be.an('array'));",
                  "pm.test('has applications', () => pm.expect(body.permissions.applications).to.be.an('array'));"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "v2 (hardened)",
      "description": "Opt-in /api/v2 endpoints: expiring tokens, rate limiting, strict validation, mToken TTL, audit. Saves the token into {{token}}.",
      "item": [
        {
          "name": "v2 Login",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept",       "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "url": { "raw": "{{baseUrl}}/v2/login", "host": ["{{baseUrl}}"], "path": ["v2", "login"] },
            "body": { "mode": "raw", "raw": "{\n  \"citizen_id\":  \"{{citizen_id}}\",\n  \"password\":    \"{{password}}\",\n  \"device_name\": \"{{device_name}}\"\n}" }
          },
          "event": [
            { "listen": "test", "script": { "type": "text/javascript", "exec": [
              "pm.test('200 OK', () => pm.response.to.have.status(200));",
              "const body = pm.response.json();",
              "pm.test('has expires_in', () => pm.expect(body.expires_in).to.be.a('number'));",
              "if (body.token) pm.collectionVariables.set('token', body.token);"
            ] } }
          ]
        },
        {
          "name": "v2 SSO exchange",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept",       "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "url": { "raw": "{{baseUrl}}/v2/sso/exchange", "host": ["{{baseUrl}}"], "path": ["v2", "sso", "exchange"] },
            "body": { "mode": "raw", "raw": "{\n  \"mToken\":      \"{{mToken}}\",\n  \"device_name\": \"{{device_name}}\"\n}" }
          },
          "event": [
            { "listen": "test", "script": { "type": "text/javascript", "exec": [
              "pm.test('200 OK', () => pm.response.to.have.status(200));",
              "const body = pm.response.json();",
              "pm.test('has expires_in', () => pm.expect(body.expires_in).to.be.a('number'));",
              "if (body.token) pm.collectionVariables.set('token', body.token);"
            ] } }
          ]
        },
        {
          "name": "v2 Get my profile",
          "request": {
            "method": "GET",
            "header": [
              { "key": "Accept",        "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{token}}" }
            ],
            "url": { "raw": "{{baseUrl}}/v2/profile", "host": ["{{baseUrl}}"], "path": ["v2", "profile"] }
          },
          "event": [
            { "listen": "test", "script": { "type": "text/javascript", "exec": [
              "pm.test('200 OK', () => pm.response.to.have.status(200));"
            ] } }
          ]
        },
        {
          "name": "v2 Get my permissions",
          "request": {
            "method": "GET",
            "header": [
              { "key": "Accept",        "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{token}}" }
            ],
            "url": { "raw": "{{baseUrl}}/v2/permissions", "host": ["{{baseUrl}}"], "path": ["v2", "permissions"] }
          },
          "event": [
            { "listen": "test", "script": { "type": "text/javascript", "exec": [
              "pm.test('200 OK', () => pm.response.to.have.status(200));"
            ] } }
          ]
        },
        {
          "name": "v2 Logout",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept",        "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{token}}" }
            ],
            "url": { "raw": "{{baseUrl}}/v2/logout", "host": ["{{baseUrl}}"], "path": ["v2", "logout"] }
          },
          "event": [
            { "listen": "test", "script": { "type": "text/javascript", "exec": [
              "pm.test('200 OK', () => pm.response.to.have.status(200));",
              "pm.collectionVariables.set('token', '');"
            ] } }
          ]
        }
      ]
    },
    {
      "name": "v3 (encrypted)",
      "description": "Opt-in /api/v3 endpoints. Register an RSA public key (set {{public_key}}), then send X-Client-Id={{client_id}}. Successful responses are an encrypted envelope; decrypting requires your RSA private key (use the PHP/Node example in API.md §9 — not done inside Postman).",
      "item": [
        {
          "name": "v3 Register client",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept",       "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "url": { "raw": "{{baseUrl}}/v3/clients/register", "host": ["{{baseUrl}}"], "path": ["v3", "clients", "register"] },
            "body": { "mode": "raw", "raw": "{\n  \"name\": \"postman-client\",\n  \"public_key\": \"{{public_key}}\"\n}" }
          },
          "event": [
            { "listen": "test", "script": { "type": "text/javascript", "exec": [
              "pm.test('200 OK', () => pm.response.to.have.status(200));",
              "const b = pm.response.json();",
              "if (b.client_id) pm.collectionVariables.set('client_id', b.client_id);"
            ] } }
          ]
        },
        {
          "name": "v3 SSO exchange (encrypted)",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept",       "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" },
              { "key": "X-Client-Id",  "value": "{{client_id}}" }
            ],
            "url": { "raw": "{{baseUrl}}/v3/sso/exchange", "host": ["{{baseUrl}}"], "path": ["v3", "sso", "exchange"] },
            "body": { "mode": "raw", "raw": "{\n  \"mToken\": \"{{mToken}}\"\n}" }
          },
          "event": [
            { "listen": "test", "script": { "type": "text/javascript", "exec": [
              "pm.test('200 OK', () => pm.response.to.have.status(200));",
              "pm.test('response is encrypted', () => pm.expect(pm.response.json().ciphertext).to.be.a('string'));"
            ] } }
          ]
        },
        {
          "name": "v3 Login (encrypted)",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept",       "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" },
              { "key": "X-Client-Id",  "value": "{{client_id}}" }
            ],
            "url": { "raw": "{{baseUrl}}/v3/login", "host": ["{{baseUrl}}"], "path": ["v3", "login"] },
            "body": { "mode": "raw", "raw": "{\n  \"citizen_id\": \"{{citizen_id}}\",\n  \"password\": \"{{password}}\"\n}" }
          },
          "event": [
            { "listen": "test", "script": { "type": "text/javascript", "exec": [
              "pm.test('200 OK', () => pm.response.to.have.status(200));",
              "pm.test('response is encrypted', () => pm.expect(pm.response.json().ciphertext).to.be.a('string'));"
            ] } }
          ]
        }
      ]
    }
  ]
}
