{
  "info": {
    "_postman_id": "storysign-api-collection",
    "name": "StorySign API",
    "description": "Complete StorySign backend API collection.\n\n**Base URL:** `{{baseUrl}}` (default: http://localhost:3000/api/v1)\n\n**Auth:** Most endpoints use Bearer `{{accessToken}}`. Run the Login requests in each flow folder first — they auto-save tokens to collection variables.\n\n**Roles:** reader | author | admin\n\n**Enums:**\n- Book status: `unsigned`, `signed`\n- Request status: `submitted`, `in_progress`, `delivered`, `rejected`\n- User status: `active`, `inactive`, `suspended`\n- Plan type: `monthly`, `yearly`\n- Analytics period: `monthly`, `6months`, `yearly`\n- Push recipient: `all`, `readers`, `authors`\n- Privacy audience: `reader`, `author`",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    { "key": "baseUrl", "value": "http://localhost:3000/api/v1" },
    { "key": "accessToken", "value": "" },
    { "key": "refreshToken", "value": "" },
    { "key": "readerToken", "value": "" },
    { "key": "authorToken", "value": "" },
    { "key": "adminToken", "value": "" },
    { "key": "readerId", "value": "" },
    { "key": "authorId", "value": "" },
    { "key": "bookId", "value": "" },
    { "key": "autographRequestId", "value": "" },
    { "key": "planId", "value": "" },
    { "key": "paymentIntentId", "value": "" },
    { "key": "notificationId", "value": "" },
    { "key": "faqId", "value": "" },
    { "key": "privacyPolicyId", "value": "" },
    { "key": "queryId", "value": "" },
    { "key": "fcmToken", "value": "your-device-fcm-token" }
  ],
  "auth": {
    "type": "bearer",
    "bearer": [{ "key": "token", "value": "{{accessToken}}", "type": "string" }]
  },
  "item": [
    {
      "name": "0. General",
      "item": [
        {
          "name": "Health Check",
          "request": {
            "auth": { "type": "noauth" },
            "method": "GET",
            "header": [],
            "url": "{{baseUrl}}/health",
            "description": "Public health check. No auth required."
          }
        },
        {
          "name": "Get Autograph Fee (Public)",
          "request": {
            "auth": { "type": "noauth" },
            "method": "GET",
            "header": [],
            "url": "{{baseUrl}}/payments/autograph-fee",
            "description": "Returns current autograph signing fee set by admin."
          }
        },
        {
          "name": "Refresh Token",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "if (pm.response.code === 200 || pm.response.code === 201) {",
                  "  const json = pm.response.json();",
                  "  if (json.accessToken) pm.collectionVariables.set('accessToken', json.accessToken);",
                  "  if (json.refreshToken) pm.collectionVariables.set('refreshToken', json.refreshToken);",
                  "}"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "auth": { "type": "noauth" },
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"refreshToken\": \"{{refreshToken}}\"\n}"
            },
            "url": "{{baseUrl}}/auth/refresh",
            "description": "Exchange a valid refreshToken for new accessToken + refreshToken pair. No Bearer auth required."
          }
        },
        {
          "name": "Stripe Webhook",
          "request": {
            "auth": { "type": "noauth" },
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "stripe-signature", "value": "whsec_...", "description": "Stripe webhook signature header" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"id\": \"evt_xxx\",\n  \"type\": \"payment_intent.succeeded\",\n  \"data\": { \"object\": { \"id\": \"pi_xxx\", \"metadata\": { \"type\": \"autograph\", \"userId\": \"\", \"requestId\": \"\" } } }\n}"
            },
            "url": "{{baseUrl}}/webhooks/stripe",
            "description": "Stripe webhook endpoint. Used by Stripe servers — not called from the app. Requires raw body + stripe-signature header."
          }
        }
      ]
    },
    {
      "name": "1. Reader Flow",
      "description": "Complete reader journey: signup → browse authors → upload books → request autograph → track requests → profile & support.",
      "item": [
        {
          "name": "1.1 Auth & Onboarding",
          "item": [
            {
              "name": "Signup (Reader)",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "if (pm.response.code === 201 || pm.response.code === 200) {",
                      "  const json = pm.response.json();",
                      "  if (json.accessToken) {",
                      "    pm.collectionVariables.set('readerToken', json.accessToken);",
                      "    pm.collectionVariables.set('accessToken', json.accessToken);",
                      "  }",
                      "  if (json.refreshToken) pm.collectionVariables.set('refreshToken', json.refreshToken);",
                      "  if (json.user?.id) pm.collectionVariables.set('readerId', json.user.id);",
                      "}"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "auth": { "type": "noauth" },
                "method": "POST",
                "header": [],
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    { "key": "role", "value": "reader", "type": "text", "description": "Required: reader" },
                    { "key": "fullName", "value": "John Reader", "type": "text" },
                    { "key": "email", "value": "reader@example.com", "type": "text" },
                    { "key": "password", "value": "Reader@12345", "type": "text", "description": "Min 8 chars" },
                    { "key": "confirmPassword", "value": "Reader@12345", "type": "text" },
                    { "key": "profilePicture", "type": "file", "src": [], "description": "Optional image file" }
                  ]
                },
                "url": "{{baseUrl}}/auth/signup",
                "description": "Register a new reader account. Multipart form-data."
              }
            },
            {
              "name": "Login (Reader)",
              "event": [
                {
                  "listen": "prerequest",
                  "script": { "exec": ["pm.collectionVariables.set('accessToken', '');"], "type": "text/javascript" }
                },
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "if (pm.response.code === 200 || pm.response.code === 201) {",
                      "  const json = pm.response.json();",
                      "  if (json.accessToken) {",
                      "    pm.collectionVariables.set('readerToken', json.accessToken);",
                      "    pm.collectionVariables.set('accessToken', json.accessToken);",
                      "  }",
                      "  if (json.refreshToken) pm.collectionVariables.set('refreshToken', json.refreshToken);",
                      "  if (json.user?.id) pm.collectionVariables.set('readerId', json.user.id);",
                      "}"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "auth": { "type": "noauth" },
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"email\": \"reader@example.com\",\n  \"password\": \"Reader@12345\"\n}"
                },
                "url": "{{baseUrl}}/auth/login",
                "description": "Login as reader. Returns accessToken, refreshToken, user object with role."
              }
            },
            {
              "name": "Forgot Password - Step 1 (Send OTP)",
              "request": {
                "auth": { "type": "noauth" },
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"email\": \"reader@example.com\"\n}"
                },
                "url": "{{baseUrl}}/auth/forgot-password",
                "description": "Sends 6-digit OTP to email (stored in Redis). In dev, OTP is logged to server console if SMTP not configured."
              }
            },
            {
              "name": "Forgot Password - Step 2 (Verify OTP)",
              "request": {
                "auth": { "type": "noauth" },
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"email\": \"reader@example.com\",\n  \"code\": \"123456\"\n}"
                },
                "url": "{{baseUrl}}/auth/forgot-password/verify",
                "description": "Verify the 6-digit OTP code."
              }
            },
            {
              "name": "Forgot Password - Step 3 (Reset Password)",
              "request": {
                "auth": { "type": "noauth" },
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"email\": \"reader@example.com\",\n  \"code\": \"123456\",\n  \"newPassword\": \"NewReader@123\",\n  \"confirmPassword\": \"NewReader@123\"\n}"
                },
                "url": "{{baseUrl}}/auth/forgot-password/reset",
                "description": "Set new password after OTP verification."
              }
            },
            {
              "name": "Change Password",
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"currentPassword\": \"Reader@12345\",\n  \"newPassword\": \"NewReader@123\",\n  \"confirmPassword\": \"NewReader@123\"\n}"
                },
                "url": "{{baseUrl}}/auth/change-password",
                "description": "Change password while logged in. Requires Bearer token."
              }
            },
            {
              "name": "Use Reader Token",
              "event": [
                {
                  "listen": "prerequest",
                  "script": {
                    "exec": ["pm.collectionVariables.set('accessToken', pm.collectionVariables.get('readerToken'));"],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/reader/profile",
                "description": "Helper request — sets accessToken to readerToken. Run before other reader requests."
              }
            }
          ]
        },
        {
          "name": "1.2 Browse Authors",
          "item": [
            {
              "name": "List All Authors",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/reader/authors?search=",
                  "host": ["{{baseUrl}}"],
                  "path": ["reader", "authors"],
                  "query": [
                    { "key": "search", "value": "", "description": "Optional: filter by author name" }
                  ]
                },
                "description": "List all active authors on the platform."
              }
            },
            {
              "name": "Author Details",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/reader/authors/{{authorId}}",
                "description": "Get author profile: name, picture, bio, date joined."
              }
            }
          ]
        },
        {
          "name": "1.3 Upload Book (Library Only)",
          "item": [
            {
              "name": "Upload Book",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "if (pm.response.code === 200 || pm.response.code === 201) {",
                      "  const json = pm.response.json();",
                      "  if (json.id) pm.collectionVariables.set('bookId', json.id);",
                      "}"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "POST",
                "header": [],
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    { "key": "title", "value": "My First Book", "type": "text", "description": "Book name" },
                    { "key": "bookPdf", "type": "file", "src": [], "description": "PDF file (required)" },
                    { "key": "coverImage", "type": "file", "src": [], "description": "Cover image (required)" }
                  ]
                },
                "url": "{{baseUrl}}/reader/books/upload",
                "description": "Upload book to library without payment. Status will be `unsigned`. Response includes fromLibrary: true and feeAmount."
              }
            }
          ]
        },
        {
          "name": "1.4 My Library",
          "item": [
            {
              "name": "List My Books",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/reader/library?page=1&limit=10&status=all",
                  "host": ["{{baseUrl}}"],
                  "path": ["reader", "library"],
                  "query": [
                    { "key": "page", "value": "1" },
                    { "key": "limit", "value": "10" },
                    { "key": "status", "value": "all", "description": "all | signed | unsigned" }
                  ]
                },
                "description": "List reader's book library. Each item includes fromLibrary, feeAmount, coverImage, downloadUrl, and authorName/author for signed books."
              }
            },
            {
              "name": "Book Details",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/reader/library/{{bookId}}",
                "description": "Get single book details. If an unpaid autograph request exists: autographRequestId, paymentIntentId, and clientSecret are included so payment can be resumed."
              }
            }
          ]
        },
        {
          "name": "1.5 Request Autograph",
          "item": [
            {
              "name": "Request Autograph (New Book)",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "if (pm.response.code === 200 || pm.response.code === 201) {",
                      "  const json = pm.response.json();",
                      "  if (json.request?.id) pm.collectionVariables.set('autographRequestId', json.request.id);",
                      "  if (json.paymentIntentId) pm.collectionVariables.set('paymentIntentId', json.paymentIntentId);",
                      "}"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "POST",
                "header": [],
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    { "key": "authorId", "value": "{{authorId}}", "type": "text", "description": "Required: author to sign" },
                    { "key": "bookTitle", "value": "Book To Sign", "type": "text" },
                    { "key": "personalMessage", "value": "Please sign on page 3!", "type": "text" },
                    { "key": "bookPdf", "type": "file", "src": [], "description": "Required if bookId not provided" },
                    { "key": "coverImage", "type": "file", "src": [], "description": "Required if bookId not provided" }
                  ]
                },
                "url": "{{baseUrl}}/reader/autograph-requests",
                "description": "Create autograph request with new book upload. Returns clientSecret + paymentIntentId for Stripe payment."
              }
            },
            {
              "name": "Request Autograph (From Library)",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "if (pm.response.code === 200 || pm.response.code === 201) {",
                      "  const json = pm.response.json();",
                      "  if (json.request?.id) pm.collectionVariables.set('autographRequestId', json.request.id);",
                      "  if (json.paymentIntentId) pm.collectionVariables.set('paymentIntentId', json.paymentIntentId);",
                      "}"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "POST",
                "header": [],
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    { "key": "authorId", "value": "{{authorId}}", "type": "text" },
                    { "key": "bookId", "value": "{{bookId}}", "type": "text", "description": "Existing library book ID — skips PDF/cover upload" },
                    { "key": "bookTitle", "value": "My First Book", "type": "text", "description": "Ignored when bookId provided" },
                    { "key": "personalMessage", "value": "Please sign my book!", "type": "text" }
                  ]
                },
                "url": "{{baseUrl}}/reader/autograph-requests",
                "description": "Request autograph for an existing library book. If an unpaid request already exists for this book, it is reused and returns paymentIntentId + clientSecret instead of creating a duplicate."
              }
            },
            {
              "name": "Confirm Payment (After Stripe)",
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"paymentIntentId\": \"{{paymentIntentId}}\"\n}"
                },
                "url": "{{baseUrl}}/reader/autograph-requests/confirm-payment",
                "description": "Call after Stripe payment succeeds. Marks request as paid and submitted. Webhook also handles this as backup."
              }
            },
            {
              "name": "Verify Payment (Alternative)",
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"paymentIntentId\": \"{{paymentIntentId}}\"\n}"
                },
                "url": "{{baseUrl}}/payments/verify-success",
                "description": "Generic payment verification endpoint. Prefer reader/autograph-requests/confirm-payment for autograph flow."
              }
            }
          ]
        },
        {
          "name": "1.6 My Requests",
          "item": [
            {
              "name": "List All Requests",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/reader/autograph-requests?page=1&limit=10&status=",
                  "host": ["{{baseUrl}}"],
                  "path": ["reader", "autograph-requests"],
                  "query": [
                    { "key": "page", "value": "1" },
                    { "key": "limit", "value": "10" },
                    { "key": "status", "value": "", "description": "Optional: submitted | in_progress | delivered | rejected" }
                  ]
                },
                "description": "List all autograph requests with optional status filter."
              }
            },
            {
              "name": "Request Details",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/reader/autograph-requests/{{autographRequestId}}",
                "description": "Full request details including status timeline dates. If unpaid: paymentIntentId and clientSecret are returned so Stripe payment can be resumed."
              }
            },
            {
              "name": "Record Download",
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"autographRequestId\": \"{{autographRequestId}}\"\n}"
                },
                "url": "{{baseUrl}}/reader/downloads/{{bookId}}",
                "description": "Record a download in download history. Returns downloadUrl (full public URL) plus history record."
              }
            }
          ]
        },
        {
          "name": "1.7 Profile & Stats",
          "item": [
            {
              "name": "Get Profile",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/reader/profile",
                "description": "Profile picture, email, full name, date joined."
              }
            },
            {
              "name": "Edit Profile",
              "request": {
                "method": "PATCH",
                "header": [],
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    { "key": "fullName", "value": "Updated Name", "type": "text" },
                    { "key": "profilePicture", "type": "file", "src": [], "description": "Optional new profile image" }
                  ]
                },
                "url": "{{baseUrl}}/reader/profile",
                "description": "Update name and/or profile picture."
              }
            },
            {
              "name": "Library Stats",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/reader/profile/stats",
                "description": "Returns: totalUploadedBooks, signedBooks, signRejected."
              }
            },
            {
              "name": "Download History",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/reader/download-history?page=1&limit=10",
                  "host": ["{{baseUrl}}"],
                  "path": ["reader", "download-history"],
                  "query": [
                    { "key": "page", "value": "1" },
                    { "key": "limit", "value": "10" }
                  ]
                },
                "description": "Download history with coverImage and full downloadUrl on each item."
              }
            }
          ]
        },
        {
          "name": "1.8 Notifications",
          "item": [
            {
              "name": "List Notifications",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/reader/notifications?page=1&limit=20",
                  "host": ["{{baseUrl}}"],
                  "path": ["reader", "notifications"],
                  "query": [
                    { "key": "page", "value": "1" },
                    { "key": "limit", "value": "20" }
                  ]
                },
                "description": "List in-app notifications."
              }
            },
            {
              "name": "Mark Notification Read",
              "request": {
                "method": "PATCH",
                "header": [],
                "url": "{{baseUrl}}/reader/notifications/{{notificationId}}/read",
                "description": "Mark a single notification as read."
              }
            }
          ]
        },
        {
          "name": "1.9 Support & Legal",
          "item": [
            {
              "name": "Contact Us",
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"John Reader\",\n  \"email\": \"reader@example.com\",\n  \"subject\": \"Need help\",\n  \"message\": \"I have a question about my signing request.\"\n}"
                },
                "url": "{{baseUrl}}/reader/contact",
                "description": "Submit contact form query to admin."
              }
            },
            {
              "name": "Help & Support",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/reader/help",
                "description": "Returns platform email, phone, supportUrl from admin settings."
              }
            },
            {
              "name": "FAQs",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/reader/faqs",
                "description": "List active FAQs managed by admin."
              }
            },
            {
              "name": "Privacy Policy",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/reader/privacy-policy",
                "description": "Reader privacy policy content."
              }
            }
          ]
        },
        {
          "name": "1.10 FCM Push",
          "item": [
            {
              "name": "Register FCM Token",
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"token\": \"{{fcmToken}}\"\n}"
                },
                "url": "{{baseUrl}}/reader/fcm-token",
                "description": "Register device FCM token for push notifications."
              }
            },
            {
              "name": "Remove FCM Token",
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"token\": \"{{fcmToken}}\"\n}"
                },
                "url": "{{baseUrl}}/reader/fcm-token/remove",
                "description": "Remove FCM token on logout."
              }
            }
          ]
        }
      ]
    },
    {
      "name": "2. Author Flow",
      "description": "Author journey: signup → subscribe → handle signing requests → approve & send signed PDF.",
      "item": [
        {
          "name": "2.1 Auth & Onboarding",
          "item": [
            {
              "name": "Signup (Author)",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "if (pm.response.code === 201 || pm.response.code === 200) {",
                      "  const json = pm.response.json();",
                      "  if (json.accessToken) {",
                      "    pm.collectionVariables.set('authorToken', json.accessToken);",
                      "    pm.collectionVariables.set('accessToken', json.accessToken);",
                      "  }",
                      "  if (json.refreshToken) pm.collectionVariables.set('refreshToken', json.refreshToken);",
                      "  if (json.user?.id) pm.collectionVariables.set('authorId', json.user.id);",
                      "}"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "auth": { "type": "noauth" },
                "method": "POST",
                "header": [],
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    { "key": "role", "value": "author", "type": "text" },
                    { "key": "fullName", "value": "Jane Author", "type": "text" },
                    { "key": "email", "value": "author@example.com", "type": "text" },
                    { "key": "password", "value": "Author@12345", "type": "text" },
                    { "key": "confirmPassword", "value": "Author@12345", "type": "text" },
                    { "key": "bio", "value": "Bestselling fiction writer with 10 published novels.", "type": "text", "description": "Required for authors" },
                    { "key": "profilePicture", "type": "file", "src": [] }
                  ]
                },
                "url": "{{baseUrl}}/auth/signup"
              }
            },
            {
              "name": "Login (Author)",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "if (pm.response.code === 200 || pm.response.code === 201) {",
                      "  const json = pm.response.json();",
                      "  if (json.accessToken) {",
                      "    pm.collectionVariables.set('authorToken', json.accessToken);",
                      "    pm.collectionVariables.set('accessToken', json.accessToken);",
                      "  }",
                      "  if (json.refreshToken) pm.collectionVariables.set('refreshToken', json.refreshToken);",
                      "  if (json.user?.id) pm.collectionVariables.set('authorId', json.user.id);",
                      "}"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "auth": { "type": "noauth" },
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"email\": \"author@example.com\",\n  \"password\": \"Author@12345\"\n}"
                },
                "url": "{{baseUrl}}/auth/login",
                "description": "Login as author. Response includes isSubscribed boolean — frontend gates dashboard if false."
              }
            },
            {
              "name": "Use Author Token",
              "event": [
                {
                  "listen": "prerequest",
                  "script": {
                    "exec": ["pm.collectionVariables.set('accessToken', pm.collectionVariables.get('authorToken'));"],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/author/profile",
                "description": "Helper — sets accessToken to authorToken."
              }
            }
          ]
        },
        {
          "name": "2.2 Subscription",
          "item": [
            {
              "name": "List Subscription Plans",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/author/subscription/plans?planType=",
                  "host": ["{{baseUrl}}"],
                  "path": ["author", "subscription", "plans"],
                  "query": [
                    { "key": "planType", "value": "", "description": "Optional: monthly | yearly" }
                  ]
                },
                "description": "List active subscription plans created by admin."
              }
            },
            {
              "name": "Checkout (Get Payment Intent)",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "if (pm.response.code === 200 || pm.response.code === 201) {",
                      "  const json = pm.response.json();",
                      "  if (json.paymentIntentId) pm.collectionVariables.set('paymentIntentId', json.paymentIntentId);",
                      "}"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"planId\": \"{{planId}}\"\n}"
                },
                "url": "{{baseUrl}}/author/subscription/checkout",
                "description": "Returns clientSecret + paymentIntentId for Stripe subscription payment."
              }
            },
            {
              "name": "Confirm Subscription Payment",
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"paymentIntentId\": \"{{paymentIntentId}}\"\n}"
                },
                "url": "{{baseUrl}}/author/subscription/confirm-payment",
                "description": "Activate subscription after Stripe payment succeeds."
              }
            },
            {
              "name": "Current Subscription",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/author/subscription/current",
                "description": "Returns plan name, dates, signs used/quota, remaining signs."
              }
            }
          ]
        },
        {
          "name": "2.3 Dashboard & Stats",
          "item": [
            {
              "name": "Sign Stats",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/author/stats",
                "description": "totalSignRequests, signedBooks, remainingSigns, pendingRequests."
              }
            }
          ]
        },
        {
          "name": "2.4 Signing Requests",
          "item": [
            {
              "name": "Pending Requests",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/author/requests/pending?page=1&limit=10",
                  "host": ["{{baseUrl}}"],
                  "path": ["author", "requests", "pending"],
                  "query": [
                    { "key": "page", "value": "1" },
                    { "key": "limit", "value": "10" }
                  ]
                },
                "description": "Paid requests with status submitted or in_progress."
              }
            },
            {
              "name": "Delivered Requests",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/author/requests/delivered?page=1&limit=10",
                  "host": ["{{baseUrl}}"],
                  "path": ["author", "requests", "delivered"],
                  "query": [
                    { "key": "page", "value": "1" },
                    { "key": "limit", "value": "10" }
                  ]
                },
                "description": "Author delivered screen — paid requests with status delivered."
              }
            },
            {
              "name": "List All Requests (Status Filter)",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/author/requests?page=1&limit=10&status=delivered",
                  "host": ["{{baseUrl}}"],
                  "path": ["author", "requests"],
                  "query": [
                    { "key": "page", "value": "1" },
                    { "key": "limit", "value": "10" },
                    { "key": "status", "value": "delivered", "description": "Optional: submitted | in_progress | delivered | rejected" }
                  ]
                },
                "description": "List author signing requests with optional status filter."
              }
            },
            {
              "name": "Request Details",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/author/requests/{{autographRequestId}}",
                "description": "Reader info, book PDF URL, personal message, book details."
              }
            },
            {
              "name": "Accept Request",
              "request": {
                "method": "POST",
                "header": [],
                "url": "{{baseUrl}}/author/requests/{{autographRequestId}}/accept",
                "description": "Accept request → status becomes in_progress. Requires active subscription."
              }
            },
            {
              "name": "Reject Request",
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"rejectionReason\": \"I am not accepting this genre at the moment.\"\n}"
                },
                "url": "{{baseUrl}}/author/requests/{{autographRequestId}}/reject",
                "description": "Reject with reason → status becomes rejected."
              }
            },
            {
              "name": "Approve & Send (Sign PDF)",
              "request": {
                "method": "POST",
                "header": [],
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    { "key": "signatureImage", "type": "file", "src": [], "description": "PNG/JPG signature image (required)" },
                    { "key": "pageIndex", "value": "2", "type": "text", "description": "0-based PDF page index" },
                    { "key": "xRatio", "value": "0.15", "type": "text", "description": "0-1 normalized X position" },
                    { "key": "yRatio", "value": "0.82", "type": "text", "description": "0-1 normalized Y position" },
                    { "key": "widthRatio", "value": "0.25", "type": "text", "description": "0-1 normalized width" },
                    { "key": "heightRatio", "value": "0.08", "type": "text", "description": "0-1 normalized height" },
                    { "key": "pageWidthPts", "value": "612", "type": "text", "description": "PDF page width in points" },
                    { "key": "pageHeightPts", "value": "792", "type": "text", "description": "PDF page height in points" },
                    { "key": "authorMessage", "value": "Enjoy your signed copy!", "type": "text", "description": "Optional message to reader" }
                  ]
                },
                "url": "{{baseUrl}}/author/requests/{{autographRequestId}}/approve-send",
                "description": "Burn signature into PDF at normalized coordinates. Status → delivered. Reader can download signed PDF."
              }
            }
          ]
        },
        {
          "name": "2.5 Profile",
          "item": [
            {
              "name": "Get Profile",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/author/profile",
                "description": "Profile, bio, active plan, total signed autographs, isSubscribed."
              }
            },
            {
              "name": "Edit Profile",
              "request": {
                "method": "PATCH",
                "header": [],
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    { "key": "fullName", "value": "Jane Author Updated", "type": "text" },
                    { "key": "bio", "value": "Updated author bio.", "type": "text" },
                    { "key": "profilePicture", "type": "file", "src": [] }
                  ]
                },
                "url": "{{baseUrl}}/author/profile"
              }
            },
            {
              "name": "Change Password",
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"currentPassword\": \"Author@12345\",\n  \"newPassword\": \"NewAuthor@123\",\n  \"confirmPassword\": \"NewAuthor@123\"\n}"
                },
                "url": "{{baseUrl}}/auth/change-password"
              }
            }
          ]
        },
        {
          "name": "2.6 Notifications & Support",
          "item": [
            {
              "name": "List Notifications",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/author/notifications?page=1&limit=20",
                  "host": ["{{baseUrl}}"],
                  "path": ["author", "notifications"],
                  "query": [
                    { "key": "page", "value": "1" },
                    { "key": "limit", "value": "20" }
                  ]
                }
              }
            },
            {
              "name": "Mark Notification Read",
              "request": {
                "method": "PATCH",
                "header": [],
                "url": "{{baseUrl}}/author/notifications/{{notificationId}}/read",
                "description": "Mark a single author notification as read."
              }
            },
            {
              "name": "Mark All Notifications Read",
              "request": {
                "method": "PATCH",
                "header": [],
                "url": "{{baseUrl}}/author/notifications/read-all",
                "description": "Mark all unread author notifications as read."
              }
            },
            {
              "name": "Contact Us",
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"Jane Author\",\n  \"email\": \"author@example.com\",\n  \"subject\": \"Need help\",\n  \"message\": \"I have a question about my subscription.\"\n}"
                },
                "url": "{{baseUrl}}/author/contact",
                "description": "Submit contact form query to admin (author flow)."
              }
            },
            {
              "name": "Help & Support",
              "request": { "method": "GET", "header": [], "url": "{{baseUrl}}/author/help" }
            },
            {
              "name": "FAQs",
              "request": { "method": "GET", "header": [], "url": "{{baseUrl}}/author/faqs" }
            },
            {
              "name": "Privacy Policy",
              "request": { "method": "GET", "header": [], "url": "{{baseUrl}}/author/privacy-policy" }
            }
          ]
        },
        {
          "name": "2.7 FCM Push",
          "item": [
            {
              "name": "Register FCM Token",
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": { "mode": "raw", "raw": "{\n  \"token\": \"{{fcmToken}}\"\n}" },
                "url": "{{baseUrl}}/author/fcm-token"
              }
            },
            {
              "name": "Remove FCM Token",
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": { "mode": "raw", "raw": "{\n  \"token\": \"{{fcmToken}}\"\n}" },
                "url": "{{baseUrl}}/author/fcm-token/remove"
              }
            }
          ]
        }
      ]
    },
    {
      "name": "3. Admin Flow",
      "description": "Admin panel: login → dashboard → manage users, requests, ebooks, subscriptions, CMS.",
      "item": [
        {
          "name": "3.1 Auth",
          "item": [
            {
              "name": "Login (Admin)",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "if (pm.response.code === 200 || pm.response.code === 201) {",
                      "  const json = pm.response.json();",
                      "  if (json.accessToken) {",
                      "    pm.collectionVariables.set('adminToken', json.accessToken);",
                      "    pm.collectionVariables.set('accessToken', json.accessToken);",
                      "  }",
                      "}"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "auth": { "type": "noauth" },
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"email\": \"admin@storysign.com\",\n  \"password\": \"Admin@12345\"\n}"
                },
                "url": "{{baseUrl}}/auth/login",
                "description": "Default seeded admin. Run: npm run seed:admin"
              }
            },
            {
              "name": "Use Admin Token",
              "event": [
                {
                  "listen": "prerequest",
                  "script": {
                    "exec": ["pm.collectionVariables.set('accessToken', pm.collectionVariables.get('adminToken'));"],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": { "method": "GET", "header": [], "url": "{{baseUrl}}/admin/profile" }
            },
            {
              "name": "Forgot Password (Admin)",
              "request": {
                "auth": { "type": "noauth" },
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": { "mode": "raw", "raw": "{\n  \"email\": \"admin@storysign.com\"\n}" },
                "url": "{{baseUrl}}/auth/forgot-password"
              }
            }
          ]
        },
        {
          "name": "3.2 Dashboard",
          "item": [
            {
              "name": "Dashboard Stats",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/admin/dashboard/stats",
                "description": "totalRevenue, totalReaders, totalAuthors, newRequests — each with *ChangePercent vs last month (+15 = 15% more, -10 = 10% less)."
              }
            },
            {
              "name": "Revenue Graph",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/admin/dashboard/revenue-graph?period=monthly",
                  "host": ["{{baseUrl}}"],
                  "path": ["admin", "dashboard", "revenue-graph"],
                  "query": [
                    { "key": "period", "value": "monthly", "description": "monthly | 6months | yearly" }
                  ]
                },
                "description": "Dual revenue graph data: reader autograph payments vs author subscriptions."
              }
            },
            {
              "name": "User Growth Graph",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/admin/dashboard/user-growth?period=6months",
                  "host": ["{{baseUrl}}"],
                  "path": ["admin", "dashboard", "user-growth"],
                  "query": [
                    { "key": "period", "value": "6months", "description": "monthly | 6months | yearly" }
                  ]
                },
                "description": "Reader vs author registrations over time."
              }
            },
            {
              "name": "Recent Requests",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/admin/dashboard/recent-requests",
                "description": "Latest 10 autograph requests."
              }
            }
          ]
        },
        {
          "name": "3.3 Reader Management",
          "item": [
            {
              "name": "Reader Stats",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/admin/readers/stats",
                "description": "totalReaders, activeReaders, inactiveReaders, suspendedReaders — each with *ChangePercent vs last month."
              }
            },
            {
              "name": "List Readers",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/admin/readers?page=1&limit=10&status=&search=",
                  "host": ["{{baseUrl}}"],
                  "path": ["admin", "readers"],
                  "query": [
                    { "key": "page", "value": "1" },
                    { "key": "limit", "value": "10" },
                    { "key": "status", "value": "", "description": "active | inactive | suspended" },
                    { "key": "search", "value": "", "description": "Search name or email" }
                  ]
                }
              }
            },
            {
              "name": "Reader Details",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "if (pm.response.code === 200) {",
                      "  const json = pm.response.json();",
                      "  if (json.user?._id) pm.collectionVariables.set('readerId', json.user._id);",
                      "}"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/admin/readers/{{readerId}}",
                "description": "Full reader info + library listing (signed & unsigned)."
              }
            },
            {
              "name": "Activate Reader",
              "request": {
                "method": "PATCH",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": { "mode": "raw", "raw": "{\n  \"status\": \"active\"\n}" },
                "url": "{{baseUrl}}/admin/readers/{{readerId}}/status"
              }
            },
            {
              "name": "Deactivate Reader",
              "request": {
                "method": "PATCH",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"status\": \"inactive\",\n  \"statusReason\": \"Account deactivated due to policy violation.\"\n}"
                },
                "url": "{{baseUrl}}/admin/readers/{{readerId}}/status",
                "description": "User sees statusReason on next login attempt."
              }
            },
            {
              "name": "Suspend Reader",
              "request": {
                "method": "PATCH",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"status\": \"suspended\",\n  \"statusReason\": \"Suspended pending investigation.\"\n}"
                },
                "url": "{{baseUrl}}/admin/readers/{{readerId}}/status"
              }
            }
          ]
        },
        {
          "name": "3.4 Author Management",
          "item": [
            {
              "name": "Author Stats",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/admin/authors/stats",
                "description": "totalAuthors, activeAuthors, inactiveAuthors, suspendedAuthors — each with *ChangePercent vs last month."
              }
            },
            {
              "name": "List Authors",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/admin/authors?page=1&limit=10&status=&search=",
                  "host": ["{{baseUrl}}"],
                  "path": ["admin", "authors"],
                  "query": [
                    { "key": "page", "value": "1" },
                    { "key": "limit", "value": "10" },
                    { "key": "status", "value": "" },
                    { "key": "search", "value": "" }
                  ]
                }
              }
            },
            {
              "name": "Author Details",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "if (pm.response.code === 200) {",
                      "  const json = pm.response.json();",
                      "  if (json.user?.id) pm.collectionVariables.set('authorId', json.user.id);",
                      "}"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/admin/authors/{{authorId}}?page=1&limit=10",
                  "host": ["{{baseUrl}}"],
                  "path": ["admin", "authors", "{{authorId}}"],
                  "query": [
                    { "key": "page", "value": "1" },
                    { "key": "limit", "value": "10" }
                  ]
                },
                "description": "Author profile + signing requests list (reader info, book, status)."
              }
            },
            {
              "name": "Activate Author",
              "request": {
                "method": "PATCH",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": { "mode": "raw", "raw": "{\n  \"status\": \"active\"\n}" },
                "url": "{{baseUrl}}/admin/authors/{{authorId}}/status"
              }
            },
            {
              "name": "Deactivate Author",
              "request": {
                "method": "PATCH",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"status\": \"inactive\",\n  \"statusReason\": \"Account deactivated.\"\n}"
                },
                "url": "{{baseUrl}}/admin/authors/{{authorId}}/status"
              }
            },
            {
              "name": "Suspend Author",
              "request": {
                "method": "PATCH",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"status\": \"suspended\",\n  \"statusReason\": \"Suspended.\"\n}"
                },
                "url": "{{baseUrl}}/admin/authors/{{authorId}}/status"
              }
            }
          ]
        },
        {
          "name": "3.5 Autograph Requests",
          "item": [
            {
              "name": "Request Stats",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/admin/autograph-requests/stats",
                "description": "totalRequests, inProgressRequests, rejectedRequests, completedRequests — each with *ChangePercent vs last month."
              }
            },
            {
              "name": "List All Requests",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/admin/autograph-requests?page=1&limit=10&status=&search=",
                  "host": ["{{baseUrl}}"],
                  "path": ["admin", "autograph-requests"],
                  "query": [
                    { "key": "page", "value": "1" },
                    { "key": "limit", "value": "10" },
                    { "key": "status", "value": "", "description": "submitted | in_progress | delivered | rejected" },
                    { "key": "search", "value": "", "description": "Search by book title" }
                  ]
                }
              }
            },
            {
              "name": "Request Details",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/admin/autograph-requests/{{autographRequestId}}",
                "description": "Complete reader, author, and book information."
              }
            }
          ]
        },
        {
          "name": "3.6 Ebook Management",
          "item": [
            {
              "name": "Ebook Stats",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/admin/ebooks/stats",
                "description": "totalBooks, signedBooks, unsignedBooks — each with *ChangePercent vs last month."
              }
            },
            {
              "name": "List Ebooks",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/admin/ebooks?page=1&limit=10&status=all&search=",
                  "host": ["{{baseUrl}}"],
                  "path": ["admin", "ebooks"],
                  "query": [
                    { "key": "page", "value": "1" },
                    { "key": "limit", "value": "10" },
                    { "key": "status", "value": "all", "description": "all | signed | unsigned" },
                    { "key": "search", "value": "" }
                  ]
                }
              }
            },
            {
              "name": "Ebook Details",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/admin/ebooks/{{bookId}}",
                "description": "Book + reader details. If signed: author info, messages, request details."
              }
            }
          ]
        },
        {
          "name": "3.7 Subscription Management",
          "item": [
            {
              "name": "List Subscription Plans",
              "request": { "method": "GET", "header": [], "url": "{{baseUrl}}/admin/subscription-plans" }
            },
            {
              "name": "Create Subscription Plan",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "if (pm.response.code === 200 || pm.response.code === 201) {",
                      "  const json = pm.response.json();",
                      "  if (json._id) pm.collectionVariables.set('planId', json._id);",
                      "}"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"Pro Monthly\",\n  \"planType\": \"monthly\",\n  \"price\": 29.99,\n  \"features\": [\"100 signings per month\", \"Priority support\", \"Analytics dashboard\"],\n  \"signQuota\": 100\n}"
                },
                "url": "{{baseUrl}}/admin/subscription-plans"
              }
            },
            {
              "name": "Update Subscription Plan",
              "request": {
                "method": "PATCH",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"Pro Monthly Updated\",\n  \"price\": 34.99,\n  \"signQuota\": 120,\n  \"isActive\": true\n}"
                },
                "url": "{{baseUrl}}/admin/subscription-plans/{{planId}}"
              }
            },
            {
              "name": "List Subscribers",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/admin/subscribers?page=1&limit=10",
                  "host": ["{{baseUrl}}"],
                  "path": ["admin", "subscribers"],
                  "query": [
                    { "key": "page", "value": "1" },
                    { "key": "limit", "value": "10" }
                  ]
                },
                "description": "Author details, plan title, amount, start date, next billing date."
              }
            }
          ]
        },
        {
          "name": "3.8 Autograph Fee Management",
          "item": [
            {
              "name": "Set Autograph Fee",
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": { "mode": "raw", "raw": "{\n  \"amount\": 25.00\n}" },
                "url": "{{baseUrl}}/payments/admin/autograph-fee",
                "description": "Set current signing fee (USD). Required before readers can request autographs."
              }
            },
            {
              "name": "Autograph Fee History",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/payments/admin/autograph-fee/history",
                "description": "Historical fee changes: id, amount, date."
              }
            }
          ]
        },
        {
          "name": "3.9 Query Management",
          "item": [
            {
              "name": "Query Stats",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/admin/queries/stats",
                "description": "totalQueries, pendingQueries, resolvedQueries — each with *ChangePercent vs last month."
              }
            },
            {
              "name": "List Queries",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "if (pm.response.code === 200) {",
                      "  const json = pm.response.json();",
                      "  if (json.items?.[0]?._id) pm.collectionVariables.set('queryId', json.items[0]._id);",
                      "}"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/admin/queries?page=1&limit=10",
                  "host": ["{{baseUrl}}"],
                  "path": ["admin", "queries"],
                  "query": [
                    { "key": "page", "value": "1" },
                    { "key": "limit", "value": "10" }
                  ]
                },
                "description": "Contact us submissions with user role."
              }
            },
            {
              "name": "Resolve Query",
              "request": {
                "method": "PATCH",
                "header": [],
                "url": "{{baseUrl}}/admin/queries/{{queryId}}/resolve"
              }
            }
          ]
        },
        {
          "name": "3.10 Reports & Analytics",
          "item": [
            {
              "name": "Top Authors By Requests",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/admin/reports/top-authors",
                "description": "Top 3 authors with most sign requests."
              }
            },
            {
              "name": "Autograph Requests Graph",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/admin/reports/autograph-requests-graph?period=monthly",
                  "host": ["{{baseUrl}}"],
                  "path": ["admin", "reports", "autograph-requests-graph"],
                  "query": [
                    { "key": "period", "value": "monthly", "description": "monthly | 6months | yearly" }
                  ]
                },
                "description": "Requests grouped by month and status."
              }
            }
          ]
        },
        {
          "name": "3.11 Push Notifications",
          "item": [
            {
              "name": "Push History",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/admin/push-notifications?page=1&limit=20",
                  "host": ["{{baseUrl}}"],
                  "path": ["admin", "push-notifications"],
                  "query": [
                    { "key": "page", "value": "1" },
                    { "key": "limit", "value": "20" }
                  ]
                }
              }
            },
            {
              "name": "Send Push Notification",
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"recipient\": \"all\",\n  \"title\": \"New Feature!\",\n  \"message\": \"Check out our latest update in the app.\"\n}"
                },
                "url": "{{baseUrl}}/admin/push-notifications",
                "description": "recipient: all | readers | authors. Sends in-app + FCM push."
              }
            },
            {
              "name": "Admin Notifications",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/admin/notifications?page=1&limit=20",
                  "host": ["{{baseUrl}}"],
                  "path": ["admin", "notifications"],
                  "query": [
                    { "key": "page", "value": "1" },
                    { "key": "limit", "value": "20" }
                  ]
                }
              }
            }
          ]
        },
        {
          "name": "3.12 CMS - Privacy Policy",
          "item": [
            {
              "name": "List Privacy Policies",
              "request": { "method": "GET", "header": [], "url": "{{baseUrl}}/admin/privacy-policies" }
            },
            {
              "name": "Upsert Privacy Policy (Reader)",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "if (pm.response.code === 200 || pm.response.code === 201) {",
                      "  const json = pm.response.json();",
                      "  if (json._id) pm.collectionVariables.set('privacyPolicyId', json._id);",
                      "}"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"audience\": \"reader\",\n  \"content\": \"<h1>Privacy Policy for Readers</h1><p>Your data is protected...</p>\"\n}"
                },
                "url": "{{baseUrl}}/admin/privacy-policies"
              }
            },
            {
              "name": "Upsert Privacy Policy (Author)",
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"audience\": \"author\",\n  \"content\": \"<h1>Privacy Policy for Authors</h1><p>Your data is protected...</p>\"\n}"
                },
                "url": "{{baseUrl}}/admin/privacy-policies"
              }
            },
            {
              "name": "Delete Privacy Policy",
              "request": {
                "method": "DELETE",
                "header": [],
                "url": "{{baseUrl}}/admin/privacy-policies/{{privacyPolicyId}}"
              }
            }
          ]
        },
        {
          "name": "3.13 CMS - FAQs",
          "item": [
            {
              "name": "List FAQs",
              "request": { "method": "GET", "header": [], "url": "{{baseUrl}}/admin/faqs" }
            },
            {
              "name": "Create FAQ",
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "if (pm.response.code === 200 || pm.response.code === 201) {",
                      "  const json = pm.response.json();",
                      "  if (json._id) pm.collectionVariables.set('faqId', json._id);",
                      "}"
                    ],
                    "type": "text/javascript"
                  }
                }
              ],
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"question\": \"How do I request an autograph?\",\n  \"answer\": \"Browse authors, upload your book, and submit a signing request.\",\n  \"sortOrder\": 1\n}"
                },
                "url": "{{baseUrl}}/admin/faqs"
              }
            },
            {
              "name": "Update FAQ",
              "request": {
                "method": "PATCH",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"question\": \"How do I request an autograph?\",\n  \"answer\": \"Updated answer text.\"\n}"
                },
                "url": "{{baseUrl}}/admin/faqs/{{faqId}}"
              }
            },
            {
              "name": "Delete FAQ",
              "request": {
                "method": "DELETE",
                "header": [],
                "url": "{{baseUrl}}/admin/faqs/{{faqId}}"
              }
            }
          ]
        },
        {
          "name": "3.14 Platform Settings",
          "item": [
            {
              "name": "Get Settings",
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{baseUrl}}/admin/settings",
                "description": "platformName, email, phone, supportUrl."
              }
            },
            {
              "name": "Update Settings",
              "request": {
                "method": "PATCH",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"platformName\": \"StorySign\",\n  \"email\": \"support@storysign.com\",\n  \"phone\": \"+1-800-555-0100\",\n  \"supportUrl\": \"https://storysign.com/support\"\n}"
                },
                "url": "{{baseUrl}}/admin/settings",
                "description": "Shown in reader/author Help & Support screens."
              }
            }
          ]
        },
        {
          "name": "3.15 Admin Profile",
          "item": [
            {
              "name": "Get Profile",
              "request": { "method": "GET", "header": [], "url": "{{baseUrl}}/admin/profile" }
            },
            {
              "name": "Edit Profile",
              "request": {
                "method": "PATCH",
                "header": [],
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    { "key": "fullName", "value": "StorySign Admin", "type": "text" },
                    { "key": "profilePicture", "type": "file", "src": [] }
                  ]
                },
                "url": "{{baseUrl}}/admin/profile"
              }
            },
            {
              "name": "Change Password",
              "request": {
                "method": "POST",
                "header": [{ "key": "Content-Type", "value": "application/json" }],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"currentPassword\": \"Admin@12345\",\n  \"newPassword\": \"NewAdmin@123\",\n  \"confirmPassword\": \"NewAdmin@123\"\n}"
                },
                "url": "{{baseUrl}}/auth/change-password"
              }
            }
          ]
        }
      ]
    }
  ]
}
