{
	"info": {
		"_postman_id": "42b80e82-f923-4c04-ad62-0c4537cce5c3",
		"name": "Pollus TPSSO (Partner-Facing)",
		"description": "## Pollus Third-Party SSO (Partner-Facing)\n\nThis collection begins **after Pollus redirects your app with an authorization `code`** on your registered `redirect_uri`.\n\n**Standard flow**:\n1) You receive `code` on your redirect URI (e.g. `https://yourapp.com/callback?code=...&state=...`).\n2) Call **/token** to exchange the `code` for `access_token` and `refresh_token`.\n3) Use `access_token` to call **/userinfo**, **/licenses**, and **/verifications**.\n4) When `access_token` expires, call **/refresh** with your `refresh_token`.\n\n**Security notes**:\n- Keep your `client_secret` server-side only.\n- `access_token` is short-lived; `refresh_token` is longer-lived.\n- Always use HTTPS.\n",
		"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
		"_exporter_id": "38659724",
		"_collection_link": "https://grey-space-997213.postman.co/workspace/My-Workspace~a44fc959-adf9-4ea8-87f1-78afa8fdb8ad/collection/17885942-42b80e82-f923-4c04-ad62-0c4537cce5c3?action=share&source=collection_link&creator=38659724"
	},
	"item": [
		{
			"name": "1) Token — Exchange Code",
			"event": [
				{
					"listen": "test",
					"script": {
						"exec": [
							"if (pm.response.code === 200) {",
							"  const json = pm.response.json();",
							"  const d = json && json.data ? json.data : {};",
							"  pm.collectionVariables.set('access_token', d.access_token || '');",
							"  pm.collectionVariables.set('refresh_token', d.refresh_token || '');",
							"  pm.collectionVariables.set('expires_in', String(d.expires_in || ''));",
							"}",
							""
						],
						"type": "text/javascript"
					}
				}
			],
			"request": {
				"method": "POST",
				"header": [
					{
						"key": "Content-Type",
						"value": "application/json"
					},
					{
						"key": "Accept",
						"value": "application/json"
					}
				],
				"body": {
					"mode": "raw",
					"raw": "{\n  \"grant_type\": \"authorization_code\",\n  \"client_id\": \"{{client_id}}\",\n  \"client_secret\": \"{{client_secret}}\",\n  \"code\": \"{{code}}\"\n}"
				},
				"url": {
					"raw": "{{base_url}}/token",
					"host": [
						"{{base_url}}"
					],
					"path": [
						"token"
					]
				},
				"description": "Exchange the one-time `code` you received on your `redirect_uri` for tokens.\n\n**Body fields**:\n- `grant_type`: must be `authorization_code`\n- `client_id`: your assigned client ID\n- `client_secret`: your client secret (server-side only)\n- `code`: the authorization code received from Pollus\n\n**Successful response** returns `access_token`, `refresh_token`, `token_type`, `expires_in`, and a `user` object.\n"
			},
			"response": [
				{
					"name": "200 OK",
					"originalRequest": {
						"method": "GET",
						"header": [],
						"url": {
							"raw": ""
						}
					},
					"status": "OK",
					"code": 200,
					"_postman_previewlanguage": "json",
					"header": [],
					"cookie": [],
					"body": "{\n  \"success\": true,\n  \"data\": {\n    \"access_token\": \"eyJhbGciOi...\",\n    \"token_type\": \"Bearer\",\n    \"expires_in\": 900,\n    \"refresh_token\": \"rfrsh_abc123...\",\n    \"user\": {\n      \"id\": 123,\n      \"email\": \"candidate@example.com\",\n      \"username\": \"candidate123\",\n      \"name\": \"Candidate Example\",\n      \"valyd_id\": \"valyd_225c7f2ac450496f97bbbc57354a5898\",\n      \"avatar_url\": null,\n      \"created_at\": \"2025-09-11T10:15:00Z\"\n    }\n  }\n}"
				},
				{
					"name": "401 invalid_client",
					"originalRequest": {
						"method": "GET",
						"header": [],
						"url": {
							"raw": ""
						}
					},
					"status": "Unauthorized",
					"code": 401,
					"_postman_previewlanguage": "json",
					"header": [],
					"cookie": [],
					"body": "{\n  \"success\": false,\n  \"error\": { \"code\": \"invalid_client\", \"message\": \"client_id/client_secret invalid\" }\n}"
				}
			]
		},
		{
			"name": "2a) Userinfo — Profile",
			"request": {
				"method": "GET",
				"header": [
					{
						"key": "Accept",
						"value": "application/json"
					},
					{
						"key": "Authorization",
						"value": "Bearer {{access_token}}",
						"type": "text"
					}
				],
				"url": {
					"raw": "{{base_url}}/userinfo",
					"host": [
						"{{base_url}}"
					],
					"path": [
						"userinfo"
					]
				},
				"description": "Get user profile and identity fields for the bearer `access_token`.\n\nTypical fields: `sub` (subject ID), `email`, `first_name`, `last_name`, `full_name`, `valyd_id`, `id_verified`, `created_at`.\n"
			},
			"response": [
				{
					"name": "200 OK",
					"originalRequest": {
						"method": "GET",
						"header": [],
						"url": {
							"raw": ""
						}
					},
					"status": "OK",
					"code": 200,
					"_postman_previewlanguage": "json",
					"header": [],
					"cookie": [],
					"body": "{\n  \"success\": true,\n  \"data\": {\n    \"sub\": \"valyd_225c7f2ac450496f97bbbc57354a5898\",\n    \"email\": \"candidate@example.com\",\n    \"first_name\": \"Candidate\",\n    \"last_name\": \"Example\",\n    \"full_name\": \"Candidate Example\",\n    \"valyd_id\": \"valyd_225c7f2ac450496f97bbbc57354a5898\",\n    \"id_verified\": true,\n    \"created_at\": \"2025-09-10T12:00:00Z\"\n  }\n}"
				},
				{
					"name": "401 invalid_token",
					"originalRequest": {
						"method": "GET",
						"header": [],
						"url": {
							"raw": ""
						}
					},
					"status": "Unauthorized",
					"code": 401,
					"_postman_previewlanguage": "json",
					"header": [],
					"cookie": [],
					"body": "{\n  \"success\": false,\n  \"error\": { \"code\": \"invalid_token\", \"message\": \"token invalid/expired\" }\n}"
				}
			]
		},
		{
			"name": "2b) Licenses — Verification Snapshot",
			"request": {
				"method": "GET",
				"header": [
					{
						"key": "Accept",
						"value": "application/json"
					},
					{
						"key": "Authorization",
						"value": "Bearer {{access_token}}",
						"type": "text"
					}
				],
				"url": {
					"raw": "{{base_url}}/licenses",
					"host": [
						"{{base_url}}"
					],
					"path": [
						"licenses"
					]
				},
				"description": "Returns a snapshot of the user's professional licenses as verified by Pollus.\n\nExample items include: nursing licenses, CDL endorsements, CPR/BLS, Food Handler, etc. Each record typically carries at least a type, number, status, expiry date, and issuer.\n"
			},
			"response": [
				{
					"name": "200 OK",
					"originalRequest": {
						"method": "GET",
						"header": [],
						"url": {
							"raw": ""
						}
					},
					"status": "OK",
					"code": 200,
					"_postman_previewlanguage": "json",
					"header": [],
					"cookie": [],
					"body": "{\n  \"success\": true,\n  \"data\": {\n    \"licenses\": [\n      {\n        \"type\": \"nurse_licenses\",\n        \"number\": \"RN-123456\",\n        \"status\": \"Active\",\n        \"expires_on\": \"2027-06-30\",\n        \"issuer\": \"CA Board of Nursing\"\n      },\n      {\n        \"type\": \"cpr_certification\",\n        \"number\": \"CPR-998877\",\n        \"status\": \"Active\",\n        \"expires_on\": \"2026-05-15\",\n        \"issuer\": \"American Heart Association\"\n      }\n    ]\n  }\n}"
				}
			]
		},
		{
			"name": "2c) Verifications — Identity Payload",
			"request": {
				"method": "GET",
				"header": [
					{
						"key": "Accept",
						"value": "application/json"
					},
					{
						"key": "Authorization",
						"value": "Bearer {{access_token}}",
						"type": "text"
					}
				],
				"url": {
					"raw": "{{base_url}}/verifications",
					"host": [
						"{{base_url}}"
					],
					"path": [
						"verifications"
					]
				},
				"description": "Returns identity/verification results for the bearer user (e.g., ID verification flag, face match confidence, last checked timestamp). Use alongside **/userinfo** for a full picture.\n"
			},
			"response": [
				{
					"name": "200 OK",
					"originalRequest": {
						"method": "GET",
						"header": [],
						"url": {
							"raw": ""
						}
					},
					"status": "OK",
					"code": 200,
					"_postman_previewlanguage": "json",
					"header": [],
					"cookie": [],
					"body": "{\n  \"success\": true,\n  \"data\": {\n    \"verifications\": {\n      \"id_verified\": true,\n      \"face_match\": 0.98,\n      \"last_checked\": \"2025-09-11T12:00:00Z\"\n    }\n  }\n}"
				}
			]
		},
		{
			"name": "3) Refresh — Rotate Tokens",
			"event": [
				{
					"listen": "test",
					"script": {
						"exec": [
							"if (pm.response.code === 200) {",
							"  const json = pm.response.json();",
							"  const d = json && json.data && json.data.tokens ? json.data.tokens : {};",
							"  if (d.access_token) pm.collectionVariables.set('access_token', d.access_token);",
							"  if (d.refresh_token) pm.collectionVariables.set('refresh_token', d.refresh_token);",
							"  if (typeof d.expires_in !== 'undefined') pm.collectionVariables.set('expires_in', String(d.expires_in));",
							"}",
							""
						],
						"type": "text/javascript"
					}
				}
			],
			"request": {
				"method": "POST",
				"header": [
					{
						"key": "Content-Type",
						"value": "application/json"
					},
					{
						"key": "Accept",
						"value": "application/json"
					}
				],
				"body": {
					"mode": "raw",
					"raw": "{\n  \"refresh_token\": \"{{refresh_token}}\",\n  \"rotate_refresh\": true\n}"
				},
				"url": {
					"raw": "{{base_url}}/refresh",
					"host": [
						"{{base_url}}"
					],
					"path": [
						"refresh"
					]
				},
				"description": "Use your `refresh_token` to obtain a new `access_token`. If `rotate_refresh` is `true`, a new `refresh_token` is also issued.\n\n**Body fields**:\n- `refresh_token`: your current refresh token\n- `rotate_refresh` (boolean): set to `true` to rotate\n"
			},
			"response": [
				{
					"name": "200 OK",
					"originalRequest": {
						"method": "GET",
						"header": [],
						"url": {
							"raw": ""
						}
					},
					"status": "OK",
					"code": 200,
					"_postman_previewlanguage": "json",
					"header": [],
					"cookie": [],
					"body": "{\n  \"success\": true,\n  \"data\": {\n    \"tokens\": {\n      \"access_token\": \"eyJhbGciOi...\",\n      \"token_type\": \"Bearer\",\n      \"expires_in\": 900,\n      \"refresh_token\": \"rfrsh_new456...\"\n    }\n  }\n}"
				},
				{
					"name": "400 invalid_grant",
					"originalRequest": {
						"method": "GET",
						"header": [],
						"url": {
							"raw": ""
						}
					},
					"status": "Bad Request",
					"code": 400,
					"_postman_previewlanguage": "json",
					"header": [],
					"cookie": [],
					"body": "{\n  \"success\": false,\n  \"error\": { \"code\": \"invalid_grant\", \"message\": \"refresh_token is invalid or expired\" }\n}"
				}
			]
		}
	],
	"event": [
		{
			"listen": "prerequest",
			"script": {
				"type": "text/javascript",
				"packages": {},
				"exec": [
					""
				]
			}
		},
		{
			"listen": "test",
			"script": {
				"type": "text/javascript",
				"packages": {},
				"exec": [
					""
				]
			}
		}
	],
	"variable": [
		{
			"key": "base_url",
			"value": "https://pollus.us/api/auth/tpsso"
		},
		{
			"key": "client_id",
			"value": "YOUR_CLIENT_ID"
		},
		{
			"key": "client_secret",
			"value": "YOUR_CLIENT_SECRET"
		},
		{
			"key": "code",
			"value": ""
		},
		{
			"key": "refresh_token",
			"value": ""
		},
		{
			"key": "expires_in",
			"value": ""
		},
		{
			"key": "access_token",
			"value": ""
		}
	]
}