From 5cf7f7da8ca43f39be2f66058de0aef16622ed76 Mon Sep 17 00:00:00 2001 From: Alexandre Brandizzi Date: Tue, 15 Sep 2026 11:03:31 -0300 Subject: [PATCH] docs: add dev Postman starter collection --- postman/README.md | 55 +++ postman/SeaHaven-Dev.postman_collection.json | 380 ++++++++++++++++++ postman/SeaHaven-Dev.postman_environment.json | 30 ++ 3 files changed, 465 insertions(+) create mode 100644 postman/README.md create mode 100644 postman/SeaHaven-Dev.postman_collection.json create mode 100644 postman/SeaHaven-Dev.postman_environment.json diff --git a/postman/README.md b/postman/README.md new file mode 100644 index 0000000..9f36c2e --- /dev/null +++ b/postman/README.md @@ -0,0 +1,55 @@ +# SeaHaven Dev Postman starter + +A small, versioned Postman starter for the SeaHaven backend **dev** API. + +- The **live OpenAPI document** (`{{baseUrl}}/swagger/v1/swagger.json`) is the + complete source of truth for routes and schemas. This committed collection is + a curated starter — it is **not** a generated copy of the full API surface. +- **Dev only.** Never point these requests at any other environment. + +## Files + +| File | Purpose | +| --- | --- | +| `SeaHaven-Dev.postman_collection.json` | Starter collection: setup requests plus safe read-only requests | +| `SeaHaven-Dev.postman_environment.json` | Dev environment: `baseUrl` plus empty secret `username` / `password` / `token` | + +## Getting started + +1. **Import order** — collection first, then environment: + 1. Postman → Import → `postman/SeaHaven-Dev.postman_collection.json` + 2. Postman → Import → `postman/SeaHaven-Dev.postman_environment.json` +2. **Select the environment** — pick `SeaHaven - Dev` in the environment picker + (top right of Postman). +3. **Fill credentials locally** — open the environment and enter values for + `username` and `password`. They ship empty and marked secret on purpose; + keep them local to your Postman workspace. +4. **Run login** — run `Authentication - Login` in the `Setup` folder once. A + successful (200) response captures the bearer token automatically. Every + login attempt clears the previous token value without deleting the variable, + so a failed login cannot leave stale authentication active. +5. **Use the safe reads** — everything in the `Safe reads` folder inherits the + collection-level `Bearer {{token}}` auth, so no extra setup is needed. + +## Token capture behavior + +The login test script stores the returned bearer token **only** in the +environment variable `token` via `pm.environment.set("token", token)`. It never +writes collection or global variables and never prints credentials or tokens to +the Postman console. The pre-request script skips the request and stops with a +clear message if `username` or `password` is empty. + +**Clearing the token:** open `Environments → SeaHaven - Dev`, clear the `token` +value (or use the environment reset), and save. Do this before sharing screens, +exporting, or switching machines. + +## Safety rules + +- Keep populated `username`, `password`, and `token` values local. **Never mark + them shared, export them, or commit them.** +- **Never save dev response bodies as collection examples or commit them.** +- **Full API surface:** in Postman, choose **Import → Link** and paste + `https://api.dev.seahaven.com/swagger/v1/swagger.json`. The `Swagger - OpenAPI + document` request is also available to check that the contract is reachable. +- **Canonical routes:** some legacy aliases may still resolve on dev, but this + collection sticks to canonical routes — prefer those when adding requests. diff --git a/postman/SeaHaven-Dev.postman_collection.json b/postman/SeaHaven-Dev.postman_collection.json new file mode 100644 index 0000000..eea89b4 --- /dev/null +++ b/postman/SeaHaven-Dev.postman_collection.json @@ -0,0 +1,380 @@ +{ + "info": { + "name": "SeaHaven - Dev", + "_postman_id": "a1f0514a-5e9f-41bd-a145-7163671b94db", + "description": "Small starter collection for the SeaHaven backend dev API. The live OpenAPI document ({{baseUrl}}/swagger/v1/swagger.json) remains the complete source of truth; this collection is a curated starter, not a generated copy of the full API surface. Dev only. Requests inherit collection-level Bearer {{token}} auth except the two noauth setup requests.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{token}}", + "type": "string" + } + ] + }, + "item": [ + { + "name": "Setup", + "item": [ + { + "name": "Swagger - OpenAPI document", + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/swagger/v1/swagger.json", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "swagger", + "v1", + "swagger.json" + ] + }, + "description": "Live OpenAPI document for dev. Complete source of truth for routes and schemas; import it into Postman for the full API surface. No auth required." + }, + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"Responded 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Responded with JSON\", function () {", + " pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");", + "});", + "", + "pm.test(\"Document looks like OpenAPI\", function () {", + " const doc = pm.response.json();", + " pm.expect(doc).to.have.property(\"openapi\");", + " pm.expect(doc).to.have.property(\"paths\");", + "});" + ] + } + } + ] + }, + { + "name": "Authentication - Login", + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"username\": \"{{username}}\",\n \"password\": \"{{password}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/api/Authentication/login", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "Authentication", + "login" + ] + }, + "description": "Exchanges the environment username/password for a bearer token. Before sending, the pre-request script clears the previous token value without deleting the variable and skips the request when credentials are empty. On success the test script stores the token only in the environment variable `token`. Credentials are never logged." + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "pm.environment.set(\"token\", \"\");", + "", + "const username = pm.environment.get(\"username\");", + "const password = pm.environment.get(\"password\");", + "", + "if (!username || !password) {", + " pm.execution.skipRequest();", + " throw new Error(\"Select the SeaHaven - Dev environment and set username and password before logging in.\");", + "}" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"Login responded 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "let body;", + "pm.test(\"Login responded with JSON\", function () {", + " pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");", + " body = pm.response.json();", + "});", + "", + "const token = body && body.token;", + "", + "pm.test(\"Login response contained a non-empty token\", function () {", + " pm.expect(token, \"expected a non-empty token field in the login response\").to.be.a(\"string\").and.not.empty;", + "});", + "", + "if (typeof token === \"string\" && token.length > 0) {", + " pm.environment.set(\"token\", token);", + "}" + ] + } + } + ] + } + ] + }, + { + "name": "Safe reads", + "item": [ + { + "name": "User - Get user profile", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/User/UserProfile", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "User", + "UserProfile" + ] + }, + "description": "Returns the profile of the authenticated user (uses the captured token)." + }, + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"Responded 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Responded with JSON\", function () {", + " pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");", + "});", + "", + "pm.test(\"Body is valid JSON\", function () {", + " pm.expect(function () { pm.response.json(); }).to.not.throw();", + "});" + ] + } + } + ] + }, + { + "name": "Vendors - Get vendor list", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/vendors/GetVendorList?page=1&pageSize=10&isActive=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "vendors", + "GetVendorList" + ], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "pageSize", + "value": "10" + }, + { + "key": "isActive", + "value": "true" + } + ] + }, + "description": "Paged list of active vendors (page 1, pageSize 10)." + }, + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"Responded 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Responded with JSON\", function () {", + " pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");", + "});", + "", + "pm.test(\"Body is valid JSON\", function () {", + " pm.expect(function () { pm.response.json(); }).to.not.throw();", + "});" + ] + } + } + ] + }, + { + "name": "Dispatches - List", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/dispatches?page=1&pageSize=25", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "dispatches" + ], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "pageSize", + "value": "25" + } + ] + }, + "description": "Paged list of dispatches (page 1, pageSize 25)." + }, + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"Responded 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Responded with JSON\", function () {", + " pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");", + "});", + "", + "pm.test(\"Body is valid JSON\", function () {", + " pm.expect(function () { pm.response.json(); }).to.not.throw();", + "});" + ] + } + } + ] + }, + { + "name": "Dropdown options", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/DropdownOptions", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "DropdownOptions" + ] + }, + "description": "Dropdown option data used by UI pickers." + }, + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"Responded 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Responded with JSON\", function () {", + " pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");", + "});", + "", + "pm.test(\"Body is valid JSON\", function () {", + " pm.expect(function () { pm.response.json(); }).to.not.throw();", + "});" + ] + } + } + ] + }, + { + "name": "Work orders - Dispatcher lookups", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/workorders/lookups/dispatchers", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "workorders", + "lookups", + "dispatchers" + ] + }, + "description": "Dispatcher lookup data for work orders." + }, + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"Responded 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Responded with JSON\", function () {", + " pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");", + "});", + "", + "pm.test(\"Body is valid JSON\", function () {", + " pm.expect(function () { pm.response.json(); }).to.not.throw();", + "});" + ] + } + } + ] + } + ] + } + ] +} diff --git a/postman/SeaHaven-Dev.postman_environment.json b/postman/SeaHaven-Dev.postman_environment.json new file mode 100644 index 0000000..38d1aeb --- /dev/null +++ b/postman/SeaHaven-Dev.postman_environment.json @@ -0,0 +1,30 @@ +{ + "name": "SeaHaven - Dev", + "values": [ + { + "key": "baseUrl", + "value": "https://api.dev.seahaven.com", + "type": "default", + "enabled": true + }, + { + "key": "username", + "value": "", + "type": "secret", + "enabled": true + }, + { + "key": "password", + "value": "", + "type": "secret", + "enabled": true + }, + { + "key": "token", + "value": "", + "type": "secret", + "enabled": true + } + ], + "_postman_variable_scope": "environment" +}