{
  "openapi": "3.0.3",
  "info": {
    "title": "RedRover integration API",
    "version": "1.0.0",
    "description": "Effective access = key grants intersect current account, membership and domain permissions. API keys cannot manage users, approvals, system configuration, financial orders or other keys. Browser clients may use the existing same-origin session and X-CSRF-Token for POST. Never put keys in browser bundles. Do not automatically retry mutations; reconcile after an uncertain response."
  },
  "servers": [
    {
      "url": "/redrover/api/v1"
    }
  ],
  "security": [
    {
      "ApiKey": []
    },
    {
      "ApiKeyAuthorization": []
    },
    {
      "SessionCookie": []
    }
  ],
  "paths": {
    "/capabilities": {
      "get": {
        "operationId": "capabilities",
        "summary": "Authentication mode and resource grants",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Key grant or current user/workspace permission denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Version conflict: refresh before saving",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; honor Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/workspaces": {
      "get": {
        "operationId": "workspaces",
        "summary": "Accessible active workspaces; workspaces:read",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "workspaces": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Workspace"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Key grant or current user/workspace permission denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Version conflict: refresh before saving",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; honor Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/items": {
      "get": {
        "operationId": "items",
        "summary": "List readable work; requires type resource and linked ancestor read grants",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Work"
                      }
                    },
                    "hasMore": {
                      "type": "boolean"
                    },
                    "nextAfter": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Key grant or current user/workspace permission denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Version conflict: refresh before saving",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; honor Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "workspaceId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": ""
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "task (default), requirement, goal, release, milestone"
          },
          {
            "name": "after",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Exclusive item ID cursor; default 0"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "1\u2013100; default 50"
          }
        ]
      }
    },
    "/item": {
      "get": {
        "operationId": "item",
        "summary": "Read one item and permitted fields",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Work"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Key grant or current user/workspace permission denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Version conflict: refresh before saving",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; honor Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "workspaceId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": ""
          },
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": ""
          }
        ]
      }
    },
    "/items/save": {
      "post": {
        "operationId": "saveWork",
        "summary": "Create or update work; requires resource:write and current domain permission",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Work"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Key grant or current user/workspace permission denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Version conflict: refresh before saving",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; honor Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "workspaceId",
                  "record"
                ],
                "properties": {
                  "workspaceId": {
                    "type": "integer"
                  },
                  "record": {
                    "$ref": "#/components/schemas/Work"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyAuthorization": []
          },
          {
            "SessionCookie": [],
            "SessionCsrf": []
          }
        ]
      }
    },
    "/comments": {
      "get": {
        "operationId": "comments",
        "summary": "Latest 100 comments, newest first; comments:read and item/ancestor read",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "comments": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Comment"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Key grant or current user/workspace permission denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Version conflict: refresh before saving",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; honor Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "workspaceId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": ""
          },
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": ""
          }
        ]
      },
      "post": {
        "operationId": "comment",
        "summary": "Add a comment; comments:write and current collaboration permission",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Comment"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Key grant or current user/workspace permission denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Version conflict: refresh before saving",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; honor Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "workspaceId",
                  "id",
                  "body"
                ],
                "properties": {
                  "workspaceId": {
                    "type": "integer"
                  },
                  "id": {
                    "type": "integer"
                  },
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 12000
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyAuthorization": []
          },
          {
            "SessionCookie": [],
            "SessionCsrf": []
          }
        ]
      }
    },
    "/capacity": {
      "get": {
        "operationId": "capacity",
        "summary": "Read load and forecasts; workspaces, capacity, tasks, requirements, releases, milestones read grants plus current time oversight",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Capacity"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Key grant or current user/workspace permission denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Version conflict: refresh before saving",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; honor Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "workspaceId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "0 means all visible workspaces"
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "ISO date, normalized to Monday; eight weeks"
          }
        ]
      }
    },
    "/options": {
      "get": {
        "operationId": "options",
        "summary": "Workspace workflow statuses, priorities and eligible assignees; workspaces and at least one work type read grant",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Permission-scoped options",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Key grant or current user/workspace permission denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Version conflict: refresh before saving",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; honor Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      },
      "ApiKeyAuthorization": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "ApiKey <secret>. Use exactly one authentication header."
      },
      "SessionCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "JSESSIONID",
        "description": "Existing same-origin RedRover login session."
      },
      "SessionCsrf": {
        "type": "apiKey",
        "in": "header",
        "name": "X-CSRF-Token",
        "description": "Current CSRF value returned by capabilities for session-authenticated writes."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "Workspace": {
        "type": "object",
        "required": [
          "id",
          "name",
          "uuid"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "name": {
            "type": "string"
          },
          "uuid": {
            "type": "string"
          },
          "sample": {
            "type": "boolean"
          }
        }
      },
      "WorkFields": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "statusKey": {
            "type": "string",
            "nullable": true
          },
          "priorityKey": {
            "type": "string",
            "nullable": true
          },
          "assigneeName": {
            "type": "string",
            "nullable": true
          },
          "blockedReason": {
            "type": "string",
            "nullable": true
          },
          "dueDate": {
            "type": "string",
            "nullable": true
          },
          "startDate": {
            "type": "string",
            "nullable": true
          },
          "targetDate": {
            "type": "string",
            "nullable": true
          },
          "actualDate": {
            "type": "string",
            "nullable": true
          },
          "versionLabel": {
            "type": "string",
            "nullable": true
          },
          "acceptance": {
            "type": "string",
            "nullable": true
          },
          "reachPeriod": {
            "type": "string",
            "nullable": true
          },
          "unit": {
            "type": "string",
            "nullable": true
          },
          "level": {
            "type": "string",
            "nullable": true
          },
          "estimatedHours": {
            "type": "number",
            "nullable": true
          },
          "progressPercent": {
            "type": "number",
            "nullable": true
          },
          "reach": {
            "type": "number",
            "nullable": true
          },
          "impact": {
            "type": "number",
            "nullable": true
          },
          "confidence": {
            "type": "number",
            "nullable": true
          },
          "effort": {
            "type": "number",
            "nullable": true
          },
          "target": {
            "type": "number",
            "nullable": true
          },
          "current": {
            "type": "number",
            "nullable": true
          },
          "assigneeId": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "parentId": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "parentItemId": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "requirementId": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "releaseId": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "goalId": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          }
        }
      },
      "Work": {
        "type": "object",
        "required": [
          "type",
          "title",
          "description",
          "status",
          "fields"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Omit for creation; required for updates."
          },
          "type": {
            "type": "string",
            "enum": [
              "task",
              "requirement",
              "goal",
              "release",
              "milestone"
            ]
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "Canonical domain status. Approval transitions use the web approval workflow."
          },
          "version": {
            "type": "integer",
            "description": "Current item version required for update; 409 means reload and reconcile."
          },
          "ownerId": {
            "type": "integer",
            "format": "int64"
          },
          "fields": {
            "$ref": "#/components/schemas/WorkFields"
          }
        }
      },
      "Comment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "body": {
            "type": "string"
          },
          "createdAt": {
            "type": "string"
          }
        }
      },
      "Capacity": {
        "type": "object",
        "description": "Permission-scoped scenario data. Dates may be null when estimates, assignments, or capacity are missing. UTC Monday\u2013Friday. Read-only API resource.",
        "properties": {
          "workspaceId": {
            "type": "integer"
          },
          "today": {
            "type": "string",
            "format": "date"
          },
          "from": {
            "type": "string",
            "format": "date"
          },
          "weeks": {
            "type": "integer"
          },
          "timezone": {
            "type": "string"
          },
          "canManage": {
            "type": "boolean"
          },
          "scopeNote": {
            "type": "string"
          },
          "projects": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProjectForecast"
            }
          },
          "people": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PersonCapacity"
            }
          }
        }
      },
      "ProjectForecast": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "targetDate": {
            "type": "string"
          },
          "forecastDate": {
            "type": "string",
            "nullable": true
          },
          "bufferedDate": {
            "type": "string",
            "nullable": true
          },
          "scopeHours": {
            "type": "number"
          },
          "remainingHours": {
            "type": "number"
          },
          "bufferedHours": {
            "type": "number"
          },
          "weightedProgress": {
            "type": "number",
            "nullable": true
          },
          "outlook": {
            "type": "string",
            "enum": [
              "no_scope",
              "needs_data",
              "needs_target",
              "overcommitted",
              "at_risk",
              "within_capacity"
            ]
          },
          "method": {
            "type": "string"
          },
          "dataIncomplete": {
            "type": "boolean"
          },
          "trend": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "work": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "PersonCapacity": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "weeklyHours": {
            "type": "number"
          },
          "confirmed": {
            "type": "boolean"
          },
          "weeks": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "week": {
                  "type": "string",
                  "format": "date"
                },
                "availableHours": {
                  "type": "number"
                },
                "allocatedHours": {
                  "type": "number"
                },
                "plannedHours": {
                  "type": "number"
                },
                "recordedHours": {
                  "type": "number"
                },
                "overextended": {
                  "type": "boolean"
                },
                "overHours": {
                  "type": "number"
                },
                "loadPercent": {
                  "type": "number",
                  "nullable": true
                }
              }
            }
          }
        }
      }
    }
  }
}
