{
  "openapi": "3.1.0",
  "info": {
    "title": "NoxConnect API",
    "version": "1.0.0",
    "description": "Capability-first API for understanding NoxConnect, discovering each Nox service, connecting providers, and configuring service setup.",
    "license": {
      "name": "Proprietary",
      "identifier": "LicenseRef-Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://app.noxhere.com",
      "description": "Hosted NoxConnect API"
    }
  ],
  "externalDocs": {
    "description": "NoxConnect developer documentation",
    "url": "/developers"
  },
  "security": [
    {
      "bearerAuth": [],
      "organization": []
    }
  ],
  "paths": {
    "/api/v1/services": {
      "get": {
        "operationId": "listNoxServices",
        "summary": "List Nox services, their focus, capabilities, and setup readiness",
        "responses": {
          "200": {
            "description": "Capability-first service catalog for the current organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceCatalog"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/V1Error"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/V1Error"
          },
          "429": {
            "$ref": "#/components/responses/V1Error"
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      }
    },
    "/api/v1/services/{service}": {
      "get": {
        "operationId": "getNoxService",
        "summary": "Get capabilities and setup readiness for one Nox service",
        "parameters": [
          {
            "$ref": "#/components/parameters/service"
          }
        ],
        "responses": {
          "200": {
            "description": "One service and its capability-first setup model",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceDetail"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/V1Error"
          },
          "401": {
            "$ref": "#/components/responses/V1Error"
          },
          "403": {
            "$ref": "#/components/responses/V1Error"
          },
          "404": {
            "$ref": "#/components/responses/V1Error"
          },
          "429": {
            "$ref": "#/components/responses/V1Error"
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      }
    },
    "/api/v1/services/{service}/setup": {
      "get": {
        "operationId": "getNoxServiceSetup",
        "summary": "Get setup state, sections, blockers, and capabilities for one service",
        "parameters": [
          {
            "$ref": "#/components/parameters/service"
          }
        ],
        "responses": {
          "200": {
            "description": "Service-scoped setup model",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceSetupDetail"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/V1Error"
          },
          "401": {
            "$ref": "#/components/responses/V1Error"
          },
          "403": {
            "$ref": "#/components/responses/V1Error"
          },
          "404": {
            "$ref": "#/components/responses/V1Error"
          },
          "429": {
            "$ref": "#/components/responses/V1Error"
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      }
    },
    "/api/v1/services/{service}/config": {
      "get": {
        "operationId": "getNoxServiceConfig",
        "summary": "Get the settings owned by one service",
        "description": "Returns an ETag and matching revision. Provider credentials are never included.",
        "parameters": [
          {
            "$ref": "#/components/parameters/service"
          }
        ],
        "responses": {
          "200": {
            "description": "Service-scoped configuration",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceConfig"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/V1Error"
          },
          "401": {
            "$ref": "#/components/responses/V1Error"
          },
          "403": {
            "$ref": "#/components/responses/V1Error"
          },
          "404": {
            "$ref": "#/components/responses/V1Error"
          },
          "429": {
            "$ref": "#/components/responses/V1Error"
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      },
      "patch": {
        "operationId": "patchNoxServiceConfig",
        "summary": "Partially update the settings owned by one service",
        "description": "Admin-only. Send the ETag from the latest GET as If-Match to prevent lost updates.",
        "parameters": [
          {
            "$ref": "#/components/parameters/service"
          },
          {
            "$ref": "#/components/parameters/ifMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ServiceConfigPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated service configuration",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceConfig"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/V1Error"
          },
          "401": {
            "$ref": "#/components/responses/V1Error"
          },
          "403": {
            "$ref": "#/components/responses/V1Error"
          },
          "409": {
            "$ref": "#/components/responses/V1Error"
          },
          "412": {
            "$ref": "#/components/responses/V1Error"
          },
          "422": {
            "$ref": "#/components/responses/V1Error"
          },
          "428": {
            "$ref": "#/components/responses/V1Error"
          },
          "429": {
            "$ref": "#/components/responses/V1Error"
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "admin",
        "x-change-safety": "conditional_write"
      }
    },
    "/api/v1/services/{service}/health": {
      "get": {
        "operationId": "getNoxServiceHealth",
        "summary": "Get service readiness and connection checks",
        "parameters": [
          {
            "$ref": "#/components/parameters/service"
          }
        ],
        "responses": {
          "200": {
            "description": "Current service health",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceHealth"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/V1Error"
          },
          "401": {
            "$ref": "#/components/responses/V1Error"
          },
          "403": {
            "$ref": "#/components/responses/V1Error"
          },
          "404": {
            "$ref": "#/components/responses/V1Error"
          },
          "429": {
            "$ref": "#/components/responses/V1Error"
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      }
    },
    "/api/integrations/setup": {
      "get": {
        "operationId": "getSetupPlan",
        "summary": "Get resumable setup state and next actions",
        "responses": {
          "200": {
            "description": "Current setup plan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SetupPlan"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      }
    },
    "/api/integrations/connections": {
      "get": {
        "operationId": "listConnections",
        "summary": "List provider connection state",
        "responses": {
          "200": {
            "description": "Connection registry",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      }
    },
    "/api/integrations/connections/{provider}/start": {
      "post": {
        "operationId": "startConnection",
        "summary": "Start a provider connection",
        "description": "Returns a userAction URL for human OAuth approval.",
        "parameters": [
          {
            "$ref": "#/components/parameters/provider"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StartConnectionBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Human action required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserAction"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "admin",
        "x-change-safety": "write_not_safe_to_retry"
      }
    },
    "/api/integrations/connections/{provider}/disconnect": {
      "post": {
        "operationId": "disconnectConnection",
        "summary": "Disconnect a provider",
        "parameters": [
          {
            "$ref": "#/components/parameters/provider"
          }
        ],
        "responses": {
          "200": {
            "description": "Disconnected",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "409": {
            "description": "Provider-managed disconnect",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "admin",
        "x-change-safety": "destructive"
      }
    },
    "/api/slack/connections/{connectionId}": {
      "patch": {
        "operationId": "assignSlackConnectionProject",
        "summary": "Assign a Slack workspace to a project",
        "description": "One workspace may be organization-wide. With multiple workspaces, every connection requires a project.",
        "parameters": [
          {
            "$ref": "#/components/parameters/connectionId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SlackProjectAssignment"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Assignment saved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "409": {
            "description": "Project is required while multiple workspaces exist",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "admin",
        "x-change-safety": "write_not_safe_to_retry"
      }
    },
    "/api/slack/channels": {
      "get": {
        "operationId": "listSlackChannels",
        "summary": "List channels visible to the connected Nox bot",
        "responses": {
          "200": {
            "description": "Slack channels",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      }
    },
    "/api/integrations/slack/routing": {
      "get": {
        "operationId": "getSlackRouting",
        "summary": "Get service-to-channel routing",
        "responses": {
          "200": {
            "description": "Current routes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "admin",
        "x-change-safety": "safe_read"
      },
      "patch": {
        "operationId": "patchSlackRouting",
        "summary": "Partially update service-to-channel routing",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RoutingPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated routes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "409": {
            "description": "Slack is disconnected or a channel is unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "admin",
        "x-change-safety": "write_not_safe_to_retry"
      }
    },
    "/api/integrations/slack/test": {
      "post": {
        "operationId": "testSlackRoute",
        "summary": "Send a test message through a saved or candidate route",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RouteTest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Test sent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "409": {
            "description": "No channel configured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "admin",
        "x-change-safety": "write_not_safe_to_retry"
      }
    },
    "/api/projects": {
      "get": {
        "operationId": "listProjects",
        "summary": "List active projects used by feature setup",
        "responses": {
          "200": {
            "description": "Projects",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      }
    },
    "/api/projects/{projectId}/archive": {
      "post": {
        "operationId": "archiveProject",
        "summary": "Stop tracking a project without deleting it",
        "x-required-role": "admin",
        "parameters": [
          {
            "$ref": "#/components/parameters/projectId"
          }
        ],
        "responses": {
          "200": {
            "description": "Project archived",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AdminRequired"
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "admin",
        "x-change-safety": "destructive"
      },
      "delete": {
        "operationId": "restoreProject",
        "summary": "Resume tracking an eligible project",
        "x-required-role": "admin",
        "parameters": [
          {
            "$ref": "#/components/parameters/projectId"
          }
        ],
        "responses": {
          "200": {
            "description": "Project restored",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AdminRequired"
          },
          "409": {
            "description": "GitHub repository is archived or retired",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "admin",
        "x-change-safety": "destructive"
      }
    },
    "/api/repos": {
      "get": {
        "operationId": "listRepositories",
        "summary": "List tracked repositories or include all discovered repositories",
        "parameters": [
          {
            "name": "include",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Repositories",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      }
    },
    "/api/repos/acknowledge": {
      "post": {
        "operationId": "acknowledgeRepositories",
        "summary": "Acknowledge newly discovered repositories",
        "x-required-role": "admin",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "repos"
                ],
                "properties": {
                  "repos": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Repositories acknowledged",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AdminRequired"
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "admin",
        "x-change-safety": "write_not_safe_to_retry"
      }
    },
    "/api/actors": {
      "get": {
        "operationId": "listActors",
        "summary": "List organization people and identity overlays",
        "responses": {
          "200": {
            "description": "Actors",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      }
    },
    "/api/actors/{actorId}": {
      "get": {
        "operationId": "getActor",
        "summary": "Get one organization identity",
        "parameters": [
          {
            "$ref": "#/components/parameters/actorId"
          }
        ],
        "responses": {
          "200": {
            "description": "Actor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "404": {
            "description": "Actor not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      },
      "patch": {
        "operationId": "updateActor",
        "summary": "Update an organization identity overlay",
        "x-required-role": "admin",
        "parameters": [
          {
            "$ref": "#/components/parameters/actorId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActorPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Actor updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AdminRequired"
          },
          "404": {
            "description": "Actor not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxConnect"
        ],
        "x-authentication": "admin",
        "x-change-safety": "write_not_safe_to_retry"
      }
    },
    "/api/features": {
      "get": {
        "operationId": "listFeatures",
        "summary": "List NoxTicket features",
        "parameters": [
          {
            "name": "state",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "open"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Features",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxTicket"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      },
      "post": {
        "operationId": "createFeature",
        "summary": "Create a GitHub-backed feature",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeatureCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Feature created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "412": {
            "description": "GitHub App is not installed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          },
          "422": {
            "description": "Invalid feature",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxTicket"
        ],
        "x-authentication": "member",
        "x-change-safety": "write_not_safe_to_retry"
      }
    },
    "/api/features/{number}": {
      "patch": {
        "operationId": "updateFeature",
        "summary": "Partially update a feature",
        "parameters": [
          {
            "$ref": "#/components/parameters/number"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeaturePatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Feature updated optimistically",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "404": {
            "description": "Feature not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          },
          "422": {
            "description": "Invalid feature update",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxTicket"
        ],
        "x-authentication": "member",
        "x-change-safety": "write_not_safe_to_retry"
      },
      "delete": {
        "operationId": "closeFeature",
        "summary": "Close a feature",
        "parameters": [
          {
            "$ref": "#/components/parameters/number"
          }
        ],
        "responses": {
          "200": {
            "description": "Feature closed optimistically",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "404": {
            "description": "Feature not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxTicket"
        ],
        "x-authentication": "member",
        "x-change-safety": "destructive"
      }
    },
    "/api/specs": {
      "get": {
        "operationId": "listSpecs",
        "summary": "List NoxTicket specifications",
        "parameters": [
          {
            "name": "featureNumber",
            "in": "query",
            "schema": {
              "type": "string",
              "description": "Positive feature number or unfiled"
            }
          },
          {
            "name": "include",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Specifications",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxTicket"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      },
      "post": {
        "operationId": "createSpec",
        "summary": "Create a specification",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SpecInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Specification created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "422": {
            "description": "Invalid specification",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxTicket"
        ],
        "x-authentication": "member",
        "x-change-safety": "write_not_safe_to_retry"
      }
    },
    "/api/specs/{specId}": {
      "get": {
        "operationId": "getSpec",
        "summary": "Get one specification",
        "parameters": [
          {
            "$ref": "#/components/parameters/specId"
          }
        ],
        "responses": {
          "200": {
            "description": "Specification",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "404": {
            "description": "Specification not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxTicket"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      },
      "patch": {
        "operationId": "updateSpec",
        "summary": "Partially update or relink a specification",
        "parameters": [
          {
            "$ref": "#/components/parameters/specId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SpecPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Specification updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "404": {
            "description": "Specification not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          },
          "422": {
            "description": "Invalid update",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxTicket"
        ],
        "x-authentication": "member",
        "x-change-safety": "write_not_safe_to_retry"
      }
    },
    "/api/specs/{specId}/archive": {
      "post": {
        "operationId": "archiveSpec",
        "summary": "Archive a specification",
        "x-required-role": "admin",
        "parameters": [
          {
            "$ref": "#/components/parameters/specId"
          }
        ],
        "responses": {
          "200": {
            "description": "Specification archived",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AdminRequired"
          }
        },
        "tags": [
          "NoxTicket"
        ],
        "x-authentication": "admin",
        "x-change-safety": "destructive"
      },
      "delete": {
        "operationId": "restoreSpec",
        "summary": "Restore a specification",
        "x-required-role": "admin",
        "parameters": [
          {
            "$ref": "#/components/parameters/specId"
          }
        ],
        "responses": {
          "200": {
            "description": "Specification restored",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AdminRequired"
          }
        },
        "tags": [
          "NoxTicket"
        ],
        "x-authentication": "admin",
        "x-change-safety": "destructive"
      }
    },
    "/api/specs/{specId}/attachments": {
      "get": {
        "operationId": "listSpecAttachments",
        "summary": "List specification attachments",
        "parameters": [
          {
            "$ref": "#/components/parameters/specId"
          }
        ],
        "responses": {
          "200": {
            "description": "Attachments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxTicket"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      },
      "post": {
        "operationId": "uploadSpecAttachment",
        "summary": "Upload a bounded specification attachment",
        "parameters": [
          {
            "$ref": "#/components/parameters/specId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Attachment uploaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "413": {
            "description": "Attachment too large",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          },
          "503": {
            "description": "Attachment storage unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxTicket"
        ],
        "x-authentication": "member",
        "x-change-safety": "write_not_safe_to_retry"
      }
    },
    "/api/specs/{specId}/attachments/{attachmentId}": {
      "get": {
        "operationId": "downloadSpecAttachment",
        "summary": "Download a specification attachment",
        "parameters": [
          {
            "$ref": "#/components/parameters/specId"
          },
          {
            "$ref": "#/components/parameters/attachmentId"
          }
        ],
        "responses": {
          "200": {
            "description": "Attachment bytes",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "404": {
            "description": "Attachment not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxTicket"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      },
      "delete": {
        "operationId": "deleteSpecAttachment",
        "summary": "Delete a specification attachment",
        "parameters": [
          {
            "$ref": "#/components/parameters/specId"
          },
          {
            "$ref": "#/components/parameters/attachmentId"
          }
        ],
        "responses": {
          "200": {
            "description": "Attachment deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "404": {
            "description": "Attachment not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxTicket"
        ],
        "x-authentication": "member",
        "x-change-safety": "destructive"
      }
    },
    "/api/v1/feed": {
      "get": {
        "operationId": "getNoxFeed",
        "summary": "Get normalized current work, posts, and release notes",
        "responses": {
          "200": {
            "description": "NoxFeed response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/V1Error"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/V1Error"
          },
          "429": {
            "$ref": "#/components/responses/V1Error"
          }
        },
        "parameters": [
          {
            "name": "mode",
            "in": "query",
            "required": false,
            "description": "Feed event mode",
            "schema": {
              "type": "string",
              "enum": [
                "opened",
                "merged",
                "release-notes"
              ],
              "default": "merged"
            }
          },
          {
            "name": "repo",
            "in": "query",
            "required": false,
            "description": "Repository name",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "actor",
            "in": "query",
            "required": false,
            "description": "GitHub login",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum events",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 25
            }
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "description": "Composite cursor returned by the previous page",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "tags": [
          "NoxFeed"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      }
    },
    "/api/issues": {
      "get": {
        "operationId": "listIssues",
        "summary": "List tracked GitHub issues",
        "responses": {
          "200": {
            "description": "Issues and aggregate metrics",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "parameters": [
          {
            "name": "state",
            "in": "query",
            "required": false,
            "description": "Issue state filter",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "repo",
            "in": "query",
            "required": false,
            "description": "Repository name",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Results per page",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 5000,
              "default": 30
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort field",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort_dir",
            "in": "query",
            "required": false,
            "description": "Sort direction",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            }
          }
        ],
        "tags": [
          "NoxFeed"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      }
    },
    "/api/issues/{repo}/{number}": {
      "get": {
        "operationId": "getIssue",
        "summary": "Get one tracked GitHub issue",
        "parameters": [
          {
            "$ref": "#/components/parameters/repo"
          },
          {
            "$ref": "#/components/parameters/number"
          }
        ],
        "responses": {
          "200": {
            "description": "Issue",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "404": {
            "description": "Issue or active repository not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxFeed"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      }
    },
    "/api/prs": {
      "get": {
        "operationId": "listPullRequests",
        "summary": "List tracked pull requests",
        "responses": {
          "200": {
            "description": "Pull requests and aggregate metrics",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "parameters": [
          {
            "name": "state",
            "in": "query",
            "required": false,
            "description": "Pull-request state filter",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "author",
            "in": "query",
            "required": false,
            "description": "GitHub author login",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "repo",
            "in": "query",
            "required": false,
            "description": "Repository name",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Results per page",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          }
        ],
        "tags": [
          "NoxFeed"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      }
    },
    "/api/prs/{repo}/{number}": {
      "get": {
        "operationId": "getPullRequest",
        "summary": "Get one tracked pull request",
        "parameters": [
          {
            "$ref": "#/components/parameters/repo"
          },
          {
            "$ref": "#/components/parameters/number"
          }
        ],
        "responses": {
          "200": {
            "description": "Pull request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "404": {
            "description": "Pull request or active repository not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxFeed"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      }
    },
    "/api/prs/close": {
      "post": {
        "operationId": "closePullRequest",
        "summary": "Close a pull request through GitHub",
        "x-required-role": "admin",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "repo",
                  "number"
                ],
                "properties": {
                  "repo": {
                    "type": "string"
                  },
                  "number": {
                    "type": "integer",
                    "minimum": 1
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Pull request closed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AdminRequired"
          }
        },
        "tags": [
          "NoxFeed"
        ],
        "x-authentication": "admin",
        "x-change-safety": "destructive"
      }
    },
    "/api/engineer-activity": {
      "get": {
        "operationId": "getEngineerActivity",
        "summary": "Get normalized monthly activity for one engineer",
        "parameters": [
          {
            "name": "login",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "month",
            "in": "query",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Engineer activity",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "400": {
            "description": "Invalid login or month",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxFeed"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      }
    },
    "/api/llm-settings": {
      "get": {
        "operationId": "getAiSettings",
        "summary": "Get organization AI execution settings",
        "x-required-role": "admin",
        "responses": {
          "200": {
            "description": "AI settings without credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AdminRequired"
          }
        },
        "tags": [
          "NoxFeed"
        ],
        "x-authentication": "admin",
        "x-change-safety": "safe_read"
      },
      "put": {
        "operationId": "putAiSettings",
        "summary": "Set organization AI execution mode",
        "x-required-role": "admin",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "mode"
                ],
                "properties": {
                  "mode": {
                    "type": "string",
                    "enum": [
                      "disabled",
                      "managed"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "AI settings saved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AdminRequired"
          },
          "503": {
            "description": "Managed AI is unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxFeed"
        ],
        "x-authentication": "admin",
        "x-change-safety": "write_not_safe_to_retry"
      }
    },
    "/api/spots/sites": {
      "get": {
        "operationId": "listNoxSpotSites",
        "summary": "List NoxSpot sites",
        "responses": {
          "200": {
            "description": "Sites",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxSpot"
        ],
        "x-authentication": "member",
        "x-change-safety": "safe_read"
      },
      "post": {
        "operationId": "createNoxSpotSite",
        "summary": "Create a NoxSpot site",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NoxSpotSiteCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Site created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxSpot"
        ],
        "x-authentication": "admin",
        "x-change-safety": "write_not_safe_to_retry"
      }
    },
    "/api/spots/sites/{siteId}": {
      "patch": {
        "operationId": "updateNoxSpotSite",
        "summary": "Update a NoxSpot site including its channel override",
        "parameters": [
          {
            "$ref": "#/components/parameters/siteId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NoxSpotSitePatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Site updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxSpot"
        ],
        "x-authentication": "admin",
        "x-change-safety": "write_not_safe_to_retry"
      },
      "delete": {
        "operationId": "deleteNoxSpotSite",
        "summary": "Delete a NoxSpot site and its screenshots",
        "parameters": [
          {
            "$ref": "#/components/parameters/siteId"
          }
        ],
        "responses": {
          "200": {
            "description": "Site deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxSpot"
        ],
        "x-authentication": "admin",
        "x-change-safety": "destructive"
      }
    },
    "/api/spots/sites/{siteId}/retry-deliveries": {
      "post": {
        "operationId": "retryNoxSpotDeliveries",
        "summary": "Retry blocked deliveries for one NoxSpot site",
        "x-required-role": "admin",
        "parameters": [
          {
            "$ref": "#/components/parameters/siteId"
          }
        ],
        "responses": {
          "200": {
            "description": "Eligible deliveries queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AdminRequired"
          },
          "404": {
            "description": "Site not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxSpot"
        ],
        "x-authentication": "admin",
        "x-change-safety": "write_not_safe_to_retry"
      }
    },
    "/api/spots/public/v1/sites/{siteId}/config": {
      "get": {
        "operationId": "getPublicNoxSpotConfig",
        "summary": "Get effective public widget configuration for the request origin",
        "security": [],
        "servers": [
          {
            "url": "https://api.noxspot.dev"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/siteId"
          }
        ],
        "responses": {
          "200": {
            "description": "Effective public widget configuration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "403": {
            "description": "Origin is not enabled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          },
          "404": {
            "description": "Site not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxSpot"
        ],
        "x-authentication": "public",
        "x-change-safety": "safe_read"
      }
    },
    "/api/spots/public/v1/reports": {
      "post": {
        "operationId": "submitPublicNoxSpotReport",
        "summary": "Submit a public NoxSpot capture",
        "security": [],
        "servers": [
          {
            "url": "https://api.noxspot.dev"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NoxSpotReport"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Capture queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "400": {
            "description": "Invalid capture",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          },
          "403": {
            "description": "Origin is not enabled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          },
          "413": {
            "description": "Request body too large",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          },
          "503": {
            "description": "Delivery unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "tags": [
          "NoxSpot"
        ],
        "x-authentication": "public",
        "x-change-safety": "write_not_safe_to_retry"
      }
    },
    "/api/spots/public/v1/errors": {
      "post": {
        "operationId": "submitPublicNoxSpotErrors",
        "summary": "Submit a bounded batch of automatic browser errors",
        "security": [],
        "servers": [
          {
            "url": "https://api.noxspot.dev"
          }
        ],
        "responses": {
          "200": {
            "description": "Errors queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "400": {
            "description": "Invalid error batch",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          },
          "403": {
            "description": "Origin is not enabled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          },
          "503": {
            "description": "Delivery unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NoxSpotErrorBatch"
              }
            }
          }
        },
        "tags": [
          "NoxSpot"
        ],
        "x-authentication": "public",
        "x-change-safety": "write_not_safe_to_retry"
      }
    },
    "/api/cues/sources": {
      "get": {
        "operationId": "listNoxCueSources",
        "summary": "List NoxCue sources and ingest keys",
        "responses": {
          "200": {
            "description": "Sources",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxCue"
        ],
        "x-authentication": "admin",
        "x-change-safety": "safe_read"
      },
      "post": {
        "operationId": "createNoxCueSource",
        "summary": "Create a NoxCue event source",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NoxCueSourceInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Source created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxCue"
        ],
        "x-authentication": "admin",
        "x-change-safety": "write_not_safe_to_retry"
      }
    },
    "/api/cues/sources/{sourceId}": {
      "put": {
        "operationId": "updateNoxCueSource",
        "summary": "Update a NoxCue event source",
        "parameters": [
          {
            "$ref": "#/components/parameters/sourceId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NoxCueSourceInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Source updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxCue"
        ],
        "x-authentication": "admin",
        "x-change-safety": "write_not_safe_to_retry"
      },
      "delete": {
        "operationId": "deleteNoxCueSource",
        "summary": "Delete a NoxCue source and revoke its keys",
        "parameters": [
          {
            "$ref": "#/components/parameters/sourceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Source deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxCue"
        ],
        "x-authentication": "admin",
        "x-change-safety": "destructive"
      }
    },
    "/api/cues/sources/{sourceId}/keys": {
      "post": {
        "operationId": "createNoxCueKey",
        "summary": "Create a one-time NoxCue ingest key",
        "description": "The key value is returned once. Do not log it.",
        "parameters": [
          {
            "$ref": "#/components/parameters/sourceId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "kind"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "kind": {
                    "const": "secret"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Key created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxCue"
        ],
        "x-authentication": "admin",
        "x-change-safety": "write_not_safe_to_retry"
      }
    },
    "/api/cues/sources/{sourceId}/keys/{keyId}": {
      "delete": {
        "operationId": "revokeNoxCueKey",
        "summary": "Revoke a NoxCue ingest key",
        "parameters": [
          {
            "$ref": "#/components/parameters/sourceId"
          },
          {
            "$ref": "#/components/parameters/keyId"
          }
        ],
        "responses": {
          "200": {
            "description": "Key revoked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxCue"
        ],
        "x-authentication": "admin",
        "x-change-safety": "destructive"
      }
    },
    "/api/cues/events": {
      "get": {
        "operationId": "listNoxCueEvents",
        "summary": "List recent NoxCue events and Slack delivery state",
        "responses": {
          "200": {
            "description": "Recent events",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "parameters": [
          {
            "name": "sourceId",
            "in": "query",
            "required": false,
            "description": "Optional source filter",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum recent events",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          }
        ],
        "tags": [
          "NoxCue"
        ],
        "x-authentication": "admin",
        "x-change-safety": "safe_read"
      }
    },
    "/api/cues/metrics": {
      "get": {
        "operationId": "getNoxCueDailyHealth",
        "summary": "Get NoxCue-derived daily user statistics and digest state",
        "parameters": [
          {
            "name": "sourceId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "NoxCue daily health",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonValue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "tags": [
          "NoxCue"
        ],
        "x-authentication": "admin",
        "x-change-safety": "safe_read"
      }
    },
    "/api/cues/public/v1/events": {
      "post": {
        "operationId": "ingestNoxCueEvent",
        "summary": "Submit one standardized NoxCue event through the stable NoxConnect gateway",
        "security": [
          {
            "noxCueKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/NoxCueUserEvent"
                  },
                  {
                    "$ref": "#/components/schemas/NoxCueError"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Event accepted and deduplicated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NoxCueIngestResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid bounded event",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          },
          "401": {
            "description": "Invalid ingest key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          },
          "413": {
            "description": "Payload exceeds 32 KiB",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          },
          "415": {
            "description": "Content-Type must be application/json",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                }
              }
            }
          }
        },
        "description": "Authenticated by X-Nox-Ingest-Key. Supply eventId or idempotencyKey when retrying error and feature events. User lifecycle facts are intrinsically deduplicated by source, user, type, and period.",
        "tags": [
          "NoxCue"
        ],
        "x-authentication": "ingest_key",
        "x-change-safety": "idempotent_with_event_key"
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "GitHub App user OAuth access token issued through a first-party Nox client. NoxConnect does not currently issue third-party client credentials."
      },
      "organization": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Org"
      },
      "noxCueKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Nox-Ingest-Key"
      }
    },
    "parameters": {
      "provider": {
        "name": "provider",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "enum": [
            "github",
            "slack"
          ]
        }
      },
      "connectionId": {
        "name": "connectionId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "projectId": {
        "name": "projectId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "sourceId": {
        "name": "sourceId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "siteId": {
        "name": "siteId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "keyId": {
        "name": "keyId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "actorId": {
        "name": "actorId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "specId": {
        "name": "specId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "attachmentId": {
        "name": "attachmentId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "repo": {
        "name": "repo",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "number": {
        "name": "number",
        "in": "path",
        "required": true,
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "service": {
        "name": "service",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "enum": [
            "noxconnect",
            "noxticket",
            "noxfeed",
            "noxspot",
            "noxcue"
          ]
        }
      },
      "ifMatch": {
        "name": "If-Match",
        "in": "header",
        "required": true,
        "description": "ETag returned by the latest service config GET",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid GitHub OAuth bearer token",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/LegacyError"
            }
          }
        }
      },
      "V1Error": {
        "description": "Coded API v1 error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiV1Error"
            }
          }
        }
      },
      "AdminRequired": {
        "description": "Organization administrator access is required",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/LegacyError"
            }
          }
        }
      }
    },
    "schemas": {
      "LegacyError": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "ApiV1Error": {
        "type": "object",
        "required": [
          "apiVersion",
          "error"
        ],
        "properties": {
          "apiVersion": {
            "const": 1
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "details": {}
            }
          }
        }
      },
      "ActorPatch": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "avatar_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "tone": {
            "type": [
              "string",
              "null"
            ]
          },
          "kind": {
            "type": [
              "string",
              "null"
            ]
          },
          "github_user_id": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "FeatureCreate": {
        "type": "object",
        "required": [
          "title"
        ],
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1
          },
          "status": {
            "type": "string"
          },
          "owners": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "specLinks": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "backlog": {
            "type": "boolean"
          }
        }
      },
      "FeaturePatch": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "owners": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "specLinks": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "backlog": {
            "type": "boolean"
          }
        }
      },
      "SpecInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "title"
        ],
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "description": {
            "type": "string",
            "maxLength": 20000
          },
          "featureNumber": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "links": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "label": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "SpecPatch": {
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "description": {
            "type": "string",
            "maxLength": 20000
          },
          "featureNumber": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "isPrimary": {
            "type": "boolean"
          },
          "links": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "label": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "ServiceCatalog": {
        "type": "object",
        "required": [
          "apiVersion",
          "organization",
          "canConfigure",
          "services"
        ],
        "properties": {
          "apiVersion": {
            "const": 1
          },
          "organization": {
            "$ref": "#/components/schemas/OrganizationReference"
          },
          "canConfigure": {
            "type": "boolean"
          },
          "services": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NoxService"
            }
          }
        }
      },
      "ServiceDetail": {
        "type": "object",
        "required": [
          "apiVersion",
          "organization",
          "canConfigure",
          "service"
        ],
        "properties": {
          "apiVersion": {
            "const": 1
          },
          "organization": {
            "$ref": "#/components/schemas/OrganizationReference"
          },
          "canConfigure": {
            "type": "boolean"
          },
          "service": {
            "$ref": "#/components/schemas/NoxService"
          }
        }
      },
      "ServiceSetupDetail": {
        "type": "object",
        "required": [
          "apiVersion",
          "organization",
          "canConfigure",
          "service",
          "state",
          "blockers",
          "connections",
          "sections",
          "capabilities",
          "links"
        ],
        "properties": {
          "apiVersion": {
            "const": 1
          },
          "organization": {
            "$ref": "#/components/schemas/OrganizationReference"
          },
          "canConfigure": {
            "type": "boolean"
          },
          "service": {
            "$ref": "#/components/schemas/ServiceId"
          },
          "state": {
            "type": "string",
            "enum": [
              "ready",
              "needs_setup",
              "disabled"
            ]
          },
          "blockers": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "connections": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ServiceConnectionRequirement"
            }
          },
          "sections": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "name",
                "capabilityIds",
                "state"
              ],
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "capabilityIds": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "state": {
                  "type": "string",
                  "enum": [
                    "ready",
                    "blocked",
                    "disabled"
                  ]
                }
              }
            }
          },
          "capabilities": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ServiceCapability"
            }
          },
          "links": {
            "$ref": "#/components/schemas/ServiceLinks"
          }
        }
      },
      "ServiceConfig": {
        "type": "object",
        "required": [
          "apiVersion",
          "organization",
          "service",
          "schemaVersion",
          "revision",
          "configuration",
          "config",
          "links"
        ],
        "properties": {
          "apiVersion": {
            "const": 1
          },
          "organization": {
            "$ref": "#/components/schemas/OrganizationReference"
          },
          "service": {
            "$ref": "#/components/schemas/ServiceId"
          },
          "schemaVersion": {
            "const": 1
          },
          "revision": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "configuration": {
            "type": "object",
            "required": [
              "mode",
              "writable",
              "writableFields"
            ],
            "properties": {
              "mode": {
                "type": "string",
                "enum": [
                  "service",
                  "resource"
                ]
              },
              "writable": {
                "type": "boolean"
              },
              "writableFields": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "config": {
            "type": "object",
            "description": "Shape depends on service. NoxSpot and NoxCue configuration is resource-scoped and linked from links.resources."
          },
          "links": {
            "$ref": "#/components/schemas/ServiceLinks"
          }
        }
      },
      "ServiceConfigPatch": {
        "anyOf": [
          {
            "$ref": "#/components/schemas/NoxConnectConfigPatch"
          },
          {
            "$ref": "#/components/schemas/NoxTicketConfigPatch"
          },
          {
            "$ref": "#/components/schemas/NoxFeedConfigPatch"
          },
          {
            "type": "object",
            "additionalProperties": false,
            "description": "NoxSpot and NoxCue have resource-scoped configuration; use links.resources."
          }
        ]
      },
      "NoxConnectConfigPatch": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "enabledServices": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "noxticket": {
                "type": "boolean"
              },
              "noxfeed": {
                "type": "boolean"
              },
              "noxspot": {
                "type": "boolean"
              },
              "noxcue": {
                "type": "boolean"
              }
            }
          },
          "newRepositoryPolicy": {
            "type": "string",
            "enum": [
              "include",
              "exclude"
            ]
          }
        }
      },
      "NoxTicketConfigPatch": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "featureRepository": {
            "type": [
              "string",
              "null"
            ],
            "minLength": 1,
            "maxLength": 100
          },
          "workflow": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "stages"
            ],
            "properties": {
              "stages": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "id",
                    "label",
                    "color"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "label": {
                      "type": "string"
                    },
                    "color": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "NoxFeedConfigPatch": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "projectScope": {
            "type": [
              "string",
              "null"
            ],
            "minLength": 1,
            "maxLength": 200,
            "description": "Null selects all projects; otherwise use the ID of an active project returned by GET /api/projects."
          },
          "releaseNotesPrompt": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 20000
          }
        }
      },
      "ServiceHealth": {
        "type": "object",
        "required": [
          "apiVersion",
          "organization",
          "service",
          "state",
          "checkedAt",
          "checks",
          "links"
        ],
        "properties": {
          "apiVersion": {
            "const": 1
          },
          "organization": {
            "$ref": "#/components/schemas/OrganizationReference"
          },
          "service": {
            "$ref": "#/components/schemas/ServiceId"
          },
          "state": {
            "type": "string",
            "enum": [
              "healthy",
              "degraded",
              "blocked",
              "disabled"
            ]
          },
          "checkedAt": {
            "type": "string",
            "format": "date-time"
          },
          "checks": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "state",
                "required"
              ],
              "properties": {
                "id": {
                  "type": "string"
                },
                "state": {
                  "type": "string",
                  "enum": [
                    "pass",
                    "warn",
                    "fail"
                  ]
                },
                "required": {
                  "type": "boolean"
                },
                "detail": {
                  "type": "string"
                }
              }
            }
          },
          "links": {
            "$ref": "#/components/schemas/ServiceLinks"
          }
        }
      },
      "ServiceId": {
        "type": "string",
        "enum": [
          "noxconnect",
          "noxticket",
          "noxfeed",
          "noxspot",
          "noxcue"
        ]
      },
      "ServiceLinks": {
        "type": "object",
        "required": [
          "self",
          "setup",
          "health",
          "resources"
        ],
        "properties": {
          "self": {
            "type": "string"
          },
          "setup": {
            "type": "string"
          },
          "health": {
            "type": "string"
          },
          "resources": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "OrganizationReference": {
        "type": "object",
        "required": [
          "login"
        ],
        "properties": {
          "login": {
            "type": "string"
          }
        }
      },
      "NoxService": {
        "type": "object",
        "required": [
          "id",
          "name",
          "kind",
          "focus",
          "description",
          "enabled",
          "setup",
          "capabilities",
          "links"
        ],
        "properties": {
          "id": {
            "type": "string",
            "enum": [
              "noxconnect",
              "noxticket",
              "noxfeed",
              "noxspot",
              "noxcue"
            ]
          },
          "name": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "foundation",
              "product"
            ]
          },
          "focus": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "setup": {
            "$ref": "#/components/schemas/ServiceSetup"
          },
          "capabilities": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ServiceCapability"
            }
          },
          "links": {
            "type": "object",
            "required": [
              "self",
              "setup",
              "config",
              "health"
            ],
            "properties": {
              "self": {
                "type": "string"
              },
              "setup": {
                "type": "string"
              },
              "config": {
                "type": "string"
              },
              "health": {
                "type": "string"
              }
            }
          }
        }
      },
      "ServiceSetup": {
        "type": "object",
        "required": [
          "state",
          "blockers",
          "connections",
          "sections"
        ],
        "properties": {
          "state": {
            "type": "string",
            "enum": [
              "ready",
              "needs_setup",
              "disabled"
            ]
          },
          "blockers": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "type",
                "provider",
                "state"
              ],
              "properties": {
                "type": {
                  "const": "connection"
                },
                "provider": {
                  "type": "string",
                  "enum": [
                    "github",
                    "slack"
                  ]
                },
                "state": {
                  "$ref": "#/components/schemas/ProviderConnectionState"
                }
              }
            }
          },
          "connections": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ServiceConnectionRequirement"
            }
          },
          "sections": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "name",
                "capabilityIds"
              ],
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "capabilityIds": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      },
      "ServiceConnectionRequirement": {
        "type": "object",
        "required": [
          "provider",
          "requirement",
          "state"
        ],
        "properties": {
          "provider": {
            "type": "string",
            "enum": [
              "github",
              "slack"
            ]
          },
          "requirement": {
            "type": "string",
            "enum": [
              "required",
              "optional"
            ]
          },
          "state": {
            "$ref": "#/components/schemas/ProviderConnectionState"
          }
        }
      },
      "ProviderConnectionState": {
        "type": "string",
        "enum": [
          "ready",
          "connecting",
          "disconnected",
          "degraded",
          "unavailable"
        ]
      },
      "ServiceCapability": {
        "type": "object",
        "required": [
          "id",
          "name",
          "description",
          "access",
          "state",
          "requires",
          "blockers",
          "operations"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "access": {
            "type": "string",
            "enum": [
              "member",
              "admin"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "ready",
              "blocked",
              "disabled"
            ]
          },
          "requires": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "github",
                "slack"
              ]
            }
          },
          "blockers": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "github",
                "slack"
              ]
            }
          },
          "operations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CapabilityOperation"
            }
          }
        }
      },
      "CapabilityOperation": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "method",
          "path",
          "authentication",
          "description"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "method": {
            "type": "string",
            "enum": [
              "GET",
              "POST",
              "PUT",
              "PATCH",
              "DELETE"
            ]
          },
          "path": {
            "type": "string"
          },
          "authentication": {
            "type": "string",
            "enum": [
              "member",
              "admin",
              "public",
              "ingest_key"
            ]
          },
          "description": {
            "type": "string"
          }
        }
      },
      "SetupPlan": {
        "type": "object",
        "required": [
          "apiVersion",
          "complete",
          "steps"
        ],
        "properties": {
          "apiVersion": {
            "type": "integer"
          },
          "complete": {
            "type": "boolean"
          },
          "steps": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/SetupStep"
            }
          }
        }
      },
      "SetupStep": {
        "type": "object",
        "required": [
          "title",
          "required",
          "state",
          "automatable"
        ],
        "properties": {
          "title": {
            "type": "string"
          },
          "required": {
            "type": "boolean"
          },
          "state": {
            "type": "string",
            "enum": [
              "available",
              "blocked",
              "complete"
            ]
          },
          "automatable": {
            "type": "boolean"
          },
          "action": {
            "type": [
              "object",
              "null"
            ]
          }
        }
      },
      "UserAction": {
        "type": "object",
        "required": [
          "provider",
          "status",
          "userAction",
          "resume"
        ],
        "properties": {
          "provider": {
            "type": "string"
          },
          "status": {
            "const": "requires_user_action"
          },
          "userAction": {
            "type": "object",
            "required": [
              "type",
              "url",
              "instructions"
            ],
            "properties": {
              "type": {
                "const": "open_url"
              },
              "url": {
                "type": "string",
                "format": "uri"
              },
              "instructions": {
                "type": "string"
              }
            }
          },
          "resume": {
            "type": "object"
          }
        }
      },
      "StartConnectionBody": {
        "type": "object",
        "properties": {
          "team": {
            "type": [
              "string",
              "null"
            ],
            "description": "Slack only: team (workspace) ID like T08B8C3E91N that pins Slack's authorize page to one workspace. An empty string or null leaves the workspace choice to Slack's picker. Omitted pins the organization's currently connected workspace so reconnects can't hop."
          },
          "projectId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Slack only: project assigned to a new workspace. Required when adding a second or later workspace."
          }
        }
      },
      "SlackProjectAssignment": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "projectId"
        ],
        "properties": {
          "projectId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Project to own this workspace. Null is allowed only while it is the organization's sole workspace."
          }
        }
      },
      "RoutingPatch": {
        "type": "object",
        "properties": {
          "routes": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "fallback": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "noxcue": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "noxticket": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "noxfeed_posts": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "noxfeed_release_notes": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "connections": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "fallback": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "noxcue": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "noxticket": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "noxfeed_posts": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "noxfeed_release_notes": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "description": "Slack connection IDs paired atomically with channel routes."
          }
        }
      },
      "RouteTest": {
        "type": "object",
        "required": [
          "route"
        ],
        "properties": {
          "route": {
            "type": "string",
            "enum": [
              "fallback",
              "noxcue",
              "noxticket",
              "noxfeed_posts",
              "noxfeed_release_notes"
            ]
          },
          "channelId": {
            "type": "string",
            "maxLength": 80,
            "description": "Optional candidate channel; otherwise uses saved routing and fallback."
          },
          "connectionId": {
            "type": "string",
            "maxLength": 80,
            "description": "Optional Slack workspace connection for the candidate channel."
          }
        }
      },
      "NoxSpotSiteCreate": {
        "type": "object",
        "required": [
          "name",
          "projectId"
        ],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 120
          },
          "projectId": {
            "type": "string"
          },
          "buttonColor": {
            "type": "string",
            "pattern": "^#[0-9a-fA-F]{6}$"
          },
          "buttonText": {
            "type": "string",
            "maxLength": 40
          },
          "widgetMode": {
            "type": "string",
            "enum": [
              "development",
              "release"
            ]
          },
          "autoErrorLogging": {
            "type": "boolean"
          }
        }
      },
      "NoxSpotSitePatch": {
        "type": "object",
        "minProperties": 1,
        "properties": {
          "slackChannelId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 80
          },
          "slackConnectionId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 120
          },
          "buttonColor": {
            "type": "string",
            "pattern": "^#[0-9a-fA-F]{6}$"
          },
          "buttonText": {
            "type": "string",
            "maxLength": 40
          },
          "widgetMode": {
            "type": "string",
            "enum": [
              "development",
              "release"
            ]
          },
          "autoErrorLogging": {
            "type": "boolean"
          },
          "environments": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "$ref": "#/components/schemas/NoxSpotEnvironment"
            }
          },
          "blocks": {
            "type": "array",
            "maxItems": 30,
            "items": {
              "$ref": "#/components/schemas/NoxSpotBlock"
            }
          }
        }
      },
      "NoxSpotEnvironment": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "url"
        ],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 60
          },
          "url": {
            "type": "string",
            "maxLength": 500
          },
          "buttonColor": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^#[0-9a-fA-F]{6}$"
          },
          "buttonText": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "widgetMode": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "development",
              "release",
              null
            ]
          },
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "NoxSpotBlock": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "type"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-z0-9][a-z0-9-]{0,119}$"
          },
          "type": {
            "type": "string",
            "enum": [
              "title",
              "description",
              "reporter",
              "contact_email",
              "custom_text",
              "custom_textarea",
              "custom_select",
              "element_picker",
              "metadata",
              "console_logs"
            ]
          },
          "label": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 120
          },
          "required": {
            "type": "boolean"
          },
          "options": {
            "type": "array",
            "maxItems": 30,
            "items": {
              "type": "string",
              "maxLength": 120
            }
          },
          "environments": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "string",
              "maxLength": 60
            }
          }
        }
      },
      "NoxSpotReport": {
        "type": "object",
        "required": [
          "siteId",
          "title"
        ],
        "properties": {
          "siteId": {
            "type": "string",
            "maxLength": 120
          },
          "title": {
            "type": "string",
            "maxLength": 256
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 10000
          },
          "reporter": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 100
          },
          "reporterEmail": {
            "type": [
              "string",
              "null"
            ],
            "format": "email",
            "maxLength": 254
          },
          "type": {
            "type": "string",
            "enum": [
              "bug",
              "feature",
              "feedback"
            ]
          },
          "environment": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 60
          },
          "screenshot": {
            "type": [
              "string",
              "null"
            ],
            "description": "Bounded PNG, JPEG, or WebP data URL"
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ]
          },
          "elements": {
            "type": [
              "array",
              "null"
            ],
            "maxItems": 50,
            "items": {
              "type": "object"
            }
          },
          "context": {
            "type": [
              "object",
              "null"
            ]
          },
          "blockValues": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {
              "type": "string"
            }
          },
          "rating": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "maximum": 5
          }
        }
      },
      "NoxCueSourceInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "enabled",
          "projectId",
          "timezone",
          "digestEnabled",
          "digestTimeLocal",
          "slackChannelId",
          "slackConnectionId"
        ],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 120
          },
          "enabled": {
            "type": "boolean"
          },
          "projectId": {
            "type": [
              "string",
              "null"
            ]
          },
          "timezone": {
            "type": "string",
            "description": "IANA timezone used for daily periods."
          },
          "digestEnabled": {
            "type": "boolean"
          },
          "digestTimeLocal": {
            "type": "string",
            "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$"
          },
          "slackChannelId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Source-specific Slack channel; null uses the organization fallback."
          },
          "slackConnectionId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Slack workspace connection for the selected channel."
          }
        }
      },
      "NoxCueError": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "title"
        ],
        "properties": {
          "version": {
            "const": 1,
            "default": 1
          },
          "type": {
            "const": "error.occurred"
          },
          "title": {
            "type": "string",
            "maxLength": 200
          },
          "message": {
            "type": "string",
            "maxLength": 2000
          },
          "idempotencyKey": {
            "type": "string",
            "maxLength": 200
          },
          "occurredAt": {
            "type": "string",
            "format": "date-time"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "data": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "errorCode": {
                "type": "string",
                "maxLength": 120
              },
              "fingerprint": {
                "type": "string",
                "maxLength": 200
              },
              "component": {
                "type": "string",
                "maxLength": 120
              },
              "environment": {
                "type": "string",
                "maxLength": 80
              },
              "affectedUser": {
                "type": "string",
                "maxLength": 200,
                "description": "Opaque identifier; NoxCue stores only its SHA-256 hash."
              },
              "fatal": {
                "type": "boolean",
                "default": false
              },
              "unhandled": {
                "type": "boolean",
                "default": false
              }
            }
          }
        }
      },
      "NoxCueUserEvent": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "userId"
        ],
        "properties": {
          "version": {
            "const": 1,
            "default": 1
          },
          "type": {
            "type": "string",
            "enum": [
              "user.registered",
              "user.active"
            ]
          },
          "userId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Stable app identifier; NoxCue stores only a source-scoped SHA-256 hash."
          },
          "occurredAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "JsonValue": {
        "description": "Legacy response whose stable typed schema has not yet been promoted into API v1.",
        "oneOf": [
          {
            "type": "null"
          },
          {
            "type": "boolean"
          },
          {
            "type": "number"
          },
          {
            "type": "string"
          },
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JsonValue"
            }
          },
          {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/JsonValue"
            }
          }
        ]
      },
      "NoxSpotErrorBatch": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "siteId",
          "errors"
        ],
        "properties": {
          "siteId": {
            "type": "string",
            "minLength": 1
          },
          "errors": {
            "type": "array",
            "minItems": 1,
            "maxItems": 10,
            "items": {
              "type": "object",
              "additionalProperties": true,
              "required": [
                "message"
              ],
              "properties": {
                "message": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 2000
                },
                "title": {
                  "type": "string",
                  "maxLength": 200
                },
                "url": {
                  "type": "string",
                  "format": "uri",
                  "maxLength": 2048
                }
              }
            }
          }
        }
      },
      "NoxCueIngestResponse": {
        "type": "object",
        "required": [
          "accepted",
          "stored",
          "eventId",
          "queued"
        ],
        "properties": {
          "accepted": {
            "const": true
          },
          "stored": {
            "type": "boolean"
          },
          "eventId": {
            "type": "string"
          },
          "queued": {
            "type": "boolean"
          },
          "duplicate": {
            "type": "boolean"
          },
          "notificationSuppressed": {
            "type": "boolean"
          },
          "period": {
            "type": "string"
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "NoxConnect",
      "description": "Connections, identity, repositories, projects, and shared delivery."
    },
    {
      "name": "NoxTicket",
      "description": "Features, workflow, specifications, and attachments."
    },
    {
      "name": "NoxFeed",
      "description": "Current work, engineering activity, and narratives."
    },
    {
      "name": "NoxSpot",
      "description": "Sites, website feedback capture, and screenshots."
    },
    {
      "name": "NoxCue",
      "description": "Event sources, ingest keys, customer-health events, and metrics."
    }
  ]
}
