{
  "openapi": "3.1.0",
  "info": {
    "title": "GlinGo Public API",
    "version": "v1",
    "description": "Public API for workspace-scoped integrations. Authentication: x-api-key: <glk_...>."
  },
  "servers": [
    { "url": "https://your-domain.com" }
  ],
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key"
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "ok": { "type": "boolean", "const": false },
          "error": {
            "type": "object",
            "properties": {
              "code": { "type": "string" },
              "message": { "type": "string" }
            },
            "required": ["code", "message"]
          }
        },
        "required": ["ok", "error"]
      },
      "SuccessEnvelope": {
        "type": "object",
        "properties": {
          "ok": { "type": "boolean", "const": true },
          "data": { "type": "object", "additionalProperties": true }
        },
        "required": ["ok", "data"]
      }
    }
  },
  "security": [{ "ApiKeyAuth": [] }],
  "paths": {
    "/api/reports/team": {
      "get": {
        "summary": "Team",
        "tags": [
          "Analytics"
        ],
        "description": "Member time, earnings, receipts and debt. full returns rows and summary; summary omits rows; table returns only rows and period. Requires owner/admin role; other roles receive can_manage_team=false without analytics. Requires reports:read, included in newly created read/full keys. Existing keys must be recreated to gain this scope. Read-only; HEAD has no response body.",
        "x-required-scopes": [
          "reports:read"
        ],
        "parameters": [
          {
            "name": "accrual_from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive start; no lower bound when omitted."
          },
          {
            "name": "accrual_to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive end; no upper bound when omitted."
          },
          {
            "name": "project_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated IDs within the key workspace."
          },
          {
            "name": "counteragent_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated IDs within the key workspace."
          },
          {
            "name": "user_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated IDs within the key workspace."
          },
          {
            "name": "view",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "full",
                "summary",
                "table"
              ],
              "default": "full"
            }
          },
          {
            "name": "sort_key",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "worked",
                "earned",
                "received",
                "debt"
              ],
              "default": "earned"
            }
          },
          {
            "name": "sort_dir",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Fields vary by view and role.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "can_manage_team": {
                          "type": "boolean"
                        },
                        "period": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        },
                        "insights": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "chart_by_day": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        },
                        "focus": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "totals": {
                          "type": "object",
                          "additionalProperties": true
                        }
                      },
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters or report loading failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing reports:read scope or insufficient role",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/reports/activity": {
      "get": {
        "summary": "Activity",
        "tags": [
          "Analytics"
        ],
        "description": "Activity summary, period comparison, members, projects, clients and event feed. Pagination applies only to the feed. Requires owner/admin role; other roles receive can_manage_team=false without analytics. Requires reports:read, included in newly created read/full keys. Existing keys must be recreated to gain this scope. Read-only; HEAD has no response body.",
        "x-required-scopes": [
          "reports:read"
        ],
        "parameters": [
          {
            "name": "date_from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive start; no lower bound when omitted."
          },
          {
            "name": "date_to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive end; no upper bound when omitted."
          },
          {
            "name": "project_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated IDs within the key workspace."
          },
          {
            "name": "counteragent_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated IDs within the key workspace."
          },
          {
            "name": "user_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated IDs within the key workspace."
          },
          {
            "name": "feed_limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 30
            }
          },
          {
            "name": "feed_offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Fields vary by view and role.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "can_manage_team": {
                          "type": "boolean"
                        },
                        "period": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        },
                        "workspace_currency": {
                          "type": "string"
                        },
                        "filters": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "summary": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "sparkline_days": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        },
                        "projects_rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        },
                        "counteragents_rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        },
                        "comparison": {
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "feed": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        },
                        "feed_pagination": {
                          "type": "object",
                          "properties": {
                            "offset": {
                              "type": "integer"
                            },
                            "limit": {
                              "type": "integer"
                            },
                            "total": {
                              "type": "integer"
                            },
                            "has_more": {
                              "type": "boolean"
                            }
                          }
                        }
                      },
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters or report loading failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing reports:read scope or insufficient role",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/reports/debtors": {
      "get": {
        "summary": "Debtors",
        "tags": [
          "Analytics"
        ],
        "description": "Client or project debt, risk metrics and previous-period comparison. Requires owner/admin role; other roles receive can_manage_team=false without analytics. Requires reports:read, included in newly created read/full keys. Existing keys must be recreated to gain this scope. Read-only; HEAD has no response body.",
        "x-required-scopes": [
          "reports:read"
        ],
        "parameters": [
          {
            "name": "accrual_from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive start; no lower bound when omitted."
          },
          {
            "name": "accrual_to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive end; no upper bound when omitted."
          },
          {
            "name": "project_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated IDs within the key workspace."
          },
          {
            "name": "counteragent_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated IDs within the key workspace."
          },
          {
            "name": "user_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated IDs within the key workspace."
          },
          {
            "name": "view",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "counteragents",
                "projects"
              ],
              "default": "counteragents"
            }
          },
          {
            "name": "sort_key",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "name",
                "client",
                "debt",
                "earned",
                "received",
                "last_paid",
                "age",
                "projects_count"
              ],
              "default": "name"
            }
          },
          {
            "name": "sort_dir",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            }
          },
          {
            "name": "overdue_only",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ],
              "default": "0"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Fields vary by view and role.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "can_manage_team": {
                          "type": "boolean"
                        },
                        "period": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        },
                        "summary": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "risks": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "comparison": {
                          "type": [
                            "object",
                            "null"
                          ]
                        },
                        "view": {
                          "type": "string"
                        }
                      },
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters or report loading failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing reports:read scope or insufficient role",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/reports/debtors/reconciliation": {
      "get": {
        "summary": "Reconciliation",
        "tags": [
          "Analytics"
        ],
        "description": "Accruals and receipts for one entity through accrual_to, with running debt. The JSON response can be used to generate CSV. Requires owner/admin role; otherwise 403. Requires reports:read, included in newly created read/full keys. Existing keys must be recreated to gain this scope. Read-only; HEAD has no response body.",
        "x-required-scopes": [
          "reports:read"
        ],
        "parameters": [
          {
            "name": "entity_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "name": "view",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "counteragents",
                "projects"
              ],
              "default": "counteragents"
            }
          },
          {
            "name": "accrual_to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Fields vary by view and role.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "view": {
                          "type": "string"
                        },
                        "entity_id": {
                          "type": "string"
                        },
                        "entity_name": {
                          "type": "string"
                        },
                        "period": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        },
                        "totals": {
                          "type": "object",
                          "additionalProperties": true
                        }
                      },
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters or report loading failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing reports:read scope or insufficient role",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Entity not found in this workspace",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/timesheet-matrix": {
      "get": {
        "summary": "Time by day",
        "tags": [
          "Analytics"
        ],
        "description": "Daily minutes grouped by project, client or team. Defaults to the current UTC month. Team view requires owner/admin. Other views retain role-based data visibility. Requires reports:read, included in newly created read/full keys. Existing keys must be recreated to gain this scope. Read-only; HEAD has no response body.",
        "x-required-scopes": [
          "reports:read"
        ],
        "parameters": [
          {
            "name": "accrual_from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive start; current UTC month start by default."
          },
          {
            "name": "accrual_to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive end; current UTC month end by default."
          },
          {
            "name": "project_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated IDs within the key workspace."
          },
          {
            "name": "counteragent_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated IDs within the key workspace."
          },
          {
            "name": "user_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated IDs within the key workspace."
          },
          {
            "name": "view",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "project",
                "counteragent",
                "team"
              ],
              "default": "project"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Fields vary by view and role.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "can_manage_team": {
                          "type": "boolean"
                        },
                        "period": {
                          "type": "object",
                          "properties": {
                            "accrual_from": {
                              "type": "string",
                              "format": "date"
                            },
                            "accrual_to": {
                              "type": "string",
                              "format": "date"
                            },
                            "days": {
                              "type": "array",
                              "items": {
                                "type": "string",
                                "format": "date"
                              }
                            }
                          }
                        },
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "key": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              },
                              "total_minutes": {
                                "type": "number"
                              },
                              "day_minutes": {
                                "type": "object",
                                "additionalProperties": {
                                  "type": "number"
                                },
                                "description": "ISO date keys mapped to daily values."
                              }
                            }
                          }
                        },
                        "view": {
                          "type": "string"
                        },
                        "unique_counteragents_count": {
                          "type": "integer"
                        },
                        "holidays": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        }
                      },
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters or report loading failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing reports:read scope or insufficient role",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/moneysheet-matrix": {
      "get": {
        "summary": "Money by day",
        "tags": [
          "Analytics"
        ],
        "description": "Daily earned or received amounts grouped by entity. Defaults to earned and the current UTC month. Team view requires owner/admin. Other views retain role-based data visibility. Requires reports:read, included in newly created read/full keys. Existing keys must be recreated to gain this scope. Read-only; HEAD has no response body.",
        "x-required-scopes": [
          "reports:read"
        ],
        "parameters": [
          {
            "name": "accrual_from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive start; current UTC month start by default."
          },
          {
            "name": "accrual_to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive end; current UTC month end by default."
          },
          {
            "name": "project_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated IDs within the key workspace."
          },
          {
            "name": "counteragent_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated IDs within the key workspace."
          },
          {
            "name": "user_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated IDs within the key workspace."
          },
          {
            "name": "view",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "project",
                "counteragent",
                "team"
              ],
              "default": "project"
            }
          },
          {
            "name": "metric",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "earned",
                "received"
              ],
              "default": "earned"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Fields vary by view and role.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "can_manage_team": {
                          "type": "boolean"
                        },
                        "period": {
                          "type": "object",
                          "properties": {
                            "accrual_from": {
                              "type": "string",
                              "format": "date"
                            },
                            "accrual_to": {
                              "type": "string",
                              "format": "date"
                            },
                            "days": {
                              "type": "array",
                              "items": {
                                "type": "string",
                                "format": "date"
                              }
                            }
                          }
                        },
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "key": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              },
                              "total_cost": {
                                "type": "number"
                              },
                              "day_costs": {
                                "type": "object",
                                "additionalProperties": {
                                  "type": "number"
                                },
                                "description": "ISO date keys mapped to daily values."
                              }
                            }
                          }
                        },
                        "view": {
                          "type": "string"
                        },
                        "unique_counteragents_count": {
                          "type": "integer"
                        },
                        "holidays": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        }
                      },
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters or report loading failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing reports:read scope or insufficient role",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/dashboard/overview": {
      "get": {
        "summary": "Overview",
        "tags": [
          "Analytics"
        ],
        "description": "Time and money KPIs, trends, debtors, risks and recent entries within the caller’s data visibility. Client role receives 403. Other roles retain their existing data visibility. Requires reports:read, included in newly created read/full keys. Existing keys must be recreated to gain this scope. Read-only; HEAD has no response body.",
        "x-required-scopes": [
          "reports:read"
        ],
        "parameters": [
          {
            "name": "date_from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive start; no lower bound when omitted."
          },
          {
            "name": "date_to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive end; no upper bound when omitted."
          },
          {
            "name": "project_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated IDs within the key workspace."
          },
          {
            "name": "counteragent_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated IDs within the key workspace."
          },
          {
            "name": "user_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated IDs within the key workspace."
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Fields vary by view and role.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "can_manage_team": {
                          "type": "boolean"
                        },
                        "workspace_currency": {
                          "type": "string"
                        },
                        "period": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "filters": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "kpi": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "focus": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "risks": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "pulse": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "debtors": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "activity": {
                          "type": "object",
                          "additionalProperties": true
                        }
                      },
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters or report loading failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing reports:read scope or insufficient role",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/timesheet": {
      "get": {
        "summary": "List timesheet entries",
        "parameters": [
          { "name": "page", "in": "query", "schema": { "type": "integer", "minimum": 1 } },
          { "name": "page_size", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 500 } },
          { "name": "accrual_from", "in": "query", "schema": { "type": "string", "format": "date" } },
          { "name": "accrual_to", "in": "query", "schema": { "type": "string", "format": "date" } }
        ],
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SuccessEnvelope" } } } },
          "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      },
      "post": {
        "summary": "Create timesheet entry",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object" } } } },
        "responses": {
          "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SuccessEnvelope" } } } },
          "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    },
    "/api/timesheet/{id}": {
      "put": {
        "summary": "Update timesheet entry",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object" } } } },
        "responses": {
          "200": { "description": "OK" },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      },
      "delete": {
        "summary": "Delete timesheet entry",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": {
          "200": { "description": "Deleted" },
          "404": { "description": "Not found" }
        }
      }
    },
    "/api/payouts": {
      "get": { "summary": "List payouts", "responses": { "200": { "description": "OK" } } },
      "post": { "summary": "Create payout", "responses": { "201": { "description": "Created" } } }
    },
    "/api/payouts/{id}": {
      "put": {
        "summary": "Update payout",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": { "200": { "description": "OK" } }
      },
      "delete": {
        "summary": "Delete payout",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": { "200": { "description": "Deleted" } }
      }
    },
    "/api/projects": {
      "get": { "summary": "List projects", "responses": { "200": { "description": "OK" } } },
      "post": { "summary": "Create project", "responses": { "201": { "description": "Created" } } }
    },
    "/api/projects/{id}": {
      "put": {
        "summary": "Update project",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": { "200": { "description": "OK" } }
      },
      "delete": {
        "summary": "Delete project",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": { "200": { "description": "Deleted" } }
      }
    },
    "/api/counteragents": {
      "get": { "summary": "List counteragents", "responses": { "200": { "description": "OK" } } },
      "post": { "summary": "Create counteragent", "responses": { "201": { "description": "Created" } } }
    },
    "/api/counteragents/{id}": {
      "put": {
        "summary": "Update counteragent",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": { "200": { "description": "OK" } }
      },
      "delete": {
        "summary": "Delete counteragent",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": { "200": { "description": "Deleted" } }
      }
    },
    "/api/calendar": {
      "get": {
        "summary": "Monthly calendar data",
        "parameters": [{ "name": "month", "in": "query", "required": true, "schema": { "type": "string", "format": "date" } }],
        "responses": { "200": { "description": "OK" } }
      }
    },
    "/api/me/access": {
      "get": {
        "summary": "Get current access context",
        "responses": { "200": { "description": "OK" } }
      }
    },
    "/api/me/api-keys": {
      "get": { "summary": "List own API keys", "responses": { "200": { "description": "OK" } } },
      "post": {
        "summary": "Create API key",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object" } } } },
        "responses": { "201": { "description": "Created" } }
      }
    },
    "/api/me/api-keys/{id}": {
      "delete": {
        "summary": "Revoke API key",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": { "200": { "description": "OK" }, "404": { "description": "Not found" } }
      }
    }
  }
}
