{
  "components": {
    "responses": {
      "Conflict": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        },
        "description": "Duplicate"
      },
      "Forbidden": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        },
        "description": "The key lacks the required scope or access to the resource"
      },
      "NotFound": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        },
        "description": "No such resource in your company"
      },
      "RateLimited": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        },
        "description": "Per-key rate limit exceeded; honour Retry-After"
      },
      "Unauthorized": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        },
        "description": "Missing, malformed, revoked or expired API key"
      },
      "Validation": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        },
        "description": "Invalid input"
      }
    },
    "schemas": {
      "AcceptRequest": {
        "description": "Accept options",
        "properties": {
          "answer_id": {
            "description": "Answer to accept (default: most recent)",
            "type": "string"
          }
        },
        "type": "object"
      },
      "Answer": {
        "description": "An answer",
        "properties": {
          "api_key_id": {
            "description": "Answering API key",
            "type": [
              "string",
              "null"
            ]
          },
          "author_email": {
            "description": "Author email",
            "type": "string"
          },
          "author_name": {
            "description": "Author display name",
            "type": "string"
          },
          "body": {
            "description": "Text",
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "description": "Created",
            "format": "date-time",
            "type": "string"
          },
          "data": {
            "description": "Structured value (string, number, boolean, array…)"
          },
          "id": {
            "description": "Id",
            "type": "string"
          },
          "is_final": {
            "description": "Final answer",
            "type": "boolean"
          },
          "question_id": {
            "description": "Question",
            "type": "string"
          },
          "updated_at": {
            "description": "Updated",
            "format": "date-time",
            "type": "string"
          },
          "user_id": {
            "description": "Answering user",
            "type": [
              "string",
              "null"
            ]
          },
          "via": {
            "description": "Channel",
            "type": "string"
          }
        },
        "type": "object"
      },
      "AnswerRequest": {
        "description": "An answer",
        "properties": {
          "body": {
            "description": "Free text (required when data is absent)",
            "type": "string"
          },
          "data": {
            "description": "Structured value for choice/number/date/yes_no kinds"
          },
          "final": {
            "description": "Mark as the final answer (default true)",
            "type": "boolean"
          }
        },
        "type": "object"
      },
      "AskRequest": {
        "description": "A question to ask",
        "properties": {
          "assignee_emails": {
            "description": "Flat alternative to assignees.emails (array of strings; a single comma separated string is also accepted)",
            "oneOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "string"
              }
            ]
          },
          "assignee_user_ids": {
            "description": "Flat alternative to assignees.user_ids (array of strings; a single comma separated string is also accepted)",
            "oneOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "string"
              }
            ]
          },
          "assignees": {
            "description": "Respondents",
            "properties": {
              "channels": {
                "description": "Notification channels: web, email, slack (default: company setting) (array of strings; a single comma separated string is also accepted)",
                "oneOf": [
                  {
                    "items": {
                      "type": "string"
                    },
                    "type": "array"
                  },
                  {
                    "type": "string"
                  }
                ]
              },
              "emails": {
                "description": "Emails (unknown ones are invited as customer respondents) (array of strings; a single comma separated string is also accepted)",
                "oneOf": [
                  {
                    "items": {
                      "type": "string"
                    },
                    "type": "array"
                  },
                  {
                    "type": "string"
                  }
                ]
              },
              "organization": {
                "description": "Organisation for newly invited respondents",
                "type": "string"
              },
              "user_ids": {
                "description": "Existing user ids (array of strings; a single comma separated string is also accepted)",
                "oneOf": [
                  {
                    "items": {
                      "type": "string"
                    },
                    "type": "array"
                  },
                  {
                    "type": "string"
                  }
                ]
              }
            },
            "type": "object"
          },
          "body": {
            "description": "Longer prompt",
            "type": "string"
          },
          "channels": {
            "description": "Flat alternative to assignees.channels (array of strings; a single comma separated string is also accepted)",
            "oneOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "string"
              }
            ]
          },
          "draft": {
            "description": "Create as draft: no notifications until published",
            "type": "boolean"
          },
          "due_at": {
            "description": "Due date, RFC 3339 or YYYY-MM-DD",
            "type": "string"
          },
          "escalate_after_hours": {
            "description": "Hand the question to escalate_to if nobody answers within this many hours (0 = none; omit = company default)",
            "type": "integer"
          },
          "escalate_to": {
            "description": "Escalation contact: user id, email or name in the company",
            "type": "string"
          },
          "escalate_via": {
            "description": "Escalation delivery channels (email, slack); omit for the company default (array of strings; a single comma separated string is also accepted)",
            "oneOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "string"
              }
            ]
          },
          "kind": {
            "description": "Answer kind (default long_text)",
            "enum": [
              "text",
              "long_text",
              "yes_no",
              "single_choice",
              "multi_choice",
              "number",
              "date",
              "file"
            ],
            "type": "string"
          },
          "linear_issue": {
            "description": "Linear issue to tie the question to (VV-123 or issue URL); the issue receives the asked/answered trail as comments",
            "type": "string"
          },
          "options": {
            "description": "Choices; required (≥2) for single_choice / multi_choice (array of strings; a single comma separated string is also accepted)",
            "oneOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "string"
              }
            ]
          },
          "organization": {
            "description": "Organisation for newly invited respondents",
            "type": "string"
          },
          "priority": {
            "description": "Priority (default normal)",
            "enum": [
              "low",
              "normal",
              "high",
              "critical"
            ],
            "type": "string"
          },
          "product_id": {
            "description": "Product id (required unless supplied at the bulk level)",
            "type": "string"
          },
          "reminder_max": {
            "description": "Cap on automatic reminders for this question; omit for the company default",
            "type": "integer"
          },
          "reminder_minutes": {
            "description": "Automatic reminder cadence in minutes: 30..10080 (30 minutes to weekly), 0 = off, omit for the company default",
            "type": "integer"
          },
          "required": {
            "description": "Must be answered (default true)",
            "type": "boolean"
          },
          "section": {
            "description": "Grouping section",
            "type": "string"
          },
          "tags": {
            "description": "Tags (array of strings; a single comma separated string is also accepted)",
            "oneOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "string"
              }
            ]
          },
          "title": {
            "description": "Title (required, ≤500 chars)",
            "type": "string"
          }
        },
        "required": [
          "product_id",
          "title"
        ],
        "type": "object"
      },
      "AssignRequest": {
        "description": "Respondents to add",
        "properties": {
          "channels": {
            "description": "Channels: web, email, slack (array of strings; a single comma separated string is also accepted)",
            "oneOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "string"
              }
            ]
          },
          "emails": {
            "description": "Emails (unknown ones are invited) (array of strings; a single comma separated string is also accepted)",
            "oneOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "string"
              }
            ]
          },
          "names": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "email → display name for newly invited respondents",
            "type": "object"
          },
          "organization": {
            "description": "Organisation for newly invited respondents",
            "type": "string"
          },
          "user_ids": {
            "description": "Existing user ids (array of strings; a single comma separated string is also accepted)",
            "oneOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "string"
              }
            ]
          }
        },
        "type": "object"
      },
      "Assignment": {
        "description": "A respondent on a question",
        "properties": {
          "channels": {
            "description": "Comma separated channels (web, email, slack)",
            "type": "string"
          },
          "created_at": {
            "description": "Created",
            "format": "date-time",
            "type": "string"
          },
          "email": {
            "description": "Respondent email",
            "type": "string"
          },
          "id": {
            "description": "Id",
            "type": "string"
          },
          "kind": {
            "description": "User kind",
            "type": "string"
          },
          "last_reminded_at": {
            "description": "Last reminder",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "description": "Respondent name",
            "type": "string"
          },
          "notified_at": {
            "description": "First notified",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "organization": {
            "description": "Organisation",
            "type": "string"
          },
          "question_id": {
            "description": "Question",
            "type": "string"
          },
          "reminder_count": {
            "description": "Reminders sent",
            "type": "integer"
          },
          "status": {
            "description": "Status",
            "enum": [
              "pending",
              "notified",
              "answered",
              "declined"
            ],
            "type": "string"
          },
          "updated_at": {
            "description": "Updated",
            "format": "date-time",
            "type": "string"
          },
          "user_id": {
            "description": "User",
            "type": "string"
          }
        },
        "type": "object"
      },
      "BulkAskRequest": {
        "description": "Several questions",
        "properties": {
          "product_id": {
            "description": "Default product id for items that omit their own",
            "type": "string"
          },
          "questions": {
            "description": "Questions (max 200)",
            "items": {
              "allOf": [
                {
                  "$ref": "#/components/schemas/AskRequest"
                }
              ],
              "required": [
                "title"
              ]
            },
            "type": "array"
          }
        },
        "required": [
          "questions"
        ],
        "type": "object"
      },
      "BulkAskResponse": {
        "description": "Created questions",
        "properties": {
          "items": {
            "description": "Created",
            "items": {
              "$ref": "#/components/schemas/QuestionCreated"
            },
            "type": "array"
          },
          "total": {
            "description": "Count",
            "type": "integer"
          }
        },
        "required": [
          "items",
          "total"
        ],
        "type": "object"
      },
      "Comment": {
        "description": "A comment",
        "properties": {
          "author_name": {
            "description": "Author display name",
            "type": "string"
          },
          "body": {
            "description": "Text",
            "type": "string"
          },
          "created_at": {
            "description": "Created",
            "format": "date-time",
            "type": "string"
          },
          "id": {
            "description": "Id",
            "type": "string"
          },
          "question_id": {
            "description": "Question",
            "type": "string"
          },
          "user_id": {
            "description": "Author user",
            "type": [
              "string",
              "null"
            ]
          },
          "via": {
            "description": "Channel",
            "type": "string"
          }
        },
        "type": "object"
      },
      "CommentRequest": {
        "description": "A comment",
        "properties": {
          "body": {
            "description": "Text",
            "type": "string"
          }
        },
        "required": [
          "body"
        ],
        "type": "object"
      },
      "Credential": {
        "description": "Vault entry metadata (no secret)",
        "properties": {
          "company_id": {
            "description": "Company",
            "type": "string"
          },
          "created_at": {
            "description": "Created",
            "format": "date-time",
            "type": "string"
          },
          "creator_name": {
            "description": "Creator",
            "type": "string"
          },
          "id": {
            "description": "Id",
            "type": "string"
          },
          "kind": {
            "description": "Kind",
            "enum": [
              "password",
              "api_key",
              "ssh_key",
              "token",
              "certificate",
              "other"
            ],
            "type": "string"
          },
          "last_accessed_at": {
            "description": "Last reveal",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "description": "Name",
            "type": "string"
          },
          "product_id": {
            "description": "Product",
            "type": [
              "string",
              "null"
            ]
          },
          "product_name": {
            "description": "Product name",
            "type": "string"
          },
          "rotated_at": {
            "description": "Last secret rotation",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "updated_at": {
            "description": "Updated",
            "format": "date-time",
            "type": "string"
          },
          "url": {
            "description": "URL",
            "type": "string"
          },
          "username": {
            "description": "Username",
            "type": "string"
          }
        },
        "type": "object"
      },
      "CredentialPatch": {
        "description": "Vault edits",
        "properties": {
          "kind": {
            "description": "Kind",
            "enum": [
              "password",
              "api_key",
              "ssh_key",
              "token",
              "certificate",
              "other"
            ],
            "type": "string"
          },
          "name": {
            "description": "Name",
            "type": "string"
          },
          "notes": {
            "description": "Notes (omitted preserves, blank clears)",
            "type": "string"
          },
          "product_id": {
            "description": "Product (blank clears)",
            "type": "string"
          },
          "secret": {
            "description": "New secret (rotates)",
            "type": "string"
          },
          "url": {
            "description": "URL",
            "type": "string"
          },
          "username": {
            "description": "Username",
            "type": "string"
          }
        },
        "type": "object"
      },
      "CredentialRequest": {
        "description": "Vault entry",
        "properties": {
          "kind": {
            "description": "Kind (default password)",
            "enum": [
              "password",
              "api_key",
              "ssh_key",
              "token",
              "certificate",
              "other"
            ],
            "type": "string"
          },
          "name": {
            "description": "Name (required)",
            "type": "string"
          },
          "notes": {
            "description": "Notes (encrypted)",
            "type": "string"
          },
          "product_id": {
            "description": "Product",
            "type": "string"
          },
          "secret": {
            "description": "Secret (required)",
            "type": "string"
          },
          "url": {
            "description": "URL",
            "type": "string"
          },
          "username": {
            "description": "Username",
            "type": "string"
          }
        },
        "required": [
          "name",
          "secret"
        ],
        "type": "object"
      },
      "Document": {
        "description": "Document metadata",
        "properties": {
          "answer_id": {
            "description": "Answer",
            "type": [
              "string",
              "null"
            ]
          },
          "company_id": {
            "description": "Company",
            "type": "string"
          },
          "content_type": {
            "description": "MIME type",
            "type": "string"
          },
          "created_at": {
            "description": "Uploaded",
            "format": "date-time",
            "type": "string"
          },
          "credential_id": {
            "description": "Credential",
            "type": [
              "string",
              "null"
            ]
          },
          "filename": {
            "description": "Filename",
            "type": "string"
          },
          "id": {
            "description": "Id",
            "type": "string"
          },
          "product_id": {
            "description": "Product",
            "type": [
              "string",
              "null"
            ]
          },
          "question_id": {
            "description": "Question",
            "type": [
              "string",
              "null"
            ]
          },
          "question_number": {
            "description": "Question number",
            "type": [
              "integer",
              "null"
            ]
          },
          "sha256": {
            "description": "SHA-256 of the plaintext",
            "type": "string"
          },
          "size_bytes": {
            "description": "Size",
            "type": "integer"
          },
          "uploaded_by_api_key_id": {
            "description": "Uploading API key",
            "type": [
              "string",
              "null"
            ]
          },
          "uploaded_by_user_id": {
            "description": "Uploading user",
            "type": [
              "string",
              "null"
            ]
          },
          "uploaded_via": {
            "description": "Channel",
            "type": "string"
          },
          "uploader_name": {
            "description": "Uploader display name",
            "type": "string"
          }
        },
        "type": "object"
      },
      "DocumentUploadRequest": {
        "description": "JSON upload",
        "properties": {
          "answer_id": {
            "description": "Attach to answer",
            "type": "string"
          },
          "content_base64": {
            "description": "File bytes, base64 (required)",
            "type": "string"
          },
          "content_type": {
            "description": "MIME type (guessed from the extension when blank)",
            "type": "string"
          },
          "filename": {
            "description": "Filename (required)",
            "type": "string"
          },
          "product_id": {
            "description": "Attach to product",
            "type": "string"
          },
          "question_id": {
            "description": "Attach to question (also sets the product)",
            "type": "string"
          }
        },
        "required": [
          "filename",
          "content_base64"
        ],
        "type": "object"
      },
      "Error": {
        "description": "Error envelope",
        "properties": {
          "error": {
            "properties": {
              "code": {
                "description": "Code",
                "enum": [
                  "unauthorized",
                  "forbidden",
                  "not_found",
                  "validation",
                  "conflict",
                  "rate_limited",
                  "internal"
                ],
                "type": "string"
              },
              "message": {
                "description": "Readable message",
                "type": "string"
              }
            },
            "required": [
              "code",
              "message"
            ],
            "type": "object"
          }
        },
        "required": [
          "error"
        ],
        "type": "object"
      },
      "InviteRequest": {
        "description": "Respondent to invite",
        "properties": {
          "email": {
            "description": "Email (required)",
            "type": "string"
          },
          "name": {
            "description": "Name",
            "type": "string"
          },
          "organization": {
            "description": "Organisation",
            "type": "string"
          },
          "product_id": {
            "description": "Product to add them to",
            "type": "string"
          },
          "title": {
            "description": "Job title",
            "type": "string"
          }
        },
        "required": [
          "email"
        ],
        "type": "object"
      },
      "InviteResult": {
        "description": "Invite result",
        "properties": {
          "created": {
            "description": "A new account was created",
            "type": "boolean"
          },
          "user": {
            "$ref": "#/components/schemas/User"
          }
        },
        "type": "object"
      },
      "Me": {
        "description": "Calling key",
        "properties": {
          "all_scopes": {
            "description": "Key has the * scope",
            "type": "boolean"
          },
          "company": {
            "properties": {
              "id": {
                "description": "Id",
                "type": "string"
              },
              "name": {
                "description": "Name",
                "type": "string"
              },
              "slug": {
                "description": "Slug",
                "type": "string"
              },
              "timezone": {
                "description": "Timezone",
                "type": "string"
              }
            },
            "type": "object"
          },
          "created_at": {
            "description": "Created",
            "format": "date-time",
            "type": "string"
          },
          "expires_at": {
            "description": "Expires",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Key id",
            "type": "string"
          },
          "label": {
            "description": "Label",
            "type": "string"
          },
          "last_used_at": {
            "description": "Last used",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "prefix": {
            "description": "Display prefix",
            "type": "string"
          },
          "scopes": {
            "description": "Effective scopes",
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "MemberRequest": {
        "description": "Member to add",
        "properties": {
          "email": {
            "description": "Email of an existing user or a new customer respondent",
            "type": "string"
          },
          "name": {
            "description": "Name for a new respondent",
            "type": "string"
          },
          "organization": {
            "description": "Organisation for a new respondent",
            "type": "string"
          },
          "role": {
            "description": "Role (default by user kind)",
            "enum": [
              "owner",
              "collaborator",
              "respondent"
            ],
            "type": "string"
          },
          "title": {
            "description": "Job title for a new respondent",
            "type": "string"
          },
          "user_id": {
            "description": "Existing user id",
            "type": "string"
          }
        },
        "type": "object"
      },
      "MemberResult": {
        "description": "Membership result",
        "properties": {
          "product_id": {
            "description": "Product",
            "type": "string"
          },
          "role": {
            "description": "Role",
            "type": "string"
          },
          "user": {
            "$ref": "#/components/schemas/User"
          },
          "user_created": {
            "description": "A new respondent account was created",
            "type": "boolean"
          }
        },
        "type": "object"
      },
      "Product": {
        "description": "A product / engagement",
        "properties": {
          "answered_questions": {
            "description": "Answered + accepted + closed",
            "type": "integer"
          },
          "company_id": {
            "description": "Owning company",
            "type": "string"
          },
          "created_at": {
            "description": "Created",
            "format": "date-time",
            "type": "string"
          },
          "customer_org": {
            "description": "Customer organisation",
            "type": "string"
          },
          "description": {
            "description": "Description",
            "type": [
              "string",
              "null"
            ]
          },
          "due_at": {
            "description": "Target date",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Id",
            "type": "string"
          },
          "name": {
            "description": "Name",
            "type": "string"
          },
          "open_questions": {
            "description": "Open + draft questions",
            "type": "integer"
          },
          "owner_user_id": {
            "description": "Owner user id",
            "type": [
              "string",
              "null"
            ]
          },
          "slug": {
            "description": "URL slug",
            "type": "string"
          },
          "status": {
            "description": "Status",
            "enum": [
              "active",
              "on_hold",
              "completed",
              "archived"
            ],
            "type": "string"
          },
          "total_questions": {
            "description": "All questions",
            "type": "integer"
          },
          "updated_at": {
            "description": "Updated",
            "format": "date-time",
            "type": "string"
          }
        },
        "type": "object"
      },
      "ProductDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Product"
          },
          {
            "properties": {
              "members": {
                "description": "Members",
                "items": {
                  "$ref": "#/components/schemas/ProductMember"
                },
                "type": "array"
              },
              "progress_percent": {
                "description": "Share of questions answered/accepted/closed",
                "type": "integer"
              }
            },
            "type": "object"
          }
        ]
      },
      "ProductMember": {
        "description": "Product membership",
        "properties": {
          "added_at": {
            "description": "Added",
            "format": "date-time",
            "type": "string"
          },
          "email": {
            "description": "Email",
            "type": "string"
          },
          "kind": {
            "description": "User kind",
            "enum": [
              "internal",
              "customer"
            ],
            "type": "string"
          },
          "name": {
            "description": "Name",
            "type": "string"
          },
          "organization": {
            "description": "Organisation",
            "type": "string"
          },
          "product_id": {
            "description": "Product id",
            "type": "string"
          },
          "role": {
            "description": "Role",
            "enum": [
              "owner",
              "collaborator",
              "respondent"
            ],
            "type": "string"
          },
          "user_id": {
            "description": "User id",
            "type": "string"
          }
        },
        "type": "object"
      },
      "ProductRequest": {
        "description": "Product fields",
        "properties": {
          "customer_org": {
            "description": "Customer organisation",
            "type": "string"
          },
          "description": {
            "description": "Description",
            "type": "string"
          },
          "due_at": {
            "description": "Target date, RFC 3339 or YYYY-MM-DD (blank clears)",
            "type": "string"
          },
          "name": {
            "description": "Name (required on create)",
            "type": "string"
          },
          "owner_user_id": {
            "description": "Owner user id (blank clears)",
            "type": "string"
          },
          "status": {
            "description": "Status",
            "enum": [
              "active",
              "on_hold",
              "completed",
              "archived"
            ],
            "type": "string"
          }
        },
        "type": "object"
      },
      "Question": {
        "description": "A requirement question",
        "properties": {
          "accepted_answer_id": {
            "description": "Accepted answer id",
            "type": [
              "string",
              "null"
            ]
          },
          "answer_count": {
            "description": "Answers recorded",
            "type": "integer"
          },
          "answered_at": {
            "description": "First answered",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "asked_via": {
            "description": "Channel the question was asked from",
            "type": "string"
          },
          "assignees": {
            "description": "Comma separated assignee names",
            "type": "string"
          },
          "body": {
            "description": "Longer prompt (markdown/plain)",
            "type": [
              "string",
              "null"
            ]
          },
          "closed_at": {
            "description": "Closed",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "company_id": {
            "description": "Company",
            "type": "string"
          },
          "created_at": {
            "description": "Created",
            "format": "date-time",
            "type": "string"
          },
          "created_by_api_key_id": {
            "description": "Asking API key",
            "type": [
              "string",
              "null"
            ]
          },
          "created_by_user_id": {
            "description": "Asking user",
            "type": [
              "string",
              "null"
            ]
          },
          "due_at": {
            "description": "Due",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Id",
            "type": "string"
          },
          "kind": {
            "description": "Answer kind",
            "enum": [
              "text",
              "long_text",
              "yes_no",
              "single_choice",
              "multi_choice",
              "number",
              "date",
              "file"
            ],
            "type": "string"
          },
          "linear": {
            "description": "Linked Linear issue",
            "properties": {
              "id": {
                "description": "Linear issue id",
                "type": "string"
              },
              "key": {
                "description": "Identifier, e.g. VV-123",
                "type": "string"
              },
              "title": {
                "description": "Issue title",
                "type": "string"
              },
              "url": {
                "description": "Issue URL",
                "type": "string"
              }
            },
            "type": [
              "object",
              "null"
            ]
          },
          "link": {
            "description": "Respondent-facing URL",
            "type": "string"
          },
          "number": {
            "description": "Per-product sequence number",
            "type": "integer"
          },
          "options": {
            "description": "Choices for single/multi choice kinds",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "overdue": {
            "description": "Open and past due",
            "type": "boolean"
          },
          "priority": {
            "description": "Priority",
            "enum": [
              "low",
              "normal",
              "high",
              "critical"
            ],
            "type": "string"
          },
          "product_id": {
            "description": "Product",
            "type": "string"
          },
          "product_name": {
            "description": "Product name",
            "type": "string"
          },
          "ref": {
            "description": "Display reference, e.g. Q-12",
            "type": "string"
          },
          "reminder_minutes": {
            "description": "Automatic reminder cadence override in minutes (0 = off); absent = company default",
            "type": [
              "integer",
              "null"
            ]
          },
          "required": {
            "description": "Must be answered",
            "type": "boolean"
          },
          "section": {
            "description": "Grouping section",
            "type": "string"
          },
          "sort_order": {
            "description": "Manual ordering",
            "type": "integer"
          },
          "status": {
            "description": "Status",
            "enum": [
              "draft",
              "open",
              "answered",
              "accepted",
              "closed"
            ],
            "type": "string"
          },
          "tag_list": {
            "description": "Tags",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "tags": {
            "description": "Comma separated tags",
            "type": "string"
          },
          "title": {
            "description": "Title",
            "type": "string"
          },
          "updated_at": {
            "description": "Updated",
            "format": "date-time",
            "type": "string"
          }
        },
        "type": "object"
      },
      "QuestionCreated": {
        "description": "A created question",
        "properties": {
          "assignments": {
            "description": "Assignments made",
            "items": {
              "$ref": "#/components/schemas/Assignment"
            },
            "type": "array"
          },
          "question": {
            "$ref": "#/components/schemas/Question"
          }
        },
        "required": [
          "question",
          "assignments"
        ],
        "type": "object"
      },
      "QuestionDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Question"
          },
          {
            "properties": {
              "answers": {
                "description": "Answers, oldest first",
                "items": {
                  "$ref": "#/components/schemas/Answer"
                },
                "type": "array"
              },
              "assignments": {
                "description": "Respondents",
                "items": {
                  "$ref": "#/components/schemas/Assignment"
                },
                "type": "array"
              },
              "comments": {
                "description": "Comments, oldest first",
                "items": {
                  "$ref": "#/components/schemas/Comment"
                },
                "type": "array"
              },
              "documents": {
                "description": "Attached documents",
                "items": {
                  "$ref": "#/components/schemas/Document"
                },
                "type": "array"
              }
            },
            "type": "object"
          }
        ]
      },
      "QuestionPatch": {
        "description": "Question edits",
        "properties": {
          "body": {
            "description": "Body (blank clears)",
            "type": "string"
          },
          "due_at": {
            "description": "Due date (blank clears)",
            "type": "string"
          },
          "escalate_after_hours": {
            "description": "Escalation window in hours (0 clears)",
            "type": "integer"
          },
          "escalate_to": {
            "description": "Escalation contact: user id, email or name",
            "type": "string"
          },
          "escalate_via": {
            "description": "Escalation channels (email, slack) (array of strings; a single comma separated string is also accepted)",
            "oneOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "string"
              }
            ]
          },
          "kind": {
            "description": "Kind",
            "enum": [
              "text",
              "long_text",
              "yes_no",
              "single_choice",
              "multi_choice",
              "number",
              "date",
              "file"
            ],
            "type": "string"
          },
          "linear_issue": {
            "description": "Link a Linear issue (VV-123 or URL); blank unlinks",
            "type": "string"
          },
          "options": {
            "description": "Choices (array of strings; a single comma separated string is also accepted)",
            "oneOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "string"
              }
            ]
          },
          "priority": {
            "description": "Priority",
            "enum": [
              "low",
              "normal",
              "high",
              "critical"
            ],
            "type": "string"
          },
          "reminder_max": {
            "description": "Cap on automatic reminders (0 = company default)",
            "type": "integer"
          },
          "reminder_minutes": {
            "description": "Reminder cadence in minutes (30..10080), 0 = off, -1 = back to the company default",
            "type": "integer"
          },
          "required": {
            "description": "Required",
            "type": "boolean"
          },
          "section": {
            "description": "Section",
            "type": "string"
          },
          "tags": {
            "description": "Tags (array of strings; a single comma separated string is also accepted)",
            "oneOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "string"
              }
            ]
          },
          "title": {
            "description": "Title",
            "type": "string"
          }
        },
        "type": "object"
      },
      "RevealedCredential": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Credential"
          },
          {
            "properties": {
              "notes": {
                "description": "Decrypted notes",
                "type": "string"
              },
              "secret": {
                "description": "Decrypted secret",
                "type": "string"
              }
            },
            "type": "object"
          }
        ]
      },
      "User": {
        "description": "A user (internal staff or customer respondent)",
        "properties": {
          "active": {
            "description": "Active",
            "type": "boolean"
          },
          "company_id": {
            "description": "Company",
            "type": "string"
          },
          "created_at": {
            "description": "Created",
            "format": "date-time",
            "type": "string"
          },
          "email": {
            "description": "Email",
            "type": "string"
          },
          "id": {
            "description": "Id",
            "type": "string"
          },
          "kind": {
            "description": "Kind",
            "enum": [
              "internal",
              "customer"
            ],
            "type": "string"
          },
          "last_login_at": {
            "description": "Last login",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "login_method": {
            "description": "Login",
            "enum": [
              "password",
              "sso",
              "code"
            ],
            "type": "string"
          },
          "name": {
            "description": "Name",
            "type": "string"
          },
          "notify_email": {
            "description": "Email notifications",
            "type": "boolean"
          },
          "notify_slack": {
            "description": "Slack notifications",
            "type": "boolean"
          },
          "organization": {
            "description": "Organisation",
            "type": "string"
          },
          "role": {
            "description": "Role",
            "enum": [
              "super_admin",
              "admin",
              "member",
              "customer"
            ],
            "type": "string"
          },
          "slack_user_id": {
            "description": "Linked Slack user",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "Job title",
            "type": "string"
          },
          "updated_at": {
            "description": "Updated",
            "format": "date-time",
            "type": "string"
          }
        },
        "type": "object"
      }
    },
    "securitySchemes": {
      "apiKeyAuth": {
        "description": "API key header",
        "in": "header",
        "name": "X-API-Key",
        "type": "apiKey"
      },
      "bearerAuth": {
        "bearerFormat": "vg_…",
        "description": "API key as a bearer token",
        "scheme": "bearer",
        "type": "http"
      },
      "oauth2": {
        "description": "Browser sign-in for MCP/API clients (OAuth 2.1, PKCE, dynamic client registration at /oauth/register)",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "/oauth/authorize",
            "refreshUrl": "/oauth/token",
            "scopes": {
              "answers:read": "answers:read",
              "answers:write": "answers:write",
              "credentials:read": "credentials:read",
              "credentials:write": "credentials:write",
              "documents:read": "documents:read",
              "documents:write": "documents:write",
              "products:read": "products:read",
              "products:write": "products:write",
              "questions:read": "questions:read",
              "questions:write": "questions:write",
              "users:read": "users:read",
              "users:write": "users:write"
            },
            "tokenUrl": "/oauth/token"
          }
        },
        "type": "oauth2"
      }
    }
  },
  "info": {
    "description": "REST surface for AI agents and integrations: products, requirement questions, assignments, answers, comments, respondents, encrypted documents and the credential vault.\n\n**Authentication** — every endpoint except `GET /openapi.json` needs an API key (`vg_…`) sent as `Authorization: Bearer vg_…` or `X-API-Key: vg_…`. Keys carry scopes: `products:read`, `products:write`, `questions:read`, `questions:write`, `answers:read`, `answers:write`, `users:read`, `users:write`, `documents:read`, `documents:write`, `credentials:read`, `credentials:write` or `*`. A `\u003cresource\u003e:write` scope implies `\u003cresource\u003e:read`.\n\n**Tenancy** — a key only sees its own company; other companies' resources answer 404.\n\n**Errors** — `{\"error\":{\"code\":\"…\",\"message\":\"…\"}}` with codes `unauthorized` (401), `forbidden` (403), `not_found` (404), `validation` (400), `conflict` (409), `rate_limited` (429, with `Retry-After`), `internal` (500).\n\n**Lists** — `{\"items\":[…],\"total\":n,\"page\":p,\"size\":s,\"pages\":k}`; `page` is 1-based, `size` defaults to 25 (max 200).\n\n**Times** — RFC 3339. Inputs also accept `YYYY-MM-DD` (midnight UTC). Outputs are UTC.\n\nThe same operations are available to MCP clients at `POST /mcp` (Streamable HTTP, stateless) with the same keys and scopes.",
    "title": "IQV Gather API",
    "version": "1.0.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/credentials": {
      "get": {
        "description": "Vault entries — metadata only, never secrets.\n\nRequires scope `credentials:read`.",
        "parameters": [
          {
            "description": "Only this product",
            "in": "query",
            "name": "product_id",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Search name / username / url",
            "in": "query",
            "name": "q",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Page number (1-based)",
            "in": "query",
            "name": "page",
            "schema": {
              "default": 1,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Page size (max 200)",
            "in": "query",
            "name": "size",
            "schema": {
              "default": 25,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "description": "Paginated list",
                  "properties": {
                    "items": {
                      "items": {
                        "$ref": "#/components/schemas/Credential"
                      },
                      "type": "array"
                    },
                    "page": {
                      "description": "Current page (1-based)",
                      "type": "integer"
                    },
                    "pages": {
                      "description": "Page count",
                      "type": "integer"
                    },
                    "size": {
                      "description": "Page size",
                      "type": "integer"
                    },
                    "total": {
                      "description": "Total matching items",
                      "type": "integer"
                    }
                  },
                  "required": [
                    "items",
                    "total",
                    "page",
                    "size",
                    "pages"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Credentials"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "List credentials",
        "tags": [
          "credentials"
        ],
        "x-required-scope": "credentials:read"
      },
      "post": {
        "description": "Seals the secret (and notes) with the KMS envelope and stores the entry.\n\nRequires scope `credentials:write`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CredentialRequest"
              }
            }
          },
          "description": "`name` and `secret` are required.",
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Credential"
                }
              }
            },
            "description": "Credential"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Create a credential",
        "tags": [
          "credentials"
        ],
        "x-required-scope": "credentials:write"
      }
    },
    "/credentials/{id}": {
      "delete": {
        "description": "Hides the entry.\n\nRequires scope `credentials:write`.",
        "parameters": [
          {
            "description": "Credential id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Delete a credential",
        "tags": [
          "credentials"
        ],
        "x-required-scope": "credentials:write"
      },
      "get": {
        "description": "Metadata only; use `/reveal` for the secret.\n\nRequires scope `credentials:read`.",
        "parameters": [
          {
            "description": "Credential id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Credential"
                }
              }
            },
            "description": "Credential"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Get credential metadata",
        "tags": [
          "credentials"
        ],
        "x-required-scope": "credentials:read"
      },
      "patch": {
        "description": "Partial update. Supplying `secret` rotates the stored value; omitted notes are preserved.\n\nRequires scope `credentials:write`.",
        "parameters": [
          {
            "description": "Credential id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CredentialPatch"
              }
            }
          },
          "description": "Fields to change.",
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Credential"
                }
              }
            },
            "description": "Credential"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Update a credential",
        "tags": [
          "credentials"
        ],
        "x-required-scope": "credentials:write"
      }
    },
    "/credentials/{id}/reveal": {
      "get": {
        "description": "Decrypts the secret and notes. Every reveal is written to the audit log.\n\nRequires scope `credentials:read`.",
        "parameters": [
          {
            "description": "Credential id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RevealedCredential"
                }
              }
            },
            "description": "Decrypted credential"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Reveal a credential",
        "tags": [
          "credentials"
        ],
        "x-required-scope": "credentials:read"
      }
    },
    "/documents": {
      "get": {
        "description": "Document metadata, newest first.\n\nRequires scope `documents:read`.",
        "parameters": [
          {
            "description": "Only this product",
            "in": "query",
            "name": "product_id",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Only this question",
            "in": "query",
            "name": "question_id",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Only this answer",
            "in": "query",
            "name": "answer_id",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Filename contains",
            "in": "query",
            "name": "q",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Page number (1-based)",
            "in": "query",
            "name": "page",
            "schema": {
              "default": 1,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Page size (max 200)",
            "in": "query",
            "name": "size",
            "schema": {
              "default": 25,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "description": "Paginated list",
                  "properties": {
                    "items": {
                      "items": {
                        "$ref": "#/components/schemas/Document"
                      },
                      "type": "array"
                    },
                    "page": {
                      "description": "Current page (1-based)",
                      "type": "integer"
                    },
                    "pages": {
                      "description": "Page count",
                      "type": "integer"
                    },
                    "size": {
                      "description": "Page size",
                      "type": "integer"
                    },
                    "total": {
                      "description": "Total matching items",
                      "type": "integer"
                    }
                  },
                  "required": [
                    "items",
                    "total",
                    "page",
                    "size",
                    "pages"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Documents"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "List documents",
        "tags": [
          "documents"
        ],
        "x-required-scope": "documents:read"
      },
      "post": {
        "description": "Stores a file encrypted at rest. Send `multipart/form-data` (`file` plus optional `product_id`, `question_id`, `answer_id`, `content_type`) or JSON with `content_base64`.\n\nRequires scope `documents:write`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentUploadRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "answer_id": {
                    "description": "Answer id",
                    "type": "string"
                  },
                  "content_type": {
                    "description": "Override the detected content type",
                    "type": "string"
                  },
                  "file": {
                    "description": "The file",
                    "format": "binary",
                    "type": "string"
                  },
                  "filename": {
                    "description": "Override the filename",
                    "type": "string"
                  },
                  "product_id": {
                    "description": "Product id",
                    "type": "string"
                  },
                  "question_id": {
                    "description": "Question id",
                    "type": "string"
                  }
                },
                "required": [
                  "file"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Document"
                }
              }
            },
            "description": "Document"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Upload a document",
        "tags": [
          "documents"
        ],
        "x-required-scope": "documents:write"
      }
    },
    "/documents/{id}": {
      "delete": {
        "description": "Removes the object and hides the record.\n\nRequires scope `documents:write`.",
        "parameters": [
          {
            "description": "Document id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Delete a document",
        "tags": [
          "documents"
        ],
        "x-required-scope": "documents:write"
      },
      "get": {
        "description": "Streams the decrypted bytes with `Content-Disposition: attachment`. The download is audited.\n\nRequires scope `documents:read`.",
        "parameters": [
          {
            "description": "Document id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "description": "",
                  "format": "binary",
                  "type": "string"
                }
              }
            },
            "description": "File bytes"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Download a document",
        "tags": [
          "documents"
        ],
        "x-required-scope": "documents:read"
      }
    },
    "/documents/{id}/meta": {
      "get": {
        "description": "Metadata only (no bytes, not audited as a download).\n\nRequires scope `documents:read`.",
        "parameters": [
          {
            "description": "Document id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Document"
                }
              }
            },
            "description": "Document"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Get document metadata",
        "tags": [
          "documents"
        ],
        "x-required-scope": "documents:read"
      }
    },
    "/me": {
      "get": {
        "description": "Returns the key's label, company and effective scopes. Useful as a connectivity check.",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Me"
                }
              }
            },
            "description": "Key description"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Describe the calling key",
        "tags": [
          "meta"
        ]
      }
    },
    "/openapi.json": {
      "get": {
        "description": "The OpenAPI 3.1 description of the API. No authentication required.",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "description": "OpenAPI document"
          }
        },
        "security": [],
        "summary": "This document",
        "tags": [
          "meta"
        ]
      }
    },
    "/products": {
      "get": {
        "description": "Products (engagements) in your company, active first.\n\nRequires scope `products:read`.",
        "parameters": [
          {
            "description": "Search name / customer organisation",
            "in": "query",
            "name": "q",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Filter by status",
            "in": "query",
            "name": "status",
            "schema": {
              "enum": [
                "active",
                "on_hold",
                "completed",
                "archived"
              ],
              "type": "string"
            }
          },
          {
            "description": "Page number (1-based)",
            "in": "query",
            "name": "page",
            "schema": {
              "default": 1,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Page size (max 200)",
            "in": "query",
            "name": "size",
            "schema": {
              "default": 25,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "description": "Paginated list",
                  "properties": {
                    "items": {
                      "items": {
                        "$ref": "#/components/schemas/Product"
                      },
                      "type": "array"
                    },
                    "page": {
                      "description": "Current page (1-based)",
                      "type": "integer"
                    },
                    "pages": {
                      "description": "Page count",
                      "type": "integer"
                    },
                    "size": {
                      "description": "Page size",
                      "type": "integer"
                    },
                    "total": {
                      "description": "Total matching items",
                      "type": "integer"
                    }
                  },
                  "required": [
                    "items",
                    "total",
                    "page",
                    "size",
                    "pages"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Products"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "List products",
        "tags": [
          "products"
        ],
        "x-required-scope": "products:read"
      },
      "post": {
        "description": "Creates a product (the thing requirements are gathered for).\n\nRequires scope `products:write`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductRequest"
              }
            }
          },
          "description": "Product fields; `name` is required.",
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            },
            "description": "Created product"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Create a product",
        "tags": [
          "products"
        ],
        "x-required-scope": "products:write"
      }
    },
    "/products/{id}": {
      "get": {
        "description": "The product with its members and question counters.\n\nRequires scope `products:read`.",
        "parameters": [
          {
            "description": "Product id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductDetail"
                }
              }
            },
            "description": "Product with members"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Get a product",
        "tags": [
          "products"
        ],
        "x-required-scope": "products:read"
      },
      "patch": {
        "description": "Partial update; only supplied fields change.\n\nRequires scope `products:write`.",
        "parameters": [
          {
            "description": "Product id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductRequest"
              }
            }
          },
          "description": "Fields to change.",
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            },
            "description": "Updated product"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Update a product",
        "tags": [
          "products"
        ],
        "x-required-scope": "products:write"
      }
    },
    "/products/{id}/members": {
      "post": {
        "description": "Adds an existing user (by `user_id` or `email`) or invites a new customer respondent (by `email`) to the product.\n\nRequires scope `users:write`.",
        "parameters": [
          {
            "description": "Product id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MemberRequest"
              }
            }
          },
          "description": "`user_id` or `email` is required.",
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemberResult"
                }
              }
            },
            "description": "Membership"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Add a product member",
        "tags": [
          "users"
        ],
        "x-required-scope": "users:write"
      }
    },
    "/questions": {
      "get": {
        "description": "Questions in your company with filters. `status` accepts a comma separated list. `unanswered=true` is shorthand for `status=open`.\n\nRequires scope `questions:read`.",
        "parameters": [
          {
            "description": "Only this product",
            "in": "query",
            "name": "product_id",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Comma separated statuses: draft, open, answered, accepted, closed",
            "in": "query",
            "name": "status",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Only questions assigned to this user",
            "in": "query",
            "name": "assignee_id",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Search title / body / tags",
            "in": "query",
            "name": "q",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Exact section",
            "in": "query",
            "name": "section",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Priority",
            "in": "query",
            "name": "priority",
            "schema": {
              "enum": [
                "low",
                "normal",
                "high",
                "critical"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only open questions past their due date",
            "in": "query",
            "name": "overdue",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "Only open questions",
            "in": "query",
            "name": "unanswered",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "Only questions updated after this RFC 3339 time",
            "in": "query",
            "name": "updated_after",
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "description": "Page number (1-based)",
            "in": "query",
            "name": "page",
            "schema": {
              "default": 1,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Page size (max 200)",
            "in": "query",
            "name": "size",
            "schema": {
              "default": 25,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "description": "Paginated list",
                  "properties": {
                    "items": {
                      "items": {
                        "$ref": "#/components/schemas/Question"
                      },
                      "type": "array"
                    },
                    "page": {
                      "description": "Current page (1-based)",
                      "type": "integer"
                    },
                    "pages": {
                      "description": "Page count",
                      "type": "integer"
                    },
                    "size": {
                      "description": "Page size",
                      "type": "integer"
                    },
                    "total": {
                      "description": "Total matching items",
                      "type": "integer"
                    }
                  },
                  "required": [
                    "items",
                    "total",
                    "page",
                    "size",
                    "pages"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Questions"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "List questions",
        "tags": [
          "questions"
        ],
        "x-required-scope": "questions:read"
      },
      "post": {
        "description": "Send a single `AskRequest` object, or `{\"product_id\": …, \"questions\": [AskRequest, …]}` to create several (max 200). Assignees named by email are invited as customer respondents when unknown and notified over the chosen channels unless `draft` is true. A partial bulk failure returns the error plus a `created` array of what succeeded.\n\nRequires scope `questions:write`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/AskRequest"
                  },
                  {
                    "$ref": "#/components/schemas/BulkAskRequest"
                  }
                ]
              }
            }
          },
          "description": "One question or a bulk envelope.",
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/QuestionCreated"
                    },
                    {
                      "$ref": "#/components/schemas/BulkAskResponse"
                    }
                  ]
                }
              }
            },
            "description": "Created question(s)"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Ask one or many questions",
        "tags": [
          "questions"
        ],
        "x-required-scope": "questions:write"
      }
    },
    "/questions/{id}": {
      "get": {
        "description": "The question with its assignments, answers, comments and documents.\n\nRequires scope `questions:read`.",
        "parameters": [
          {
            "description": "Question id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuestionDetail"
                }
              }
            },
            "description": "Question detail"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Get a question",
        "tags": [
          "questions"
        ],
        "x-required-scope": "questions:read"
      },
      "patch": {
        "description": "Edits title, body, kind, options, section, priority, required, due_at or tags. Status changes use the accept/close/reopen/publish actions.\n\nRequires scope `questions:write`.",
        "parameters": [
          {
            "description": "Question id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuestionPatch"
              }
            }
          },
          "description": "Fields to change.",
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Question"
                }
              }
            },
            "description": "The question"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Update a question",
        "tags": [
          "questions"
        ],
        "x-required-scope": "questions:write"
      }
    },
    "/questions/{id}/accept": {
      "post": {
        "description": "Marks the question accepted. `answer_id` selects the accepted answer; when omitted the most recent answer is used.\n\nRequires scope `questions:write`.",
        "parameters": [
          {
            "description": "Question id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AcceptRequest"
              }
            }
          },
          "required": false
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Question"
                }
              }
            },
            "description": "The question"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Accept an answer",
        "tags": [
          "questions"
        ],
        "x-required-scope": "questions:write"
      }
    },
    "/questions/{id}/answers": {
      "get": {
        "description": "Answers to the question, oldest first.\n\nRequires scope `answers:read`.",
        "parameters": [
          {
            "description": "Question id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "description": "Paginated list",
                  "properties": {
                    "items": {
                      "items": {
                        "$ref": "#/components/schemas/Answer"
                      },
                      "type": "array"
                    },
                    "page": {
                      "description": "Current page (1-based)",
                      "type": "integer"
                    },
                    "pages": {
                      "description": "Page count",
                      "type": "integer"
                    },
                    "size": {
                      "description": "Page size",
                      "type": "integer"
                    },
                    "total": {
                      "description": "Total matching items",
                      "type": "integer"
                    }
                  },
                  "required": [
                    "items",
                    "total",
                    "page",
                    "size",
                    "pages"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Answers"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "List answers",
        "tags": [
          "answers"
        ],
        "x-required-scope": "answers:read"
      },
      "post": {
        "description": "Records an answer on behalf of the calling agent. `data` holds the structured value for choice/number/date/yes_no kinds; `body` is free text (required when `data` is absent).\n\nRequires scope `answers:write`.",
        "parameters": [
          {
            "description": "Question id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AnswerRequest"
              }
            }
          },
          "description": "The answer.",
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Answer"
                }
              }
            },
            "description": "Answer"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Record an answer",
        "tags": [
          "answers"
        ],
        "x-required-scope": "answers:write"
      }
    },
    "/questions/{id}/assign": {
      "post": {
        "description": "Adds respondents by user id and/or email (unknown emails are invited as customer respondents) and notifies them.\n\nRequires scope `questions:write`.",
        "parameters": [
          {
            "description": "Question id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssignRequest"
              }
            }
          },
          "description": "Respondents and channels.",
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "description": "Paginated list",
                  "properties": {
                    "items": {
                      "items": {
                        "$ref": "#/components/schemas/Assignment"
                      },
                      "type": "array"
                    },
                    "page": {
                      "description": "Current page (1-based)",
                      "type": "integer"
                    },
                    "pages": {
                      "description": "Page count",
                      "type": "integer"
                    },
                    "size": {
                      "description": "Page size",
                      "type": "integer"
                    },
                    "total": {
                      "description": "Total matching items",
                      "type": "integer"
                    }
                  },
                  "required": [
                    "items",
                    "total",
                    "page",
                    "size",
                    "pages"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Assignments"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Assign respondents",
        "tags": [
          "questions"
        ],
        "x-required-scope": "questions:write"
      }
    },
    "/questions/{id}/close": {
      "post": {
        "description": "Closes the question without accepting an answer.\n\nRequires scope `questions:write`.",
        "parameters": [
          {
            "description": "Question id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Question"
                }
              }
            },
            "description": "The question"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Close a question",
        "tags": [
          "questions"
        ],
        "x-required-scope": "questions:write"
      }
    },
    "/questions/{id}/comments": {
      "post": {
        "description": "Adds discussion to the question thread.\n\nRequires scope `questions:write`.",
        "parameters": [
          {
            "description": "Question id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommentRequest"
              }
            }
          },
          "description": "Comment body.",
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Comment"
                }
              }
            },
            "description": "Comment"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Add a comment",
        "tags": [
          "questions"
        ],
        "x-required-scope": "questions:write"
      }
    },
    "/questions/{id}/escalate": {
      "post": {
        "description": "Hands an open, unanswered question to another person: they are assigned it and told who has not responded for how long; the asker gets an FYI. Uses the question's configured contact unless escalate_to is given.\n\nRequires scope `questions:write`.",
        "parameters": [
          {
            "description": "Question id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "escalate_to": {
                    "description": "User id or email to escalate to (optional when configured)",
                    "type": "string"
                  },
                  "reason": {
                    "description": "Optional note replacing the automatic 'No response from … in …' text",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "description": "Optional escalation target and note",
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Question"
                }
              }
            },
            "description": "Question"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Escalate now",
        "tags": [
          "questions"
        ],
        "x-required-scope": "questions:write"
      }
    },
    "/questions/{id}/publish": {
      "post": {
        "description": "Moves a draft to open and notifies its assignees. No-op for non-drafts.\n\nRequires scope `questions:write`.",
        "parameters": [
          {
            "description": "Question id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Question"
                }
              }
            },
            "description": "The question"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Publish a draft",
        "tags": [
          "questions"
        ],
        "x-required-scope": "questions:write"
      }
    },
    "/questions/{id}/remind": {
      "post": {
        "description": "Re-notifies every respondent who has not yet answered.\n\nRequires scope `questions:write`.",
        "parameters": [
          {
            "description": "Question id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "question_id": {
                      "description": "Question id",
                      "type": "string"
                    },
                    "reminded": {
                      "description": "Respondents reminded",
                      "type": "integer"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "Reminder count"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Send reminders",
        "tags": [
          "questions"
        ],
        "x-required-scope": "questions:write"
      }
    },
    "/questions/{id}/reopen": {
      "post": {
        "description": "Returns an answered/accepted/closed question to open.\n\nRequires scope `questions:write`.",
        "parameters": [
          {
            "description": "Question id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Question"
                }
              }
            },
            "description": "The question"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Reopen a question",
        "tags": [
          "questions"
        ],
        "x-required-scope": "questions:write"
      }
    },
    "/users": {
      "get": {
        "description": "Users in your company. `kind=customer` lists respondents; `product_id` restricts to members of that product.\n\nRequires scope `users:read`.",
        "parameters": [
          {
            "description": "Search name / email / organisation",
            "in": "query",
            "name": "q",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "User kind",
            "in": "query",
            "name": "kind",
            "schema": {
              "enum": [
                "internal",
                "customer"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only members of this product",
            "in": "query",
            "name": "product_id",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Page number (1-based)",
            "in": "query",
            "name": "page",
            "schema": {
              "default": 1,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Page size (max 200)",
            "in": "query",
            "name": "size",
            "schema": {
              "default": 25,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "description": "Paginated list",
                  "properties": {
                    "items": {
                      "items": {
                        "$ref": "#/components/schemas/User"
                      },
                      "type": "array"
                    },
                    "page": {
                      "description": "Current page (1-based)",
                      "type": "integer"
                    },
                    "pages": {
                      "description": "Page count",
                      "type": "integer"
                    },
                    "size": {
                      "description": "Page size",
                      "type": "integer"
                    },
                    "total": {
                      "description": "Total matching items",
                      "type": "integer"
                    }
                  },
                  "required": [
                    "items",
                    "total",
                    "page",
                    "size",
                    "pages"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Users"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "List users",
        "tags": [
          "users"
        ],
        "x-required-scope": "users:read"
      }
    },
    "/users/invite": {
      "post": {
        "description": "Finds or creates a customer respondent by email (login by emailed code), optionally adding them to a product. New accounts receive a welcome email.\n\nRequires scope `users:write`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InviteRequest"
              }
            }
          },
          "description": "`email` is required.",
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InviteResult"
                }
              }
            },
            "description": "Existing respondent"
          },
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InviteResult"
                }
              }
            },
            "description": "Created respondent"
          },
          "400": {
            "$ref": "#/components/responses/Validation"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Invite a respondent",
        "tags": [
          "users"
        ],
        "x-required-scope": "users:write"
      }
    }
  },
  "security": [
    {
      "bearerAuth": []
    },
    {
      "apiKeyAuth": []
    }
  ],
  "servers": [
    {
      "url": "/api/v1"
    }
  ],
  "tags": [
    {
      "name": "meta"
    },
    {
      "name": "products"
    },
    {
      "name": "questions"
    },
    {
      "name": "answers"
    },
    {
      "name": "users"
    },
    {
      "name": "documents"
    },
    {
      "name": "credentials"
    }
  ]
}