{
  "openapi": "3.1.0",
  "info": {
    "title": "Pilla API",
    "version": "1.2.0",
    "description": "The Pilla API provides role-scoped access to users, teams, team membership, workflow instances, reports, webhooks, and API keys for Pilla, AI work management for deskless teams.\n\n## Authentication\n\nMost endpoints use Pilla API keys. Include the key in the `Authorization` header:\n\n```\nAuthorization: Bearer pk_live_...\n```\n\nPersonal API keys inherit the connected user's role. Staff can access their own or assigned resources, managers can access resources for their teams, and admins can access their account. Admin-created account-level keys are not tied to one user and can access the whole account. Every data operation is tenant-scoped. Report endpoints require a personal API key linked to an active staff, manager, or admin user; account-level keys are rejected.\n\nThe `/api-keys` endpoints are the exception: they use the signed-in Pilla web session token described by `UserSessionAuth`. Non-admins can manage their own keys; admins can also manage account-level keys.\n\n## Rate limiting\n\nAPI-key endpoints default to 60 requests per minute and 10,000 requests per day per key. Responses include `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset`. A 429 response also includes `Retry-After`.\n\n## Idempotency\n\nMutation POST, PATCH, and DELETE operations accept an optional `Idempotency-Key` header. Use a unique value for one logical mutation and reuse it only when retrying the exact same method, path, query, and request body. Successful and client-error responses are replayable for 24 hours. Reusing a key with a different request, or while the first request is still processing, returns 409. If safe replay storage is unavailable, keyed requests fail closed with 503 rather than risk repeating a mutation. Replayed responses include `Idempotency-Replayed: true`. The read-only report POST operations do not mutate data and do not use idempotency keys.\n\n## Pagination\n\nList endpoints use cursor pagination. Pass `limit` (1 to 200, default 50) and the previous response's `next_cursor` as `cursor`. Reports instead return at most 100 records and 100 groups per breakdown. Their `hasMore` fields say when matching records or groups were omitted.\n\n## Versioning and deprecation\n\n`/api/v1` is the current stable REST version. Backward-compatible fields and operations may be added within v1. Breaking changes use a new versioned base path. Before a v1 operation is removed, its OpenAPI operation will be marked deprecated and responses will include `Deprecation` and `Sunset` headers with migration guidance.\n\n## Errors\n\nErrors use a JSON object with `error.code`, `error.message`, and `error.status`. Unknown `/api/v1/*` paths also return this JSON format rather than an HTML page.\n\n## Webhooks\n\nWebhook callbacks are signed with HMAC-SHA256. The creation response returns the signing secret once.\n\n## Model Context Protocol\n\nFor agent integrations, use the streamable HTTP MCP endpoint at `https://yourpilla.com/api/mcp`. It supports Pilla API keys and OAuth. Discovery and setup guidance is available at `https://yourpilla.com/developers/mcp`."
  },
  "servers": [
    {
      "url": "https://yourpilla.com/api/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "Users",
      "description": "Manage users in your account"
    },
    {
      "name": "Teams",
      "description": "Manage teams and team membership"
    },
    {
      "name": "Workflows",
      "description": "View and complete workflow instances"
    },
    {
      "name": "Reports",
      "description": "Read stored workflow run and step performance"
    },
    {
      "name": "Webhooks",
      "description": "Subscribe to events via signed HTTP callbacks"
    },
    {
      "name": "API Keys",
      "description": "Create and manage Pilla API credentials"
    }
  ],
  "paths": {
    "/users": {
      "get": {
        "tags": [
          "Users"
        ],
        "summary": "List users",
        "description": "Returns a paginated list of active users in your account. Staff (role 1) see only themselves. Managers (role 2) see users on their teams. Admins (role 3+) and account-level keys see all users.",
        "operationId": "listUsers",
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "team_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by team ID"
          },
          {
            "name": "role",
            "in": "query",
            "schema": {
              "type": "integer",
              "enum": [
                1,
                2,
                3
              ]
            },
            "description": "Filter by role (1 = staff, 2 = manager, 3 = admin)"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of users",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/User"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "tags": [
          "Users"
        ],
        "summary": "Create a user",
        "operationId": "createUser",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "User created",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/User"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/IdempotencyUnavailable"
          }
        },
        "description": "Creates a new user. Requires admin role (3+).",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ]
      }
    },
    "/users/{id}": {
      "get": {
        "tags": [
          "Users"
        ],
        "summary": "Get a user",
        "description": "Returns a single user with their team memberships. Staff can only access their own record. Managers can access users on their teams.",
        "operationId": "getUser",
        "parameters": [
          {
            "$ref": "#/components/parameters/ResourceId"
          }
        ],
        "responses": {
          "200": {
            "description": "User details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/UserDetail"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "tags": [
          "Users"
        ],
        "summary": "Update a user",
        "operationId": "updateUser",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/ResourceId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "User updated",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/User"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/IdempotencyUnavailable"
          }
        },
        "description": "Updates a user. Requires admin role (3+)."
      },
      "delete": {
        "tags": [
          "Users"
        ],
        "summary": "Archive a user",
        "description": "Soft-deletes the user by setting `date_archived`. Requires admin role (3+).",
        "operationId": "archiveUser",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/ResourceId"
          }
        ],
        "responses": {
          "200": {
            "description": "User archived",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "archived": {
                              "type": "boolean",
                              "example": true
                            },
                            "id": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/IdempotencyUnavailable"
          }
        }
      }
    },
    "/teams": {
      "get": {
        "tags": [
          "Teams"
        ],
        "summary": "List teams",
        "operationId": "listTeams",
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of teams",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Team"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "description": "Returns a paginated list of teams. Staff and managers see only their own teams. Admins and account-level keys see all teams."
      },
      "post": {
        "tags": [
          "Teams"
        ],
        "summary": "Create a team",
        "operationId": "createTeam",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeamCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Team created",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Team"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/IdempotencyUnavailable"
          }
        },
        "description": "Creates a new team. Requires admin role (3+).",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ]
      }
    },
    "/teams/{id}": {
      "get": {
        "tags": [
          "Teams"
        ],
        "summary": "Get a team",
        "description": "Returns a single team with member count. Staff and managers can only access their own teams.",
        "operationId": "getTeam",
        "parameters": [
          {
            "$ref": "#/components/parameters/ResourceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Team details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/TeamDetail"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "tags": [
          "Teams"
        ],
        "summary": "Update a team",
        "operationId": "updateTeam",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/ResourceId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeamUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Team updated",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Team"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/IdempotencyUnavailable"
          }
        },
        "description": "Updates a team. Requires admin role (3+)."
      }
    },
    "/teams/{id}/members": {
      "get": {
        "tags": [
          "Teams"
        ],
        "summary": "List team members",
        "operationId": "listTeamMembers",
        "parameters": [
          {
            "$ref": "#/components/parameters/ResourceId"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of team members",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/TeamMember"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "description": "Returns a paginated list of members for a team. Staff and managers can only access their own teams."
      },
      "post": {
        "tags": [
          "Teams"
        ],
        "summary": "Add a member to a team",
        "operationId": "addTeamMember",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/ResourceId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "user_id"
                ],
                "properties": {
                  "user_id": {
                    "type": "string",
                    "description": "The ID of the user to add"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Member added",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "user_id": {
                              "type": "string"
                            },
                            "team_id": {
                              "type": "string"
                            },
                            "joined_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/IdempotencyUnavailable"
          }
        },
        "description": "Adds a user to a team. Requires admin role (3+)."
      }
    },
    "/workflows": {
      "get": {
        "tags": [
          "Workflows"
        ],
        "summary": "List workflows",
        "operationId": "listWork",
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "team_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by team ID"
          },
          {
            "name": "start_date",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Filter workflows due on or after this date"
          },
          {
            "name": "end_date",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Filter workflows due on or before this date"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "completed",
                "pending",
                "overdue"
              ]
            },
            "description": "Filter by workflow status"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of workflows",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Workflow"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "description": "Returns a paginated list of workflow instances. Staff see workflows for their teams, managers see workflows for their teams, and admins and account-level keys see all account workflows."
      }
    },
    "/workflows/{id}": {
      "get": {
        "tags": [
          "Workflows"
        ],
        "summary": "Get a workflow",
        "description": "Returns one workflow instance. Staff and managers can access workflows for their teams.",
        "operationId": "getWork",
        "parameters": [
          {
            "$ref": "#/components/parameters/ResourceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Workflow details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/WorkflowDetail"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/workflows/{id}/finish": {
      "post": {
        "tags": [
          "Workflows"
        ],
        "summary": "Finish a workflow",
        "description": "Marks a workflow as finished, emits the workflow.finished webhook event, and starts configured completion actions. Any role can finish an accessible workflow.",
        "operationId": "finishWork",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/ResourceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Workflow finished",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "finished_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/IdempotencyUnavailable"
          }
        }
      }
    },
    "/workflows/{id}/skip": {
      "post": {
        "tags": [
          "Workflows"
        ],
        "summary": "Skip a workflow",
        "description": "Marks a workflow as skipped and emits the workflow.skipped webhook event. Any role can skip an accessible workflow.",
        "operationId": "skipWork",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/ResourceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Workflow skipped",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "skipped_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/IdempotencyUnavailable"
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhook subscriptions",
        "operationId": "listWebhooks",
        "responses": {
          "200": {
            "description": "List of webhook subscriptions",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Webhook"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "description": "Returns all webhook subscriptions. Requires admin role (3+)."
      },
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Create a webhook subscription",
        "description": "Creates a webhook subscription. The `signing_secret` is returned only in the creation response and cannot be retrieved later. Requires admin role (3+).",
        "operationId": "createWebhook",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook created (includes signing_secret)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/WebhookCreated"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/IdempotencyUnavailable"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ]
      }
    },
    "/webhooks/{id}": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Get a webhook subscription",
        "operationId": "getWebhook",
        "parameters": [
          {
            "$ref": "#/components/parameters/ResourceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Webhook"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "description": "Returns details for a single webhook subscription. Requires admin role (3+)."
      },
      "patch": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Update a webhook subscription",
        "operationId": "updateWebhook",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/ResourceId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook updated",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Webhook"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/IdempotencyUnavailable"
          }
        },
        "description": "Updates a webhook subscription. Requires admin role (3+)."
      },
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete a webhook subscription",
        "description": "Soft-deletes the webhook subscription. Requires admin role (3+).",
        "operationId": "deleteWebhook",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/ResourceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook deleted",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "deleted": {
                              "type": "boolean",
                              "example": true
                            },
                            "id": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/IdempotencyUnavailable"
          }
        }
      }
    },
    "/api-keys": {
      "get": {
        "tags": [
          "API Keys"
        ],
        "summary": "List API keys",
        "description": "Lists API keys visible to the signed-in user. Admins see account keys; other users see keys they created.",
        "operationId": "listApiKeys",
        "responses": {
          "200": {
            "description": "List of API keys",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/ApiKey"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [
          {
            "UserSessionAuth": []
          }
        ]
      },
      "post": {
        "tags": [
          "API Keys"
        ],
        "summary": "Create an API key",
        "description": "Creates a new API key linked to the authenticated user. The full key is returned only in the creation response and cannot be retrieved later. Set `account_level: true` to create an account-level key with unrestricted access (admin only).",
        "operationId": "createApiKey",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiKeyCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "API key created (includes full key)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ApiKeyCreated"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/IdempotencyUnavailable"
          }
        },
        "security": [
          {
            "UserSessionAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ]
      }
    },
    "/api-keys/{id}": {
      "get": {
        "tags": [
          "API Keys"
        ],
        "summary": "Get an API key",
        "description": "Returns one API key visible to the signed-in user.",
        "operationId": "getApiKey",
        "parameters": [
          {
            "$ref": "#/components/parameters/ResourceId"
          }
        ],
        "responses": {
          "200": {
            "description": "API key details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ApiKey"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [
          {
            "UserSessionAuth": []
          }
        ]
      },
      "delete": {
        "tags": [
          "API Keys"
        ],
        "summary": "Revoke an API key",
        "description": "Revokes an API key visible to the signed-in user.",
        "operationId": "revokeApiKey",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/ResourceId"
          }
        ],
        "responses": {
          "200": {
            "description": "API key revoked",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "revoked": {
                              "type": "boolean",
                              "example": true
                            },
                            "id": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/IdempotencyUnavailable"
          }
        },
        "security": [
          {
            "UserSessionAuth": []
          }
        ]
      }
    },
    "/teams/{id}/members/{user_id}": {
      "delete": {
        "tags": [
          "Teams"
        ],
        "summary": "Remove a member from a team",
        "description": "Removes a user from a team. Requires admin role (3+).",
        "operationId": "removeTeamMember",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/ResourceId"
          },
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The ID of the user to remove"
          }
        ],
        "responses": {
          "200": {
            "description": "Member removed",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "removed": {
                              "type": "boolean",
                              "example": true
                            },
                            "user_id": {
                              "type": "string"
                            },
                            "team_id": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/IdempotencyUnavailable"
          }
        }
      }
    },
    "/reports/workflow-runs": {
      "post": {
        "tags": [
          "Reports"
        ],
        "summary": "Report on workflow runs",
        "description": "Returns a read-only report over stored workflow runs scheduled within an inclusive local-calendar date range. Staff and managers see only teams they currently belong to. Admins see the whole account. Account-level API keys are rejected because reports require a linked, active role 1, 2, or 3 user. A future run is unfinished and not yet overdue, including work in progress and work without a deadline. Team and tag filters refer to the workflow run. Records and each breakdown are capped at 100; `hasMore` reports omitted results. Completion rates exclude future runs and are rounded to four decimal places.",
        "operationId": "reportWorkflowRuns",
        "x-read-only": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkflowRunReportRequest"
              },
              "example": {
                "start_date": "2026-09-01",
                "end_date": "2026-09-07",
                "team_ids": ["team_london"],
                "tag_ids": ["opening_checks", "__none__"],
                "statuses": ["on_time", "missed"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored workflow run report",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowRunReportResponse"
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/ValidationError" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "500": { "$ref": "#/components/responses/InternalError" },
          "502": { "$ref": "#/components/responses/ReportUpstreamError" },
          "503": { "$ref": "#/components/responses/ReportUnavailable" },
          "504": { "$ref": "#/components/responses/ReportTimeout" }
        }
      }
    },
    "/reports/workflow-steps": {
      "post": {
        "tags": [
          "Reports"
        ],
        "summary": "Report on workflow steps",
        "description": "Returns a read-only report over stored workflow steps whose workflow run is scheduled within an inclusive local-calendar date range. Staff and managers see only teams they currently belong to. Admins see the whole account. Account-level API keys are rejected because reports require a linked, active role 1, 2, or 3 user. A future step is unfinished and not yet overdue, including steps in work in progress or without a deadline. `tag_ids` filters step tags independently of workflow run tags. Answers contain stored scalar, list, checklist, or media metadata only. Media values never contain file contents or URLs. Records and each breakdown are capped at 100; `hasMore` reports omitted results. Completion rates include missed and skipped steps in the denominator, exclude future steps, and are rounded to four decimal places.",
        "operationId": "reportWorkflowSteps",
        "x-read-only": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkflowStepReportRequest"
              },
              "example": {
                "start_date": "2026-09-01",
                "end_date": "2026-09-07",
                "team_ids": null,
                "tag_ids": ["temperature_check", "__none__"],
                "statuses": ["on_time", "skipped"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored workflow step report",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowStepReportResponse"
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/ValidationError" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "500": { "$ref": "#/components/responses/InternalError" },
          "502": { "$ref": "#/components/responses/ReportUpstreamError" },
          "503": { "$ref": "#/components/responses/ReportUnavailable" },
          "504": { "$ref": "#/components/responses/ReportTimeout" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key authentication. Use your API key (pk_live_...) as a Bearer token."
      },
      "UserSessionAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Signed-in Pilla user session token. Used only by API-key management endpoints."
      }
    },
    "parameters": {
      "ResourceId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "Resource ID"
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "schema": {
          "type": "string"
        },
        "description": "Pagination cursor from a previous response"
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200,
          "default": 50
        },
        "description": "Number of results per page (1-200)"
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "description": "Unique retry key for one logical mutation. Retained for 24 hours."
      }
    },
    "schemas": {
      "Meta": {
        "type": "object",
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Pagination": {
        "type": "object",
        "properties": {
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": "string"
          },
          "limit": {
            "type": "integer"
          }
        }
      },
      "SuccessResponse": {
        "type": "object",
        "properties": {
          "data": {},
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "PaginatedResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {}
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "INVALID_API_KEY",
                  "INSUFFICIENT_ROLE",
                  "IP_NOT_ALLOWED",
                  "RATE_LIMIT_EXCEEDED",
                  "RESOURCE_NOT_FOUND",
                  "VALIDATION_ERROR",
                  "INTERNAL_ERROR",
                  "METHOD_NOT_ALLOWED",
                  "IP_BLOCKED",
                  "IDEMPOTENCY_CONFLICT",
                  "IDEMPOTENCY_IN_PROGRESS",
                  "IDEMPOTENCY_UNAVAILABLE"
                ]
              },
              "message": {
                "type": "string"
              },
              "status": {
                "type": "integer"
              }
            }
          }
        }
      },
      "UserRef": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          }
        }
      },
      "TeamRef": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "TemplateRef": {
        "type": "object",
        "nullable": true,
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "rrule": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "User": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "role_id": {
            "type": "integer",
            "description": "1 = staff, 2 = manager, 3 = admin"
          },
          "job_title": {
            "type": "string",
            "nullable": true
          },
          "profile_picture": {
            "type": "string",
            "nullable": true
          },
          "birthday": {
            "type": "string",
            "nullable": true
          },
          "last_active": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "salary": {
            "type": "number",
            "nullable": true
          },
          "work_start": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "UserDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/User"
          },
          {
            "type": "object",
            "properties": {
              "teams": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TeamRef"
                }
              }
            }
          }
        ]
      },
      "UserCreate": {
        "type": "object",
        "required": [
          "name",
          "email"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "role_id": {
            "type": "integer",
            "default": 1,
            "description": "1 = staff, 2 = manager, 3 = admin"
          },
          "job_title": {
            "type": "string"
          },
          "birthday": {
            "type": "string"
          },
          "salary": {
            "type": "number"
          },
          "work_start": {
            "type": "string"
          }
        }
      },
      "UserUpdate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "role_id": {
            "type": "integer"
          },
          "job_title": {
            "type": "string"
          },
          "birthday": {
            "type": "string"
          },
          "salary": {
            "type": "number"
          },
          "work_start": {
            "type": "string"
          }
        }
      },
      "Team": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "address": {
            "type": "string",
            "nullable": true
          },
          "latitude": {
            "type": "number",
            "nullable": true
          },
          "longitude": {
            "type": "number",
            "nullable": true
          },
          "timezone": {
            "type": "string",
            "nullable": true
          },
          "use_location": {
            "type": "boolean",
            "nullable": true
          },
          "profile_picture": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TeamDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Team"
          },
          {
            "type": "object",
            "properties": {
              "member_count": {
                "type": "integer"
              }
            }
          }
        ]
      },
      "TeamCreate": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "timezone": {
            "type": "string"
          },
          "latitude": {
            "type": "number"
          },
          "longitude": {
            "type": "number"
          },
          "use_location": {
            "type": "boolean"
          }
        }
      },
      "TeamUpdate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "timezone": {
            "type": "string"
          },
          "latitude": {
            "type": "number"
          },
          "longitude": {
            "type": "number"
          },
          "use_location": {
            "type": "boolean"
          }
        }
      },
      "TeamMember": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "job_title": {
            "type": "string",
            "nullable": true
          },
          "role_id": {
            "type": "integer"
          },
          "profile_picture": {
            "type": "string",
            "nullable": true
          },
          "joined_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Workflow": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "start_time": {
            "type": "string",
            "format": "date-time"
          },
          "end_time": {
            "type": "string",
            "format": "date-time"
          },
          "finished_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "completed",
              "pending",
              "overdue"
            ]
          },
          "business_timezone": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "user": {
            "$ref": "#/components/schemas/UserRef"
          },
          "team": {
            "$ref": "#/components/schemas/TeamRef"
          },
          "template": {
            "$ref": "#/components/schemas/TemplateRef"
          }
        }
      },
      "WorkflowDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Workflow"
          }
        ]
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEvent"
            }
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "enabled": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookCreated": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Webhook"
          },
          {
            "type": "object",
            "properties": {
              "signing_secret": {
                "type": "string",
                "description": "HMAC signing secret (whsec_...). Only returned on creation."
              }
            }
          }
        ]
      },
      "WebhookCreate": {
        "type": "object",
        "required": [
          "url",
          "events"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "HTTPS URL to receive webhook payloads"
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEvent"
            },
            "description": "Events to subscribe to"
          },
          "description": {
            "type": "string"
          }
        }
      },
      "WebhookUpdate": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEvent"
            }
          },
          "description": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "WebhookEvent": {
        "type": "string",
        "enum": [
          "workflow.finished",
          "workflow.skipped",
          "user.created",
          "user.archived"
        ]
      },
      "ApiKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "key_prefix": {
            "type": "string",
            "description": "First 12 characters of the key (e.g. pk_live_abc1)"
          },
          "user_id": {
            "type": "string",
            "nullable": true,
            "description": "The user this key is linked to, or null for account-level keys"
          },
          "account_level": {
            "type": "boolean",
            "description": "Whether this is an account-level key with unrestricted access"
          },
          "last_used_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ApiKeyCreated": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiKey"
          },
          {
            "type": "object",
            "properties": {
              "key": {
                "type": "string",
                "description": "The full API key (pk_live_...). Only returned on creation."
              }
            }
          }
        ]
      },
      "WorkflowAnalysisIdList": {
        "type": "array",
        "maxItems": 100,
        "uniqueItems": true,
        "items": {
          "type": "string",
          "pattern": "^[a-zA-Z0-9_-]{1,100}$"
        }
      },
      "WorkflowRunReportRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["start_date", "end_date"],
        "properties": {
          "start_date": {
            "type": "string",
            "format": "date",
            "description": "First scheduled local calendar date, inclusive. The range must span no more than 366 days.",
            "example": "2026-09-01"
          },
          "end_date": {
            "type": "string",
            "format": "date",
            "description": "Last scheduled local calendar date, inclusive. Must be on or after start_date.",
            "example": "2026-09-07"
          },
          "team_ids": {
            "description": "Workflow team IDs. Omit or use null for all permitted teams; [] matches no teams.",
            "oneOf": [
              { "$ref": "#/components/schemas/WorkflowAnalysisIdList" },
              { "type": "null" }
            ]
          },
          "tag_ids": {
            "description": "Workflow run tag IDs. Omit or use null for all tags; [] matches no tags; __none__ matches untagged runs.",
            "oneOf": [
              { "$ref": "#/components/schemas/WorkflowAnalysisIdList" },
              { "type": "null" }
            ]
          },
          "statuses": {
            "description": "Run statuses. Omit or use null for all statuses; [] matches no runs.",
            "oneOf": [
              {
                "type": "array",
                "maxItems": 100,
                "uniqueItems": true,
                "items": { "type": "string", "enum": ["on_time", "late", "missed", "future"] }
              },
              { "type": "null" }
            ]
          }
        }
      },
      "WorkflowStepReportRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["start_date", "end_date"],
        "properties": {
          "start_date": {
            "type": "string",
            "format": "date",
            "description": "First workflow scheduled local calendar date, inclusive. The range must span no more than 366 days.",
            "example": "2026-09-01"
          },
          "end_date": {
            "type": "string",
            "format": "date",
            "description": "Last workflow scheduled local calendar date, inclusive. Must be on or after start_date.",
            "example": "2026-09-07"
          },
          "team_ids": {
            "description": "Workflow team IDs. Omit or use null for all permitted teams; [] matches no teams.",
            "oneOf": [
              { "$ref": "#/components/schemas/WorkflowAnalysisIdList" },
              { "type": "null" }
            ]
          },
          "tag_ids": {
            "description": "Step tag IDs, independent of workflow run tags. Omit or use null for all tags; [] matches no tags; __none__ matches untagged steps.",
            "oneOf": [
              { "$ref": "#/components/schemas/WorkflowAnalysisIdList" },
              { "type": "null" }
            ]
          },
          "statuses": {
            "description": "Step statuses. Omit or use null for all statuses; [] matches no steps.",
            "oneOf": [
              {
                "type": "array",
                "maxItems": 100,
                "uniqueItems": true,
                "items": { "type": "string", "enum": ["on_time", "late", "missed", "future", "skipped"] }
              },
              { "type": "null" }
            ]
          }
        }
      },
      "WorkflowAnalysisAccessScope": {
        "type": "object",
        "additionalProperties": false,
        "required": ["accountWide", "description"],
        "properties": {
          "accountWide": { "type": "boolean" },
          "description": {
            "type": "string",
            "description": "Whether the linked user receives account-wide results or only results for teams they currently belong to."
          }
        }
      },
      "WorkflowRunCountFields": {
        "type": "object",
        "required": ["total", "completed", "onTime", "late", "missed", "future", "completionRate"],
        "properties": {
          "total": { "type": "integer", "minimum": 0 },
          "completed": { "type": "integer", "minimum": 0 },
          "onTime": { "type": "integer", "minimum": 0 },
          "late": { "type": "integer", "minimum": 0 },
          "missed": { "type": "integer", "minimum": 0 },
          "future": { "type": "integer", "minimum": 0 },
          "completionRate": {
            "description": "completed / (completed + missed), excluding future runs and rounded to four decimal places; null when the denominator is zero.",
            "type": ["number", "null"],
            "minimum": 0,
            "maximum": 1
          }
        }
      },
      "WorkflowStepCountFields": {
        "type": "object",
        "required": ["total", "completed", "onTime", "late", "missed", "future", "skipped", "completionRate"],
        "properties": {
          "total": { "type": "integer", "minimum": 0 },
          "completed": { "type": "integer", "minimum": 0 },
          "onTime": { "type": "integer", "minimum": 0 },
          "late": { "type": "integer", "minimum": 0 },
          "missed": { "type": "integer", "minimum": 0 },
          "future": { "type": "integer", "minimum": 0 },
          "skipped": { "type": "integer", "minimum": 0 },
          "completionRate": {
            "description": "completed / (completed + missed + skipped), excluding future steps and rounded to four decimal places; null when the denominator is zero.",
            "type": ["number", "null"],
            "minimum": 0,
            "maximum": 1
          }
        }
      },
      "WorkflowRunTotals": {
        "allOf": [
          { "$ref": "#/components/schemas/WorkflowRunCountFields" }
        ],
        "unevaluatedProperties": false
      },
      "WorkflowStepTotals": {
        "allOf": [
          { "$ref": "#/components/schemas/WorkflowStepCountFields" }
        ],
        "unevaluatedProperties": false
      },
      "WorkflowRunGroup": {
        "allOf": [
          { "$ref": "#/components/schemas/WorkflowRunCountFields" },
          {
            "type": "object",
            "required": ["id", "name"],
            "properties": {
              "id": { "type": ["string", "null"] },
              "name": { "type": "string" }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "WorkflowStepGroup": {
        "allOf": [
          { "$ref": "#/components/schemas/WorkflowStepCountFields" },
          {
            "type": "object",
            "required": ["id", "name"],
            "properties": {
              "id": { "type": ["string", "null"] },
              "name": { "type": "string" }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "WorkflowRunBreakdown": {
        "type": "object",
        "additionalProperties": false,
        "required": ["groups", "hasMore"],
        "properties": {
          "groups": { "type": "array", "maxItems": 100, "items": { "$ref": "#/components/schemas/WorkflowRunGroup" } },
          "hasMore": { "type": "boolean", "description": "True when more than 100 groups matched." }
        }
      },
      "WorkflowStepBreakdown": {
        "type": "object",
        "additionalProperties": false,
        "required": ["groups", "hasMore"],
        "properties": {
          "groups": { "type": "array", "maxItems": 100, "items": { "$ref": "#/components/schemas/WorkflowStepGroup" } },
          "hasMore": { "type": "boolean", "description": "True when more than 100 groups matched." }
        }
      },
      "WorkflowRunSeriesPoint": {
        "allOf": [
          { "$ref": "#/components/schemas/WorkflowRunCountFields" },
          { "type": "object", "required": ["date"], "properties": { "date": { "type": "string", "format": "date" } } }
        ],
        "unevaluatedProperties": false
      },
      "WorkflowStepSeriesPoint": {
        "allOf": [
          { "$ref": "#/components/schemas/WorkflowStepCountFields" },
          { "type": "object", "required": ["date"], "properties": { "date": { "type": "string", "format": "date" } } }
        ],
        "unevaluatedProperties": false
      },
      "WorkflowAnalysisCompletedBy": {
        "type": "object",
        "additionalProperties": false,
        "required": ["id", "name"],
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" }
        }
      },
      "WorkflowRunRecord": {
        "type": "object",
        "additionalProperties": false,
        "required": ["id", "name", "workflowId", "workflowName", "teamName", "templateName", "tagName", "date", "startedAt", "status"],
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "workflowId": { "type": "string" },
          "workflowName": { "type": "string" },
          "teamId": { "type": "string" },
          "teamName": { "type": "string" },
          "templateId": { "type": "string" },
          "templateName": { "type": "string" },
          "tagId": { "type": "string" },
          "tagName": { "type": "string" },
          "date": { "type": "string", "format": "date", "description": "Workflow scheduled date in its local business or team timezone." },
          "startedAt": { "type": "string", "format": "date-time" },
          "dueAt": { "type": "string", "format": "date-time" },
          "status": { "type": "string", "enum": ["on_time", "late", "missed", "future"] },
          "completionTimestamp": { "type": "string", "format": "date-time" }
        }
      },
      "WorkflowAnalysisScalarAnswer": {
        "type": "object",
        "additionalProperties": false,
        "required": ["kind", "value", "truncated"],
        "properties": {
          "kind": { "const": "scalar" },
          "value": { "type": "string", "maxLength": 2000 },
          "truncated": { "type": "boolean", "description": "True when the stored scalar exceeded 2,000 characters." }
        }
      },
      "WorkflowAnalysisListAnswer": {
        "type": "object",
        "additionalProperties": false,
        "required": ["kind", "value", "truncated"],
        "properties": {
          "kind": { "const": "list" },
          "value": { "type": "array", "maxItems": 20, "items": { "type": ["string", "null"], "maxLength": 100 } },
          "truncated": { "type": "boolean", "description": "True when more than 20 items existed or an item exceeded 100 characters." }
        }
      },
      "WorkflowAnalysisChecklistItem": {
        "type": "object",
        "additionalProperties": false,
        "required": ["completed"],
        "properties": {
          "instruction": { "type": "string", "maxLength": 100 },
          "completed": { "type": "boolean" }
        }
      },
      "WorkflowAnalysisChecklistAnswer": {
        "type": "object",
        "additionalProperties": false,
        "required": ["kind", "total", "completed", "items", "truncated"],
        "properties": {
          "kind": { "const": "checklist" },
          "total": { "type": "integer", "minimum": 0 },
          "completed": { "type": "integer", "minimum": 0 },
          "items": { "type": "array", "maxItems": 20, "items": { "$ref": "#/components/schemas/WorkflowAnalysisChecklistItem" } },
          "truncated": { "type": "boolean", "description": "True when more than 20 items existed or an instruction exceeded 100 characters." }
        }
      },
      "WorkflowAnalysisMediaAnswer": {
        "type": "object",
        "additionalProperties": false,
        "required": ["kind", "recorded", "truncated"],
        "properties": {
          "kind": { "const": "media" },
          "recorded": { "type": "boolean" },
          "value": { "type": "null", "description": "When present, always null. JSON output normally omits it. The report exposes media metadata only." },
          "truncated": { "const": false }
        }
      },
      "WorkflowAnalysisAnswer": {
        "oneOf": [
          { "$ref": "#/components/schemas/WorkflowAnalysisScalarAnswer" },
          { "$ref": "#/components/schemas/WorkflowAnalysisListAnswer" },
          { "$ref": "#/components/schemas/WorkflowAnalysisChecklistAnswer" },
          { "$ref": "#/components/schemas/WorkflowAnalysisMediaAnswer" }
        ]
      },
      "WorkflowStepRecord": {
        "type": "object",
        "additionalProperties": false,
        "required": ["id", "name", "workflowId", "workflowName", "teamName", "templateName", "tagName", "date", "startedAt", "status", "type"],
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "workflowId": { "type": "string" },
          "workflowName": { "type": "string" },
          "teamId": { "type": "string" },
          "teamName": { "type": "string" },
          "templateId": { "type": "string" },
          "templateName": { "type": "string" },
          "tagId": { "type": "string", "description": "Step tag ID, independent of the workflow run tag." },
          "tagName": { "type": "string", "description": "Step tag name, independent of the workflow run tag." },
          "date": { "type": "string", "format": "date", "description": "Workflow scheduled date in its local business or team timezone." },
          "startedAt": { "type": "string", "format": "date-time" },
          "dueAt": { "type": "string", "format": "date-time" },
          "status": { "type": "string", "enum": ["on_time", "late", "missed", "future", "skipped"] },
          "type": { "type": "string" },
          "completionTimestamp": { "type": "string", "format": "date-time" },
          "completedBy": { "$ref": "#/components/schemas/WorkflowAnalysisCompletedBy" },
          "answer": { "$ref": "#/components/schemas/WorkflowAnalysisAnswer" }
        }
      },
      "WorkflowRunReport": {
        "type": "object",
        "additionalProperties": false,
        "required": ["reportVersion", "source", "filters", "coverage", "asOf", "totals", "breakdowns", "series", "records", "recordsLimit", "hasMore", "accessScope"],
        "properties": {
          "reportVersion": { "const": "workflow_analysis_v1" },
          "source": { "const": "runs" },
          "filters": { "$ref": "#/components/schemas/WorkflowRunReportFilters" },
          "coverage": { "const": "stored", "description": "Only answers and timings stored by Pilla are reported." },
          "asOf": { "type": "string", "format": "date-time" },
          "totals": { "$ref": "#/components/schemas/WorkflowRunTotals" },
          "breakdowns": {
            "type": "object",
            "additionalProperties": false,
            "required": ["teams", "tags", "templates"],
            "properties": {
              "teams": { "$ref": "#/components/schemas/WorkflowRunBreakdown" },
              "tags": { "$ref": "#/components/schemas/WorkflowRunBreakdown" },
              "templates": { "$ref": "#/components/schemas/WorkflowRunBreakdown" }
            }
          },
          "series": { "type": "array", "maxItems": 366, "items": { "$ref": "#/components/schemas/WorkflowRunSeriesPoint" } },
          "records": { "type": "array", "maxItems": 100, "items": { "$ref": "#/components/schemas/WorkflowRunRecord" } },
          "recordsLimit": { "const": 100 },
          "hasMore": { "type": "boolean", "description": "True when more than 100 records matched." },
          "accessScope": { "$ref": "#/components/schemas/WorkflowAnalysisAccessScope" }
        }
      },
      "WorkflowStepReport": {
        "type": "object",
        "additionalProperties": false,
        "required": ["reportVersion", "source", "filters", "coverage", "asOf", "totals", "breakdowns", "series", "records", "recordsLimit", "hasMore", "accessScope"],
        "properties": {
          "reportVersion": { "const": "workflow_analysis_v1" },
          "source": { "const": "steps" },
          "filters": { "$ref": "#/components/schemas/WorkflowStepReportFilters" },
          "coverage": { "const": "stored", "description": "Only answers and timings stored by Pilla are reported." },
          "asOf": { "type": "string", "format": "date-time" },
          "totals": { "$ref": "#/components/schemas/WorkflowStepTotals" },
          "breakdowns": {
            "type": "object",
            "additionalProperties": false,
            "required": ["teams", "tags", "templates", "steps"],
            "properties": {
              "teams": { "$ref": "#/components/schemas/WorkflowStepBreakdown" },
              "tags": { "$ref": "#/components/schemas/WorkflowStepBreakdown" },
              "templates": { "$ref": "#/components/schemas/WorkflowStepBreakdown" },
              "steps": { "$ref": "#/components/schemas/WorkflowStepBreakdown" }
            }
          },
          "series": { "type": "array", "maxItems": 366, "items": { "$ref": "#/components/schemas/WorkflowStepSeriesPoint" } },
          "records": { "type": "array", "maxItems": 100, "items": { "$ref": "#/components/schemas/WorkflowStepRecord" } },
          "recordsLimit": { "const": 100 },
          "hasMore": { "type": "boolean", "description": "True when more than 100 records matched." },
          "accessScope": { "$ref": "#/components/schemas/WorkflowAnalysisAccessScope" }
        }
      },
      "WorkflowRunReportFilters": {
        "type": "object",
        "additionalProperties": false,
        "required": ["start_date", "end_date", "team_ids", "tag_ids", "statuses"],
        "properties": {
          "start_date": { "type": "string", "format": "date" },
          "end_date": { "type": "string", "format": "date" },
          "team_ids": { "oneOf": [{ "$ref": "#/components/schemas/WorkflowAnalysisIdList" }, { "type": "null" }] },
          "tag_ids": { "oneOf": [{ "$ref": "#/components/schemas/WorkflowAnalysisIdList" }, { "type": "null" }] },
          "statuses": { "oneOf": [{ "type": "array", "uniqueItems": true, "maxItems": 100, "items": { "type": "string", "enum": ["on_time", "late", "missed", "future"] } }, { "type": "null" }] }
        }
      },
      "WorkflowStepReportFilters": {
        "type": "object",
        "additionalProperties": false,
        "required": ["start_date", "end_date", "team_ids", "tag_ids", "statuses"],
        "properties": {
          "start_date": { "type": "string", "format": "date" },
          "end_date": { "type": "string", "format": "date" },
          "team_ids": { "oneOf": [{ "$ref": "#/components/schemas/WorkflowAnalysisIdList" }, { "type": "null" }] },
          "tag_ids": { "oneOf": [{ "$ref": "#/components/schemas/WorkflowAnalysisIdList" }, { "type": "null" }] },
          "statuses": { "oneOf": [{ "type": "array", "uniqueItems": true, "maxItems": 100, "items": { "type": "string", "enum": ["on_time", "late", "missed", "future", "skipped"] } }, { "type": "null" }] }
        }
      },
      "WorkflowRunReportResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": ["data", "meta"],
        "properties": {
          "data": { "$ref": "#/components/schemas/WorkflowRunReport" },
          "meta": { "$ref": "#/components/schemas/Meta" }
        }
      },
      "WorkflowStepReportResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": ["data", "meta"],
        "properties": {
          "data": { "$ref": "#/components/schemas/WorkflowStepReport" },
          "meta": { "$ref": "#/components/schemas/Meta" }
        }
      },
      "ApiKeyCreate": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "A label for the API key"
          },
          "account_level": {
            "type": "boolean",
            "description": "Create an account-level key with unrestricted access. Requires admin role (3+).",
            "default": false
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Optional expiry date"
          }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Invalid or missing API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": {
                "code": "INVALID_API_KEY",
                "message": "Invalid or expired API key",
                "status": 401
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "Insufficient role for this operation",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": {
                "code": "INSUFFICIENT_ROLE",
                "message": "This operation requires admin role (role 3+)",
                "status": 403
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": {
                "code": "RESOURCE_NOT_FOUND",
                "message": "Resource not found",
                "status": 404
              }
            }
          }
        }
      },
      "ValidationError": {
        "description": "Validation error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": {
                "code": "VALIDATION_ERROR",
                "message": "name is required",
                "status": 400
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": {
                "code": "RATE_LIMIT_EXCEEDED",
                "message": "Rate limit exceeded",
                "status": 429
              }
            }
          }
        }
      },
      "InternalError": {
        "description": "Internal server error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": {
                "code": "INTERNAL_ERROR",
                "message": "Internal server error",
                "status": 500
              }
            }
          }
        }
      },
      "ReportUpstreamError": {
        "description": "The reporting service returned an invalid or unexpected response",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ErrorResponse" },
            "example": {
              "error": {
                "code": "INTERNAL_ERROR",
                "message": "Reporting service returned an invalid response",
                "status": 502
              }
            }
          }
        }
      },
      "ReportUnavailable": {
        "description": "The reporting service is unavailable",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ErrorResponse" },
            "example": {
              "error": {
                "code": "INTERNAL_ERROR",
                "message": "Reporting service is unavailable",
                "status": 503
              }
            }
          }
        }
      },
      "ReportTimeout": {
        "description": "The report exceeded its execution time limit; retry with a shorter date range",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ErrorResponse" },
            "example": {
              "error": {
                "code": "INTERNAL_ERROR",
                "message": "This report took too long. Try a shorter date range.",
                "status": 504
              }
            }
          }
        }
      },
      "IdempotencyConflict": {
        "description": "The key is already processing or was used with a different request",
        "headers": {
          "Retry-After": {
            "description": "Present while the original request is still processing",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "IdempotencyUnavailable": {
        "description": "Safe idempotent replay is temporarily unavailable",
        "headers": {
          "Retry-After": {
            "description": "Seconds to wait before retrying",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    }
  }
}
