{
  "info": {
    "_postman_id": "cfd1a286-2dc1-4d62-97f7-2b8863edaa2d",
    "name": "CalmBoard Integrations API",
    "description": "API-key management, per-user OAuth redirect settings, versioned integration API examples, and MCP server examples for CalmBoard. Use a session token for settings calls and an integration API key or OAuth bearer token for /api/v1 and /mcp calls.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "event": [
    {
      "listen": "test",
      "script": {
        "type": "text/javascript",
        "exec": [
          "pm.test(\"Response does not return a server error\", function () {",
          "  pm.expect(pm.response.code).to.be.below(500);",
          "});",
          "",
          "const contentType = pm.response.headers.get(\"Content-Type\") || \"\";",
          "if (contentType.includes(\"application/json\")) {",
          "  pm.test(\"Response body is valid JSON\", function () {",
          "    pm.response.json();",
          "  });",
          "}"
        ]
      }
    }
  ],
  "variable": [
    { "key": "baseUrl", "value": "https://calmboard.ai" },
    { "key": "sessionToken", "value": "" },
    { "key": "loginEmail", "value": "user@example.com" },
    { "key": "loginPassword", "value": "Password1!" },
    { "key": "recaptchaToken", "value": "" },
    { "key": "apiKey", "value": "cbk_your_api_key" },
    { "key": "oauthAccessToken", "value": "cbo_your_oauth_access_token" },
    { "key": "oauthClientId", "value": "cb_oauth_your_client_id" },
    { "key": "oauthRedirectUri", "value": "http://localhost:6274/oauth/callback" },
    { "key": "oauthResource", "value": "https://calmboard.ai/api/v1" },
    { "key": "mcpOAuthResource", "value": "https://calmboard.ai/mcp" },
    { "key": "oauthCode", "value": "" },
    { "key": "oauthCodeChallenge", "value": "BASE64URL_SHA256_VERIFIER" },
    { "key": "oauthCodeVerifier", "value": "replace_with_a_43_to_128_character_pkce_verifier_value" },
    { "key": "keyId", "value": "key_123" },
    { "key": "projectId", "value": "prj_123" },
    { "key": "boardId", "value": "brd_123" },
    { "key": "columnId", "value": "col_backlog" },
    { "key": "targetColumnId", "value": "col_review" },
    { "key": "invalidColumnId", "value": "col_does_not_exist" },
    { "key": "taskId", "value": "tsk_123" },
    { "key": "sprintId", "value": "spr_123" }
  ],
  "item": [
    {
      "name": "Session auth helper",
      "description": "Use this folder when you need a CalmBoard session token for session-authenticated requests. In production, reCAPTCHA may block direct Postman login; in that case sign in through the browser and copy localStorage.calmboard_token into the sessionToken collection variable.",
      "item": [
        {
          "name": "Sign in and set sessionToken",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"{{loginEmail}}\",\n  \"password\": \"{{loginPassword}}\",\n  \"recaptcha_token\": \"{{recaptchaToken}}\"\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/api/auth/login",
              "host": ["{{baseUrl}}"],
              "path": ["api", "auth", "login"]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Sign in returns a CalmBoard session token\", function () {",
                  "  pm.response.to.have.status(200);",
                  "  const json = pm.response.json();",
                  "  pm.expect(json.token).to.be.a(\"string\").and.not.empty;",
                  "  pm.collectionVariables.set(\"sessionToken\", json.token);",
                  "});"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "API key management (session auth)",
      "item": [
        {
          "name": "List API keys",
          "request": {
            "method": "GET",
            "header": [
              { "key": "Authorization", "value": "Bearer {{sessionToken}}" }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/integrations/api-keys",
              "host": ["{{baseUrl}}"],
              "path": ["api", "integrations", "api-keys"]
            }
          }
        },
        {
          "name": "Create API key",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Authorization", "value": "Bearer {{sessionToken}}" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Slack sync\"\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/api/integrations/api-keys",
              "host": ["{{baseUrl}}"],
              "path": ["api", "integrations", "api-keys"]
            }
          }
        },
        {
          "name": "Revoke API key",
          "request": {
            "method": "DELETE",
            "header": [
              { "key": "Authorization", "value": "Bearer {{sessionToken}}" }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/integrations/api-keys/{{keyId}}",
              "host": ["{{baseUrl}}"],
              "path": ["api", "integrations", "api-keys", "{{keyId}}"]
            }
          }
        }
      ]
    },
    {
      "name": "OAuth bearer token flow",
      "item": [
        {
          "name": "OAuth protected resource metadata",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/.well-known/oauth-protected-resource",
              "host": ["{{baseUrl}}"],
              "path": [".well-known", "oauth-protected-resource"]
            }
          }
        },
        {
          "name": "MCP OAuth protected resource metadata",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/.well-known/oauth-protected-resource/mcp",
              "host": ["{{baseUrl}}"],
              "path": [".well-known", "oauth-protected-resource", "mcp"]
            }
          }
        },
        {
          "name": "OAuth authorization server metadata",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/.well-known/oauth-authorization-server",
              "host": ["{{baseUrl}}"],
              "path": [".well-known", "oauth-authorization-server"]
            }
          }
        },
        {
          "name": "Register OAuth client dynamically",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"client_name\": \"Postman MCP client\",\n  \"redirect_uris\": [\n    \"{{oauthRedirectUri}}\"\n  ],\n  \"grant_types\": [\"authorization_code\"],\n  \"response_types\": [\"code\"],\n  \"token_endpoint_auth_method\": \"none\"\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/api/oauth/register",
              "host": ["{{baseUrl}}"],
              "path": ["api", "oauth", "register"]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Dynamic client registration returns a client ID\", function () {",
                  "  pm.response.to.have.status(201);",
                  "  const json = pm.response.json();",
                  "  pm.expect(json.client_id).to.be.a(\"string\").and.not.empty;",
                  "  pm.collectionVariables.set(\"oauthClientId\", json.client_id);",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Save OAuth redirect URIs (session auth)",
          "request": {
            "method": "PUT",
            "header": [
              { "key": "Authorization", "value": "Bearer {{sessionToken}}" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"redirect_uris\": [\n    \"{{oauthRedirectUri}}\"\n  ]\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/api/integrations/oauth-settings",
              "host": ["{{baseUrl}}"],
              "path": ["api", "integrations", "oauth-settings"]
            }
          }
        },
        {
          "name": "Issue OAuth authorization code (session auth)",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const token = String(pm.collectionVariables.get(\"sessionToken\") || pm.variables.get(\"sessionToken\") || \"\").trim();",
                  "if (!token) {",
                  "  throw new Error(\"Set sessionToken before issuing an OAuth authorization code. Run 'Session auth helper / Sign in and set sessionToken', or copy localStorage.calmboard_token from a signed-in CalmBoard browser session into the sessionToken collection variable.\");",
                  "}"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"OAuth authorization code request returns redirect_to\", function () {",
                  "  pm.response.to.have.status(200);",
                  "  const json = pm.response.json();",
                  "  pm.expect(json.redirect_to).to.be.a(\"string\").and.not.empty;",
                  "  const redirectUrl = new URL(json.redirect_to);",
                  "  const code = redirectUrl.searchParams.get(\"code\");",
                  "  pm.expect(code).to.be.a(\"string\").and.not.empty;",
                  "  pm.collectionVariables.set(\"oauthCode\", code);",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [
              { "key": "Authorization", "value": "Bearer {{sessionToken}}" }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/oauth/authorize?response_type=code&client_id={{oauthClientId}}&redirect_uri={{oauthRedirectUri}}&scope=integrations%3Aread%20integrations%3Awrite&state=postman-state&code_challenge={{oauthCodeChallenge}}&code_challenge_method=S256&resource={{oauthResource}}",
              "host": ["{{baseUrl}}"],
              "path": ["api", "oauth", "authorize"],
              "query": [
                { "key": "response_type", "value": "code" },
                { "key": "client_id", "value": "{{oauthClientId}}" },
                { "key": "redirect_uri", "value": "{{oauthRedirectUri}}" },
                { "key": "scope", "value": "integrations:read integrations:write" },
                { "key": "state", "value": "postman-state" },
                { "key": "code_challenge", "value": "{{oauthCodeChallenge}}" },
                { "key": "code_challenge_method", "value": "S256" },
                { "key": "resource", "value": "{{oauthResource}}" }
              ]
            }
          }
        },
        {
          "name": "Exchange OAuth authorization code for bearer token",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/x-www-form-urlencoded" }
            ],
            "body": {
              "mode": "urlencoded",
              "urlencoded": [
                { "key": "grant_type", "value": "authorization_code", "type": "text" },
                { "key": "client_id", "value": "{{oauthClientId}}", "type": "text" },
                { "key": "redirect_uri", "value": "{{oauthRedirectUri}}", "type": "text" },
                { "key": "code", "value": "{{oauthCode}}", "type": "text" },
                { "key": "code_verifier", "value": "{{oauthCodeVerifier}}", "type": "text" },
                { "key": "resource", "value": "{{oauthResource}}", "type": "text" }
              ]
            },
            "url": {
              "raw": "{{baseUrl}}/api/oauth/token",
              "host": ["{{baseUrl}}"],
              "path": ["api", "oauth", "token"]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"OAuth token exchange returns a bearer token\", function () {",
                  "  pm.response.to.have.status(200);",
                  "  const json = pm.response.json();",
                  "  pm.expect(json.access_token).to.be.a(\"string\").and.not.empty;",
                  "  pm.expect(json.token_type).to.eql(\"Bearer\");",
                  "  pm.collectionVariables.set(\"oauthAccessToken\", json.access_token);",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "List projects with OAuth bearer token",
          "request": {
            "method": "GET",
            "header": [
              { "key": "Authorization", "value": "Bearer {{oauthAccessToken}}" }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/projects",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "projects"]
            }
          }
        }
      ]
    },
    {
      "name": "MCP server",
      "description": "Paid-plan MCP examples. Use either Authorization: Bearer {{oauthAccessToken}} or Authorization: Bearer {{apiKey}}.",
      "item": [
        {
          "name": "MCP server info",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/mcp",
              "host": ["{{baseUrl}}"],
              "path": ["mcp"]
            }
          }
        },
        {
          "name": "MCP initialize",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Authorization", "value": "Bearer {{oauthAccessToken}}" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"jsonrpc\": \"2.0\",\n  \"id\": 1,\n  \"method\": \"initialize\",\n  \"params\": {\n    \"protocolVersion\": \"2025-06-18\",\n    \"capabilities\": {},\n    \"clientInfo\": {\n      \"name\": \"Postman MCP test\",\n      \"version\": \"1.0.0\"\n    }\n  }\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/mcp",
              "host": ["{{baseUrl}}"],
              "path": ["mcp"]
            }
          }
        },
        {
          "name": "MCP list tools",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Authorization", "value": "Bearer {{oauthAccessToken}}" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"jsonrpc\": \"2.0\",\n  \"id\": 2,\n  \"method\": \"tools/list\"\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/mcp",
              "host": ["{{baseUrl}}"],
              "path": ["mcp"]
            }
          }
        },
        {
          "name": "MCP call list tasks",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Authorization", "value": "Bearer {{oauthAccessToken}}" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"jsonrpc\": \"2.0\",\n  \"id\": 3,\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"calmboard.list_tasks\",\n    \"arguments\": {\n      \"project_id\": \"{{projectId}}\",\n      \"board_id\": \"{{boardId}}\",\n      \"limit\": 20\n    }\n  }\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/mcp",
              "host": ["{{baseUrl}}"],
              "path": ["mcp"]
            }
          }
        },
        {
          "name": "MCP list tools with API key",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Authorization", "value": "Bearer {{apiKey}}" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"jsonrpc\": \"2.0\",\n  \"id\": 4,\n  \"method\": \"tools/list\"\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/mcp",
              "host": ["{{baseUrl}}"],
              "path": ["mcp"]
            }
          }
        }
      ]
    },
    {
      "name": "Versioned API (API key auth)",
      "item": [
        {
          "name": "List projects",
          "request": {
            "method": "GET",
            "header": [
              { "key": "Authorization", "value": "Bearer {{apiKey}}" }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/projects",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "projects"]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"List projects returns 200\", function () {",
                  "  pm.response.to.have.status(200);",
                  "});",
                  "pm.test(\"Projects payload is an array\", function () {",
                  "  const json = pm.response.json();",
                  "  pm.expect(json.projects).to.be.an(\"array\");",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "List project boards",
          "request": {
            "method": "GET",
            "header": [
              { "key": "Authorization", "value": "Bearer {{apiKey}}" }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/projects/{{projectId}}/boards",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "projects", "{{projectId}}", "boards"]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"List boards returns 200\", function () {",
                  "  pm.response.to.have.status(200);",
                  "});",
                  "pm.test(\"Boards payload is an array\", function () {",
                  "  const json = pm.response.json();",
                  "  pm.expect(json.boards).to.be.an(\"array\");",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "List board columns",
          "request": {
            "method": "GET",
            "header": [
              { "key": "Authorization", "value": "Bearer {{apiKey}}" }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/projects/{{projectId}}/boards/{{boardId}}/columns",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "projects", "{{projectId}}", "boards", "{{boardId}}", "columns"]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"List columns returns 200\", function () {",
                  "  pm.response.to.have.status(200);",
                  "});",
                  "pm.test(\"Columns payload is an array\", function () {",
                  "  const json = pm.response.json();",
                  "  pm.expect(json.columns).to.be.an(\"array\");",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "List tasks",
          "request": {
            "method": "GET",
            "header": [
              { "key": "Authorization", "value": "Bearer {{apiKey}}" }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/projects/{{projectId}}/tasks?board_id={{boardId}}",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "projects", "{{projectId}}", "tasks"],
              "query": [
                { "key": "board_id", "value": "{{boardId}}" }
              ]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"List tasks returns 200\", function () {",
                  "  pm.response.to.have.status(200);",
                  "});",
                  "pm.test(\"Tasks payload is an array\", function () {",
                  "  const json = pm.response.json();",
                  "  pm.expect(json.tasks).to.be.an(\"array\");",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Create task",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Authorization", "value": "Bearer {{apiKey}}" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"board_id\": \"{{boardId}}\",\n  \"column_id\": \"{{columnId}}\",\n  \"title\": \"Sync Slack release alerts\",\n  \"description\": \"Post CalmBoard task updates to Slack.\",\n  \"position\": 1,\n  \"tags\": [\"integration\"]\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/api/v1/projects/{{projectId}}/tasks",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "projects", "{{projectId}}", "tasks"]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Create task returns 201\", function () {",
                  "  pm.response.to.have.status(201);",
                  "});",
                  "pm.test(\"Create task returns a task id\", function () {",
                  "  const json = pm.response.json();",
                  "  pm.expect(json.task_id).to.be.a(\"string\").and.not.empty;",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Update task",
          "request": {
            "method": "PATCH",
            "header": [
              { "key": "Authorization", "value": "Bearer {{apiKey}}" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"title\": \"Sync Slack deployment alerts\",\n  \"description\": \"Post CalmBoard deployment task updates to Slack.\",\n  \"blocked\": false,\n  \"complexity_points\": 5\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/api/v1/projects/{{projectId}}/tasks/{{taskId}}",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "projects", "{{projectId}}", "tasks", "{{taskId}}"]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Update task returns 200\", function () {",
                  "  pm.response.to.have.status(200);",
                  "});",
                  "pm.test(\"Update task returns the task id\", function () {",
                  "  const json = pm.response.json();",
                  "  pm.expect(json.task_id).to.be.a(\"string\").and.not.empty;",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Add task comment",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Authorization", "value": "Bearer {{apiKey}}" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"body\": \"Slack webhook is configured and ready for review.\"\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/api/v1/projects/{{projectId}}/tasks/{{taskId}}/comments",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "projects", "{{projectId}}", "tasks", "{{taskId}}", "comments"]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Add comment returns 201\", function () {",
                  "  pm.response.to.have.status(201);",
                  "});",
                  "pm.test(\"Add comment returns a comment id\", function () {",
                  "  const json = pm.response.json();",
                  "  pm.expect(json.comment_id).to.be.a(\"string\").and.not.empty;",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Move task",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Authorization", "value": "Bearer {{apiKey}}" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"to_column_id\": \"{{targetColumnId}}\",\n  \"position\": 2\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/api/v1/projects/{{projectId}}/tasks/{{taskId}}/move",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "projects", "{{projectId}}", "tasks", "{{taskId}}", "move"]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Move task returns 200\", function () {",
                  "  pm.response.to.have.status(200);",
                  "});",
                  "pm.test(\"Move task returns the target column\", function () {",
                  "  const json = pm.response.json();",
                  "  pm.expect(json.to_column_id).to.eql(pm.variables.get(\"targetColumnId\"));",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Move task with invalid column (should fail)",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Authorization", "value": "Bearer {{apiKey}}" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"to_column_id\": \"{{invalidColumnId}}\",\n  \"position\": 1\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/api/v1/projects/{{projectId}}/tasks/{{taskId}}/move",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "projects", "{{projectId}}", "tasks", "{{taskId}}", "move"]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Move task rejects a non-existent column\", function () {",
                  "  pm.response.to.have.status(400);",
                  "});",
                  "pm.test(\"Invalid column response explains the validation failure\", function () {",
                  "  const json = pm.response.json();",
                  "  pm.expect(json.error).to.eql(\"invalid to_column_id\");",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "List sprints",
          "request": {
            "method": "GET",
            "header": [
              { "key": "Authorization", "value": "Bearer {{apiKey}}" }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/projects/{{projectId}}/sprints?board_id={{boardId}}",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "projects", "{{projectId}}", "sprints"],
              "query": [
                { "key": "board_id", "value": "{{boardId}}" }
              ]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"List sprints returns 200\", function () {",
                  "  pm.response.to.have.status(200);",
                  "});",
                  "pm.test(\"Sprints payload is an array\", function () {",
                  "  const json = pm.response.json();",
                  "  pm.expect(json.sprints).to.be.an(\"array\");",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Create sprint",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Authorization", "value": "Bearer {{apiKey}}" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"board_id\": \"{{boardId}}\",\n  \"title\": \"Sprint 9\",\n  \"goal\": \"Finish release automation\",\n  \"start_date\": \"2026-04-20\",\n  \"end_date\": \"2026-05-01\",\n  \"status\": \"planned\"\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/api/v1/projects/{{projectId}}/sprints",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "projects", "{{projectId}}", "sprints"]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Create sprint returns 201\", function () {",
                  "  pm.response.to.have.status(201);",
                  "});",
                  "pm.test(\"Create sprint returns a sprint id\", function () {",
                  "  const json = pm.response.json();",
                  "  pm.expect(json.sprint_id).to.be.a(\"string\").and.not.empty;",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Update sprint",
          "request": {
            "method": "PATCH",
            "header": [
              { "key": "Authorization", "value": "Bearer {{apiKey}}" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"title\": \"Sprint 9 - Release automation\",\n  \"status\": \"active\"\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/api/v1/projects/{{projectId}}/sprints/{{sprintId}}",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "projects", "{{projectId}}", "sprints", "{{sprintId}}"]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Update sprint returns 200\", function () {",
                  "  pm.response.to.have.status(200);",
                  "});",
                  "pm.test(\"Update sprint returns the sprint id\", function () {",
                  "  const json = pm.response.json();",
                  "  pm.expect(json.sprint_id).to.be.a(\"string\").and.not.empty;",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "List insights",
          "request": {
            "method": "GET",
            "header": [
              { "key": "Authorization", "value": "Bearer {{apiKey}}" }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/projects/{{projectId}}/insights?board_id={{boardId}}",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "projects", "{{projectId}}", "insights"],
              "query": [
                { "key": "board_id", "value": "{{boardId}}" }
              ]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"List insights returns 200\", function () {",
                  "  pm.response.to.have.status(200);",
                  "});",
                  "pm.test(\"Insights payload is an array\", function () {",
                  "  const json = pm.response.json();",
                  "  pm.expect(json.insights).to.be.an(\"array\");",
                  "});"
                ]
              }
            }
          ]
        }
      ]
    }
  ]
}
