# build-postman-collection — Postman collection (committed JSON file)

> **Builds:** a **committed Postman Collection v2.1 JSON file** at
> `docs/postman/<project>.postman_collection.json` — folders, requests, saved response examples,
> per-request documentation, collection variables, and the token-pipeline test scripts.
> **Reference implementation (mirror its shape exactly):** `save/docs/postman/save.postman_collection.json`
> (a real base-style collection). Open it to copy the JSON structure when in doubt.
> **Flow:** `START` writes the **initial skeleton**; then **each API plan** adds/updates its own request.
> **Source of truth (no duplication):** endpoint implementation + response envelope → [`build-api.md`](build-api.md) (runs first).

---

## 0) The file & tooling (no MCP — a plain JSON file)

- **One committed file:** `docs/postman/<project>.postman_collection.json` (Collection **v2.1** schema). Edit it as JSON.
- **Per-API plan is the source:** each `docs/project/api/<audience>/<flow>/<endpoint>.md` §Postman gives the request (method/url/body), its ✅/⚠️/❌ examples, and its documentation (screen link + every variable). Add that request into the JSON.
- **Derive from real code** — the route, Form Request rules, Resource, and `app/Traits/Response/*`. Never invent.
- Keep it **valid JSON** at all times (a broken file breaks import). Model every node on `save`'s file.

---

## 1) START — write the initial skeleton (once per project)

When `START` runs, create `docs/postman/<project>.postman_collection.json` with:

1. **`info`** — `name` = "<Project> API v1"; `schema` = `https://schema.getpostman.com/json/collection/v2.1.0/collection.json`;
   `description` = a markdown **lifecycle narrative** (like `save`): the main flows, auth model, common errors, and **Figma links** (from `brand-identity.md`).
2. **`variable`** — `base_url` = `http://127.0.0.1:8000/api/v1/` (trailing slash, includes the version), `user_token` = "", `temp-token` = "", plus the domain ids/params used across requests (`id`, `phone`, `<entity>_id`, `slug`, …).
3. **`item` — structure it `audience → section → flow`** (NOT a flat list of every flow):
   - **Top level = a folder per audience** (`user` / `provider` / `delegate` / `company` + `shared`). **Multi-audience → one folder per audience, and inside EACH audience its own 3 sections.** Single-audience projects skip the audience level and start at the sections.
     ```
     user/       Auth/  Logic/  Settings/
     provider/   Auth/  Logic/  Settings/
     delegate/   Auth/  Logic/  Settings/
     shared/     (endpoints every audience calls — don't duplicate per audience)
     ```
   - **The 3 semantic SECTION folders (inside each audience):**
     - **`Auth`** — identity + account: `auth`, `profile`, `notifications` (+ account settings).
     - **`Logic`** — the core domain flows that audience is about (`debts`, `postpone`, `links`, `trusted`, `plans`, `reports`, `feedback`, lookups, …).
     - **`Settings`** — static/public content (the former `cms`): `pages`, `faqs`, `socials`, `contact-us`, public settings.
   - **Then a sub-folder per flow** inside its section (each flow's section is declared in its plan file, `api-plan-template.md` §5). Request names = **kebab-case route segments** (`create-debt`, `verify-otp`). A section an audience doesn't use is omitted; truly cross-app endpoints go in `shared/`.
   - **Guest:** include a guest request **only if** guest mode is action-capable; a browse-only guest has **no** endpoint (see [`build-api.md`](build-api.md)).
4. **No collection-level auth** — auth is declared **per request** (§3).

This is what the developer gets from `START`: a ready, empty-but-structured collection to fill as each API plan is built.

---

## 2) Each API plan → add/update its request in the JSON

When an API plan is executed (in a sprint), **append its request to the collection file** (idempotent — see §6):

**Token pipeline via `event`/`test` scripts** (tokens are never pasted manually):
```json
"event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
  "try { const j = pm.response.json();",
  "  if (pm.response.code === 200 && j.data) {",
  "    if (j.data.token) { pm.environment.set('user_token', j.data.token); pm.collectionVariables.set('user_token', j.data.token); }",
  "    if (j.data.user && j.data.user.token) { pm.environment.set('user_token', j.data.user.token); pm.collectionVariables.set('user_token', j.data.user.token); }",
  "  }",
  "} catch (e) {}"
] } }]
```
- Temp-token stages set `temp-token`; resource-creating requests capture their id (`pm.environment.set('<entity>_id', response.data.id)`).

---

## 3) Per-request shape (match the code exactly)

- **Auth per request:** an `auth` bearer block (`{{user_token}}`, or `{{temp-token}}` for the temp stage) **plus** an explicit header `Authorization: Bearer {{user_token}}`. Public endpoints: no auth.
- **Headers:** `Accept: application/json` (always, `description:"required"`); `Authorization` on protected requests. Localization is the query param **`?lang=ar`**, NOT a header. Don't set `Content-Type` (formdata sets it).
- **Body = `formdata`** (base uses zero raw-JSON bodies): scalar fields `type:"text"` with the **Laravel rule in `description`**; file fields `type:"file"`, key suffixed `[]` (`files[]`, `images[]`). URL = `{{base_url}}<segment>` (+ `?page=&per_page=` for lists).

---

## 4) Saved examples — in the request's `response[]` array

Attach a saved `response` per real scenario, emoji-named like `save`: `✅ success`, `⚠️ validation error`,
`❌ unauthenticated`, and as applicable `no subscription`, `empty`, `not found`. On re-runs **overwrite** stale examples — never duplicate. Envelope (from `app/Traits/Response/`, **Arabic messages**):
- **Success 200** (creates also 200): `{ "message": "تم ... بنجاح.", "data": { ... } }`
- **Validation 422**: `{ "message": "...", "errors": { "field": ["..."] } }`
- **Unauthenticated 401**: `{ "message": "...", "data": [] }` · plus 400/403/404 per the controller.

Example data = realistic values from `analysis.md`/seeders (real enums, consistent ids), Arabic for `ar`; success `data` mirrors the **Resource** exactly. No secrets/tokens/passwords.

---

## 5) Per-request documentation (`request.description`) — mirror save

Markdown derived from the code: one-line purpose · **Design (Figma) link — الرابط الكامل للشاشة، لا الـ node-id الخام**
(ابنِه آليًا: `https://www.figma.com/design/<fileKey>/<name>?node-id=<node بـ `-` بدل `:`>&m=dev` — الـ `fileKey` من
`brand-identity.md`، والـ node من خطة الـ endpoint بعد استبدال `254:1955`→`254-1955`. لو الخطة كتبت node-id خام، حوّله؛
لا تكتب `254:1955` وحده) · Method/URL ·
Authentication (the real middleware chain) · Headers · Request body (the `<FormRequest>` — **every field**: name,
rule, required/optional, enum values + meaning) · Success response (`<Resource>` fields) · Error responses (only the
ones this endpoint produces). Body + examples + docs must describe the **same** contract.

---

## 6) Idempotent updates (subsequent runs)
1. Resolve the **section → flow** folder path in `item[]` (create the section — `Auth` / `Logic` / `Settings` — and the flow folder if missing).
2. Find the request by kebab-case name → **update** it; not found → **add** it. Never duplicate an endpoint.
3. Update method/url/auth/headers/body/test-script, overwrite examples (§4), rewrite the description (§5).

---

## 7) Verify (definition of done)
- `docs/postman/<project>.postman_collection.json` is **valid JSON**, Collection v2.1, imports cleanly.
- Structure is **`audience → section (Auth/Logic/Settings) → flow`**; `profile`+`notifications` sit under `Auth`, static/public content under `Settings`; one request per endpoint (re-run created **no duplicate**).
- Auth per request (bearer + explicit header); public = none. Token pipeline works end-to-end (login → temp-token → user_token) with no manual paste.
- Bodies formdata; files `type:file` `[]`; scalar fields carry the validation rule in `description`; localization via `?lang=ar`.
- Examples present with the **exact** Arabic envelopes; success `data` matches the Resource.
- Description complete (Figma **رابط كامل clickable** — لا node-id خام؛ `?node-id=<-وليس :>` + middleware + FormRequest + Service + errors); docs == examples == code.

## References (single source — do not duplicate here)
- **Model file to copy:** `save/docs/postman/save.postman_collection.json`
- Endpoint implementation + response envelope → [`build-api.md`](build-api.md) (runs first)
- Per-API plan (the request source) → `docs/project/api/<audience>/<flow>/<endpoint>.md`
- Real seed data → `docs/project/analysis.md` · identity/Figma → `docs/project/brand-identity.md`
