{
  "info": {
    "name": "Push API",
    "description": "Complete REST API collection for the Push notification infrastructure. Set the `baseUrl` and `bearerToken` / `apiKey` variables before running.\n\n**Base URL:** `http://localhost:4000`\n\n**Auth options:**\n- Bearer JWT → obtained from POST /auth/verify-code\n- Project API key → `x-api-key` header (from dashboard or POST /projects response)",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "_postman_id": "push-api-v1"
  },
  "variable": [
    { "key": "baseUrl",       "value": "http://localhost:4000", "type": "string" },
    { "key": "bearerToken",   "value": "",                     "type": "string", "description": "JWT from POST /auth/verify-code" },
    { "key": "apiKey",        "value": "",                     "type": "string", "description": "Project API key (x-api-key)" },
    { "key": "projectId",     "value": "1",                    "type": "string" },
    { "key": "subscriberId",  "value": "1",                    "type": "string" },
    { "key": "customerId",    "value": "1",                    "type": "string" },
    { "key": "notificationId","value": "",                     "type": "string", "description": "UUID of a notification" }
  ],
  "auth": {
    "type": "bearer",
    "bearer": [{ "key": "token", "value": "{{bearerToken}}", "type": "string" }]
  },
  "item": [
    {
      "name": "Auth",
      "description": "Email OTP authentication flow.",
      "item": [
        {
          "name": "Request Login Code",
          "request": {
            "auth": { "type": "noauth" },
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/auth/request-code", "host": ["{{baseUrl}}"], "path": ["auth","request-code"] },
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"user@example.com\"\n}",
              "options": { "raw": { "language": "json" } }
            },
            "description": "Sends a 6-digit OTP to the email address. Code expires in 10 minutes."
          }
        },
        {
          "name": "Verify Code & Get Token",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "var json = pm.response.json();",
                  "if (json.token) { pm.collectionVariables.set('bearerToken', json.token); }",
                  "if (json.project && json.project.id) { pm.collectionVariables.set('projectId', String(json.project.id)); }",
                  "if (json.project && json.project.api_key) { pm.collectionVariables.set('apiKey', json.project.api_key); }",
                  "if (json.customer && json.customer.id) { pm.collectionVariables.set('customerId', String(json.customer.id)); }"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "auth": { "type": "noauth" },
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/auth/verify-code", "host": ["{{baseUrl}}"], "path": ["auth","verify-code"] },
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"user@example.com\",\n  \"code\":  \"483920\"\n}",
              "options": { "raw": { "language": "json" } }
            },
            "description": "Verifies OTP. Auto-creates customer + project on first login. **Saves token, projectId, apiKey, customerId to collection variables automatically.**"
          }
        },
        {
          "name": "Get Current User (me)",
          "request": {
            "method": "GET",
            "url": { "raw": "{{baseUrl}}/auth/me", "host": ["{{baseUrl}}"], "path": ["auth","me"] },
            "description": "Returns the authenticated customer and their default project."
          }
        }
      ]
    },
    {
      "name": "Projects",
      "description": "Project management endpoints.",
      "item": [
        {
          "name": "List Projects",
          "request": {
            "method": "GET",
            "url": { "raw": "{{baseUrl}}/projects", "host": ["{{baseUrl}}"], "path": ["projects"] },
            "description": "Returns all projects belonging to the authenticated customer."
          }
        },
        {
          "name": "Create Project",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "var json = pm.response.json();",
                  "if (json.project && json.project.id) { pm.collectionVariables.set('projectId', String(json.project.id)); }",
                  "if (json.project && json.project.api_key) { pm.collectionVariables.set('apiKey', json.project.api_key); }"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/projects", "host": ["{{baseUrl}}"], "path": ["projects"] },
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"My New Project\"\n}",
              "options": { "raw": { "language": "json" } }
            },
            "description": "Creates a project. API key auto-generated. **Saves projectId and apiKey to collection variables.**"
          }
        },
        {
          "name": "Update Project",
          "request": {
            "method": "PUT",
            "url": { "raw": "{{baseUrl}}/projects/{{projectId}}", "host": ["{{baseUrl}}"], "path": ["projects","{{projectId}}"] },
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Renamed Project\"\n}",
              "options": { "raw": { "language": "json" } }
            },
            "description": "Renames a project. Must be the owning customer."
          }
        },
        {
          "name": "Regenerate API Key",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "var json = pm.response.json();",
                  "if (json.apiKey) { pm.collectionVariables.set('apiKey', json.apiKey); }"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/projects/{{projectId}}/regenerate-key", "host": ["{{baseUrl}}"], "path": ["projects","{{projectId}}","regenerate-key"] },
            "description": "Invalidates the current API key and issues a new one. **Saves new apiKey to collection variables.**"
          }
        },
        {
          "name": "Get Branding (auth context)",
          "request": {
            "method": "GET",
            "url": { "raw": "{{baseUrl}}/projects/branding", "host": ["{{baseUrl}}"], "path": ["projects","branding"] },
            "description": "Returns branding for the project in the auth context. No :id required."
          }
        },
        {
          "name": "Set Branding (auth context)",
          "request": {
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/projects/branding", "host": ["{{baseUrl}}"], "path": ["projects","branding"] },
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"brandName\":    \"Acme Corp\",\n  \"iconUrl\":      \"https://acme.com/icon.png\",\n  \"badgeUrl\":     \"https://acme.com/badge.png\",\n  \"heroImageUrl\": \"https://acme.com/hero.jpg\",\n  \"themeColor\":   \"#0070F3\"\n}",
              "options": { "raw": { "language": "json" } }
            },
            "description": "Upserts branding. All fields optional. Used by the subscribe page and auto-applied to outgoing notifications."
          }
        },
        {
          "name": "Get Branding by Project ID (public)",
          "request": {
            "auth": { "type": "noauth" },
            "method": "GET",
            "url": { "raw": "{{baseUrl}}/projects/{{projectId}}/branding", "host": ["{{baseUrl}}"], "path": ["projects","{{projectId}}","branding"] },
            "description": "Public endpoint. Used by hosted subscribe pages to load your brand."
          }
        },
        {
          "name": "Set Branding by Project ID",
          "request": {
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/projects/{{projectId}}/branding", "host": ["{{baseUrl}}"], "path": ["projects","{{projectId}}","branding"] },
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"brandName\":    \"Acme Corp\",\n  \"iconUrl\":      \"https://acme.com/icon.png\",\n  \"badgeUrl\":     \"https://acme.com/badge.png\",\n  \"heroImageUrl\": \"https://acme.com/hero.jpg\",\n  \"themeColor\":   \"#0070F3\"\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "Get Project Analytics",
          "request": {
            "method": "GET",
            "url": { "raw": "{{baseUrl}}/projects/{{projectId}}/analytics", "host": ["{{baseUrl}}"], "path": ["projects","{{projectId}}","analytics"] },
            "description": "Returns totalSubscribers, notificationsSent, impressions, clicks, CTR, topNotifications[], subscriberGrowth[]."
          }
        }
      ]
    },
    {
      "name": "Subscribers",
      "description": "Subscriber registration and management.",
      "item": [
        {
          "name": "Register Subscriber (public)",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "var json = pm.response.json();",
                  "if (json.subscriberId) { pm.collectionVariables.set('subscriberId', String(json.subscriberId)); }"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "auth": { "type": "noauth" },
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/subscribers/register", "host": ["{{baseUrl}}"], "path": ["subscribers","register"] },
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"projectId\": {{projectId}},\n  \"subscription\": {\n    \"endpoint\": \"https://fcm.googleapis.com/fcm/send/example-endpoint\",\n    \"keys\": {\n      \"p256dh\": \"BNcRdreALRFXTkOOUHK1EtK2wtaz5Ry4YfYCA_0QTpQtUbVlTGet\",\n      \"auth\":   \"tBHItJI5svbpez7KI4CCXg\"\n    }\n  },\n  \"browser\":    \"Chrome\",\n  \"os\":         \"Windows\",\n  \"deviceType\": \"desktop\"\n}",
              "options": { "raw": { "language": "json" } }
            },
            "description": "Called by the service worker when a user opts in. Deduplicates by endpoint. **Saves subscriberId to collection variables.**"
          }
        },
        {
          "name": "List Subscribers",
          "request": {
            "method": "GET",
            "url": { "raw": "{{baseUrl}}/subscribers", "host": ["{{baseUrl}}"], "path": ["subscribers"] },
            "description": "Scoped to project (API key) or customer (JWT)."
          }
        },
        {
          "name": "Create Subscriber (manual)",
          "request": {
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/subscribers", "host": ["{{baseUrl}}"], "path": ["subscribers"] },
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"subscription\": {\n    \"endpoint\": \"https://fcm.googleapis.com/fcm/send/manual-endpoint\",\n    \"keys\": {\n      \"p256dh\": \"BNcRdreALRFXTkOOUHK1EtK2wtaz5Ry4YfYCA_0QTpQtUbVlTGet\",\n      \"auth\":   \"tBHItJI5svbpez7KI4CCXg\"\n    }\n  },\n  \"browser\":    \"Firefox\",\n  \"deviceType\": \"mobile\"\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "Delete Subscriber",
          "request": {
            "method": "DELETE",
            "url": { "raw": "{{baseUrl}}/subscribers/{{subscriberId}}", "host": ["{{baseUrl}}"], "path": ["subscribers","{{subscriberId}}"] },
            "description": "Permanently removes a subscriber. Must belong to the authenticated project or customer."
          }
        }
      ]
    },
    {
      "name": "Notifications",
      "description": "Send notifications and view history.",
      "item": [
        {
          "name": "Send — Web Push (all subscribers)",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "// Store the first notificationId from results if available",
                  "var json = pm.response.json();",
                  "if (json.notificationId) { pm.collectionVariables.set('notificationId', json.notificationId); }"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/notifications/send", "host": ["{{baseUrl}}"], "path": ["notifications","send"] },
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "x-api-key",    "value": "{{apiKey}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"type\": \"web\",\n  \"target\": { \"all\": true },\n  \"payload\": {\n    \"title\":    \"New feature launched 🎉\",\n    \"body\":     \"Click to learn more about what's new.\",\n    \"clickUrl\": \"https://yourdomain.com/features\",\n    \"icon\":     \"https://yourdomain.com/icon.png\",\n    \"badge\":    \"https://yourdomain.com/badge.png\",\n    \"image\":    \"https://yourdomain.com/banner.png\",\n    \"data\":     { \"campaignId\": \"launch-2026\" }\n  }\n}",
              "options": { "raw": { "language": "json" } }
            },
            "description": "Bulk send to all project subscribers. Project branding (icon, badge, title prefix) is automatically applied if not provided."
          }
        },
        {
          "name": "Send — Web Push (specific subscribers)",
          "request": {
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/notifications/send", "host": ["{{baseUrl}}"], "path": ["notifications","send"] },
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "x-api-key",    "value": "{{apiKey}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"type\": \"web\",\n  \"target\": { \"subscriberIds\": [{{subscriberId}}] },\n  \"payload\": {\n    \"title\": \"Hey there!\",\n    \"body\":  \"This is a targeted push notification.\"\n  }\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "Send — Web Push (direct subscription object)",
          "request": {
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/notifications/send", "host": ["{{baseUrl}}"], "path": ["notifications","send"] },
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "x-api-key",    "value": "{{apiKey}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"type\": \"web\",\n  \"target\": {\n    \"endpoint\": \"https://fcm.googleapis.com/fcm/send/example-endpoint\",\n    \"keys\": {\n      \"p256dh\": \"BNcRdreALRFXTkOOUHK1EtK2wtaz5Ry4YfYCA_0QTpQtUbVlTGet\",\n      \"auth\":   \"tBHItJI5svbpez7KI4CCXg\"\n    }\n  },\n  \"payload\": {\n    \"title\": \"Direct push\",\n    \"body\":  \"Sent directly to a subscription object.\"\n  }\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "Send — Mobile (Android / FCM)",
          "request": {
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/notifications/send", "host": ["{{baseUrl}}"], "path": ["notifications","send"] },
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "x-api-key",    "value": "{{apiKey}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"type\":   \"mobile\",\n  \"target\": { \"platform\": \"android\", \"token\": \"APA91bHPRgkFl...\" },\n  \"payload\": {\n    \"title\": \"Update available\",\n    \"body\":  \"Version 2.0 is ready to install.\",\n    \"data\":  { \"screen\": \"updates\" }\n  }\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "Send — Mobile (iOS / APNs)",
          "request": {
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/notifications/send", "host": ["{{baseUrl}}"], "path": ["notifications","send"] },
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "x-api-key",    "value": "{{apiKey}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"type\":   \"mobile\",\n  \"target\": { \"platform\": \"ios\", \"token\": \"apns_device_token_here\" },\n  \"payload\": {\n    \"title\": \"You have a new message\",\n    \"body\":  \"Tap to read it.\",\n    \"data\":  { \"messageId\": \"msg_123\" }\n  }\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "Send — Email",
          "request": {
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/notifications/send", "host": ["{{baseUrl}}"], "path": ["notifications","send"] },
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "x-api-key",    "value": "{{apiKey}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"type\":    \"email\",\n  \"target\":  \"recipient@example.com\",\n  \"payload\": {\n    \"subject\": \"Your order has shipped\",\n    \"body\":    \"<p>Your order #1234 is on its way. Track it <a href='https://track.example.com'>here</a>.</p>\"\n  }\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "Send — SMS",
          "request": {
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/notifications/send", "host": ["{{baseUrl}}"], "path": ["notifications","send"] },
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "x-api-key",    "value": "{{apiKey}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"type\":    \"sms\",\n  \"target\":  \"+14155552671\",\n  \"payload\": {\n    \"message\": \"Your verification code is 482910. It expires in 10 minutes.\"\n  }\n}",
              "options": { "raw": { "language": "json" } }
            }
          }
        },
        {
          "name": "Get Notification History",
          "request": {
            "method": "GET",
            "url": { "raw": "{{baseUrl}}/notifications/history", "host": ["{{baseUrl}}"], "path": ["notifications","history"] },
            "description": "Returns all notifications for the authenticated project, newest first."
          }
        },
        {
          "name": "Test Send (all providers)",
          "request": {
            "auth": { "type": "noauth" },
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/notifications/test/send", "host": ["{{baseUrl}}"], "path": ["notifications","test","send"] },
            "description": "Exercises all configured providers using TEST_* env vars. No auth required. Use for health checks."
          }
        }
      ]
    },
    {
      "name": "Events",
      "description": "Notification lifecycle event tracking.",
      "item": [
        {
          "name": "Track Event (public)",
          "request": {
            "auth": { "type": "noauth" },
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/events/track", "host": ["{{baseUrl}}"], "path": ["events","track"] },
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"notificationId\": \"{{notificationId}}\",\n  \"subscriberId\":   {{subscriberId}},\n  \"eventType\":      \"clicked\",\n  \"projectId\":      {{projectId}},\n  \"userAgent\":      \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\",\n  \"timestamp\":      \"2026-03-20T14:31:00.000Z\"\n}",
              "options": { "raw": { "language": "json" } }
            },
            "description": "Records a notification lifecycle event. Called by the service worker. Valid eventType values: delivered, shown, clicked."
          }
        },
        {
          "name": "Get Events for Subscriber",
          "request": {
            "method": "GET",
            "url": { "raw": "{{baseUrl}}/events/subscriber/{{subscriberId}}", "host": ["{{baseUrl}}"], "path": ["events","subscriber","{{subscriberId}}"] },
            "description": "Returns all events for a subscriber, newest first."
          }
        },
        {
          "name": "Get Notification Detail & Metrics",
          "request": {
            "method": "GET",
            "url": { "raw": "{{baseUrl}}/events/notifications/{{notificationId}}", "host": ["{{baseUrl}}"], "path": ["events","notifications","{{notificationId}}"] },
            "description": "Returns full notification record, aggregated metrics (delivery, impressions, clicks, CTR), and raw event timeline."
          }
        }
      ]
    },
    {
      "name": "Customers",
      "description": "Customer account management.",
      "item": [
        {
          "name": "List Customers (admin)",
          "request": {
            "method": "GET",
            "url": { "raw": "{{baseUrl}}/customers", "host": ["{{baseUrl}}"], "path": ["customers"] },
            "description": "Returns all customers. **Admin only** — requires Bearer JWT with role=admin."
          }
        },
        {
          "name": "Create Customer (admin)",
          "request": {
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/customers", "host": ["{{baseUrl}}"], "path": ["customers"] },
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\":  \"Acme Corp\",\n  \"email\": \"admin@acme.com\",\n  \"phone\": \"+14155552671\"\n}",
              "options": { "raw": { "language": "json" } }
            },
            "description": "Creates a customer in the CRM. **Admin only** — requires Bearer JWT with role=admin."
          }
        },
        {
          "name": "Get My Customer (API key auth)",
          "request": {
            "auth": { "type": "noauth" },
            "method": "GET",
            "url": { "raw": "{{baseUrl}}/customers/me", "host": ["{{baseUrl}}"], "path": ["customers","me"] },
            "header": [{ "key": "x-api-key", "value": "{{apiKey}}" }],
            "description": "Uses x-api-key authentication only. Returns the customer who owns the provided API key."
          }
        },
        {
          "name": "Regenerate Customer API Key",
          "request": {
            "auth": { "type": "noauth" },
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/customers/regenerate-key", "host": ["{{baseUrl}}"], "path": ["customers","regenerate-key"] },
            "header": [{ "key": "x-api-key", "value": "{{apiKey}}" }],
            "description": "Regenerates the customer-level API key. Requires x-api-key auth."
          }
        },
        {
          "name": "Get Customer by ID",
          "request": {
            "method": "GET",
            "url": { "raw": "{{baseUrl}}/customers/{{customerId}}", "host": ["{{baseUrl}}"], "path": ["customers","{{customerId}}"] }
          }
        },
        {
          "name": "Update Customer",
          "request": {
            "method": "PUT",
            "url": { "raw": "{{baseUrl}}/customers/{{customerId}}", "host": ["{{baseUrl}}"], "path": ["customers","{{customerId}}"] },
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\":          \"Updated Name\",\n  \"email\":         \"updated@example.com\",\n  \"phone\":         \"+14155550000\",\n  \"preferences\":   { \"marketing\": true },\n  \"device_tokens\": {}\n}",
              "options": { "raw": { "language": "json" } }
            },
            "description": "Partially updates a customer record. All fields optional."
          }
        },
        {
          "name": "Delete Customer",
          "request": {
            "method": "DELETE",
            "url": { "raw": "{{baseUrl}}/customers/{{customerId}}", "host": ["{{baseUrl}}"], "path": ["customers","{{customerId}}"] },
            "description": "Permanently deletes the customer record."
          }
        },
        {
          "name": "Register Device Token",
          "request": {
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/customers/{{customerId}}/device-token", "host": ["{{baseUrl}}"], "path": ["customers","{{customerId}}","device-token"] },
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"platform\": \"android\",\n  \"token\":    \"APA91bHPRgkFl...\"\n}",
              "options": { "raw": { "language": "json" } }
            },
            "description": "Registers or updates a mobile device token. platform: android | ios."
          }
        },
        {
          "name": "Set Customer Role (admin)",
          "request": {
            "method": "PATCH",
            "url": { "raw": "{{baseUrl}}/customers/{{customerId}}/role", "host": ["{{baseUrl}}"], "path": ["customers","{{customerId}}","role"] },
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"role\": \"admin\"\n}",
              "options": { "raw": { "language": "json" } }
            },
            "description": "Sets a customer's role to `user` or `admin`. **Admin only.**"
          }
        }
      ]
    },
    {
      "name": "Stripe",
      "description": "Billing and subscription management via Stripe. Checkout and portal endpoints require admin Bearer JWT.",
      "item": [
        {
          "name": "Create Checkout Session (admin)",
          "request": {
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/stripe/checkout", "host": ["{{baseUrl}}"], "path": ["stripe","checkout"] },
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"customerId\": {{customerId}}\n}",
              "options": { "raw": { "language": "json" } }
            },
            "description": "Creates a Stripe Checkout session for the Organisation tier. Returns `{ url }` — redirect the user to this URL. **Admin only.**"
          }
        },
        {
          "name": "Billing Portal (admin)",
          "request": {
            "method": "GET",
            "url": { "raw": "{{baseUrl}}/stripe/portal/{{customerId}}", "host": ["{{baseUrl}}"], "path": ["stripe","portal","{{customerId}}"] },
            "description": "Returns a Stripe-hosted billing portal URL for the customer. **Admin only.**"
          }
        },
        {
          "name": "Stripe Webhook (Stripe-signed)",
          "request": {
            "auth": { "type": "noauth" },
            "method": "POST",
            "url": { "raw": "{{baseUrl}}/stripe/webhook", "host": ["{{baseUrl}}"], "path": ["stripe","webhook"] },
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "stripe-signature", "value": "<stripe-signature-value>", "description": "Provided by Stripe on each webhook call. Required for HMAC verification." }
            ],
            "body": {
              "mode": "raw",
              "raw": "<raw Stripe event JSON body>",
              "options": { "raw": { "language": "json" } }
            },
            "description": "Receives Stripe event callbacks. The body **must** be the raw (unparsed) JSON — do not pretty-print it or signature verification will fail. Stripe calls this automatically; this entry is for manual testing only."
          }
        }
      ]
    },
    {
      "name": "Health",
      "description": "Service health check.",
      "item": [
        {
          "name": "Health Check",
          "request": {
            "auth": { "type": "noauth" },
            "method": "GET",
            "url": { "raw": "{{baseUrl}}/health", "host": ["{{baseUrl}}"], "path": ["health"] },
            "description": "Returns `{ status, checks: { db, vapid, firebase, apns, twilio } }`. No auth required. Use to verify the service is running and all integrations are configured."
          }
        }
      ]
    }
  ]
}
