docs: add dev Postman starter collection

This commit is contained in:
Alexandre Brandizzi 2026-09-15 11:03:31 -03:00
parent 1a6edd255a
commit 5cf7f7da8c
3 changed files with 465 additions and 0 deletions

55
postman/README.md Normal file
View file

@ -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.

View file

@ -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();",
"});"
]
}
}
]
}
]
}
]
}

View file

@ -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"
}