> ## Documentation Index
> Fetch the complete documentation index at: https://docs.goosybear.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Call widget.add

> Make a new widget and put it on a desk or project — 'add a chart of our weekly visits', 'put a button that refreshes the briefing on the Client project', 'add a switch for the welcome automation to my Today desk'. A widget is a chart, a single number, a breakdown table, a monitor on one thing, a link straight back to a site, page, board or Data table, a note in their words, a button that presses one tool or starts one automation, or a switch that turns one automation on and off. Pass board_id for a desk or project (its id from `widget.list` or `board.tree`); with none it lands on the Dashboard's first desk. For numbers, only call it when you know which numbers it shows and how far back it looks; if the ask is vague, ask one short question first. For one site or page use the site_* numbers with site_id (from `page.list`) or page_path. Never invent an id for a link, a button or a switch — read it from a tool that listed the thing. An expiry is a promise: pass expires_in_days when they said how long they want it. Not for a bespoke coded card — that is `desk.build_card`; not for showing an existing widget somewhere else — that is `widget.place`.

Every result names the workspace it ran in. Say which workspace the answer is about. When the account has more than one workspace and none is selected, this tool refuses with `workspace_ambiguous` and lists the choices — offer them, never pick one.



## OpenAPI

````yaml /openapi.json post /api/v1/tools/widget.add
openapi: 3.1.0
info:
  title: Goosy Bear API
  version: 1.0.0-beta
  summary: Manage workspace content, projects, Data tables, Pages, library and credits.
  description: >-
    BETA. This API is in beta: paths, request shapes and response envelopes may
    change, and every response carries an `x-goosy-api: beta` header for as long
    as that is true. A change is additive, or it is deprecated first: a response
    to a call that uses a deprecated feature carries `Deprecation` and `Sunset`
    headers, and nothing is removed until at least 90 days after its
    deprecation. Pin the OpenAPI document you generated against and re-generate
    when it changes.
servers:
  - url: https://app.goosybear.ai
    description: Production
security:
  - tenantApiKey: []
paths:
  /api/v1/tools/widget.add:
    post:
      tags:
        - widget
      summary: Call widget.add
      description: >-
        Make a new widget and put it on a desk or project — 'add a chart of our
        weekly visits', 'put a button that refreshes the briefing on the Client
        project', 'add a switch for the welcome automation to my Today desk'. A
        widget is a chart, a single number, a breakdown table, a monitor on one
        thing, a link straight back to a site, page, board or Data table, a note
        in their words, a button that presses one tool or starts one automation,
        or a switch that turns one automation on and off. Pass board_id for a
        desk or project (its id from `widget.list` or `board.tree`); with none
        it lands on the Dashboard's first desk. For numbers, only call it when
        you know which numbers it shows and how far back it looks; if the ask is
        vague, ask one short question first. For one site or page use the site_*
        numbers with site_id (from `page.list`) or page_path. Never invent an id
        for a link, a button or a switch — read it from a tool that listed the
        thing. An expiry is a promise: pass expires_in_days when they said how
        long they want it. Not for a bespoke coded card — that is
        `desk.build_card`; not for showing an existing widget somewhere else —
        that is `widget.place`.


        Every result names the workspace it ran in. Say which workspace the
        answer is about. When the account has more than one workspace and none
        is selected, this tool refuses with `workspace_ambiguous` and lists the
        choices — offer them, never pick one.
      operationId: call_widget_add
      parameters:
        - name: x-request-id
          in: header
          required: false
          description: >-
            Your own id for this request, echoed back and recorded on the audit
            trail. 1–128 characters from `A–Z a–z 0–9 . _ : -`, starting with a
            letter or digit; anything else is replaced by a generated id.
          schema:
            type: string
            maxLength: 128
        - name: Idempotency-Key
          in: header
          required: true
          description: >-
            Your key for this write: send the same key when you retry and the
            first result comes back instead of a second action. Keys are
            honoured for at least 24 hours. 1–200 visible ASCII characters.
            Replaces the `idempotency_key` body field, which still works until
            2026-12-31; this action needs a key on one of the two, and the
            header is the one to send.
          schema:
            type: string
            maxLength: 200
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                kind:
                  type: string
                  enum:
                    - chart
                    - table
                    - kpi
                    - monitor
                    - note
                    - link
                    - button
                    - switch
                    - briefing
                    - needs_you
                    - analytics
                  description: >-
                    chart for a trend over time · kpi for one number · table for
                    a breakdown · monitor to watch one thing · link for a way
                    straight back to a site, page, board or Data table · note
                    for anything they want written down · button to press one
                    tool or start one automation · switch to turn one automation
                    on and off, or flip one yes/no cell of a Data table ·
                    briefing, needs_you and analytics for the week's briefing,
                    what is waiting on them and their analytics panel.
                title:
                  type: string
                  minLength: 1
                  description: >-
                    What they will see on it. Plain business language, their
                    words where you have them.
                board_id:
                  description: >-
                    The desk or project to put it on: a desk id from
                    `widget.list` (the Dashboard's tabs) or a project id from
                    `board.tree`. Omit for the Dashboard's first desk.
                  type: string
                  format: uuid
                  pattern: >-
                    ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$
                metric_keys:
                  description: >-
                    Which numbers it shows. Required on chart, table, kpi and
                    monitor; omitted on every other kind.
                  minItems: 1
                  maxItems: 6
                  type: array
                  items:
                    type: string
                    enum:
                      - rev_leads
                      - rev_booked_calls
                      - rev_calls_showed
                      - rev_show_rate
                      - rev_sales_won
                      - rev_revenue_won
                      - rev_revenue_by_source
                      - rev_open_pipeline_value
                      - email_sent
                      - email_delivered
                      - email_delivery_rate
                      - email_opened
                      - email_open_rate
                      - email_clicked
                      - email_click_rate
                      - email_replied
                      - email_complaint_rate
                      - email_bounce_rate
                      - list_size
                      - list_new_subscribers
                      - list_unsubscribe_rate
                      - ads_spend
                      - ads_impressions
                      - ads_clicks
                      - ads_ctr
                      - ads_cpc
                      - ads_cpm
                      - ads_reach
                      - ads_frequency
                      - ads_conversions
                      - ads_cost_per_lead
                      - ads_cost_per_booked_call
                      - ads_attributed_revenue
                      - vid_views
                      - vid_watch_time_minutes
                      - vid_avg_view_duration
                      - vid_impressions
                      - vid_impressions_ctr
                      - vid_subscribers_gained
                      - vid_net_subscribers
                      - vid_breakout_score
                      - soc_posts_published
                      - soc_impressions
                      - soc_engagements
                      - soc_engagement_rate
                      - soc_meta_impressions
                      - soc_meta_engagements
                      - soc_meta_engagement_rate
                      - soc_fb_impressions
                      - soc_fb_engagements
                      - soc_fb_engagement_rate
                      - soc_ig_impressions
                      - soc_ig_reach
                      - soc_ig_engagements
                      - soc_ig_engagement_rate
                      - soc_ig_profile_visits
                      - soc_ig_new_follows
                      - sys_produced
                      - hyros_attributed_revenue
                      - hyros_attributed_leads
                      - web_sessions
                      - web_active_users
                      - web_conversions
                      - web_revenue
                      - web_search_impressions
                      - web_search_clicks
                      - web_search_ctr
                      - web_search_position
                      - site_views
                      - site_visitors
                      - site_sessions
                      - site_conversions
                      - site_conversion_rate
                grain:
                  description: >-
                    How the numbers are bucketed. Use 'day' for a chart unless
                    they asked for weeks or months.
                  type: string
                  enum:
                    - hour
                    - day
                    - week
                    - month
                    - quarter
                    - year
                    - lifetime
                window_periods:
                  description: >-
                    How far back it looks, counted in `grain` periods. 'the last
                    28 days' with grain=day is 28.
                  type: integer
                  minimum: 1
                  maximum: 366
                compare:
                  description: >-
                    What it compares against. 'previous_period' is the usual
                    answer; 'none' shows a bare number.
                  type: string
                  enum:
                    - none
                    - previous_period
                    - same_period_last_year
                entity:
                  description: >-
                    The thing a monitor watches, e.g. {kind: 'ad_set', id:
                    '...'}. Required for that kind.
                  type: object
                  properties:
                    kind:
                      type: string
                      minLength: 1
                    id:
                      type: string
                      minLength: 1
                  required:
                    - kind
                    - id
                  additionalProperties: false
                condition:
                  description: >-
                    The 'tell me when' threshold. 'no_change_for' takes a number
                    of days as its value.
                  type: object
                  properties:
                    metric_key:
                      type: string
                      enum:
                        - rev_leads
                        - rev_booked_calls
                        - rev_calls_showed
                        - rev_show_rate
                        - rev_sales_won
                        - rev_revenue_won
                        - rev_revenue_by_source
                        - rev_open_pipeline_value
                        - email_sent
                        - email_delivered
                        - email_delivery_rate
                        - email_opened
                        - email_open_rate
                        - email_clicked
                        - email_click_rate
                        - email_replied
                        - email_complaint_rate
                        - email_bounce_rate
                        - list_size
                        - list_new_subscribers
                        - list_unsubscribe_rate
                        - ads_spend
                        - ads_impressions
                        - ads_clicks
                        - ads_ctr
                        - ads_cpc
                        - ads_cpm
                        - ads_reach
                        - ads_frequency
                        - ads_conversions
                        - ads_cost_per_lead
                        - ads_cost_per_booked_call
                        - ads_attributed_revenue
                        - vid_views
                        - vid_watch_time_minutes
                        - vid_avg_view_duration
                        - vid_impressions
                        - vid_impressions_ctr
                        - vid_subscribers_gained
                        - vid_net_subscribers
                        - vid_breakout_score
                        - soc_posts_published
                        - soc_impressions
                        - soc_engagements
                        - soc_engagement_rate
                        - soc_meta_impressions
                        - soc_meta_engagements
                        - soc_meta_engagement_rate
                        - soc_fb_impressions
                        - soc_fb_engagements
                        - soc_fb_engagement_rate
                        - soc_ig_impressions
                        - soc_ig_reach
                        - soc_ig_engagements
                        - soc_ig_engagement_rate
                        - soc_ig_profile_visits
                        - soc_ig_new_follows
                        - sys_produced
                        - hyros_attributed_revenue
                        - hyros_attributed_leads
                        - web_sessions
                        - web_active_users
                        - web_conversions
                        - web_revenue
                        - web_search_impressions
                        - web_search_clicks
                        - web_search_ctr
                        - web_search_position
                        - site_views
                        - site_visitors
                        - site_sessions
                        - site_conversions
                        - site_conversion_rate
                    operator:
                      type: string
                      enum:
                        - above
                        - below
                        - no_change_for
                    value:
                      type: number
                  required:
                    - metric_key
                    - operator
                    - value
                  additionalProperties: false
                link_target_kind:
                  description: >-
                    For a link: what it opens — a site, a page, a board (or
                    project), or a Data table. Required for that kind.
                  type: string
                  enum:
                    - page
                    - site
                    - board
                    - data_table
                link_target_id:
                  description: >-
                    For a link: the id of the thing it opens, read from a tool
                    that listed it — a link to an id that does not resolve is a
                    dead widget.
                  type: string
                  minLength: 1
                note_body:
                  description: >-
                    For a note: what it says, in their words where you have
                    them. Markdown renders. Required for that kind.
                  type: string
                  minLength: 1
                  maxLength: 8000
                site_id:
                  description: >-
                    For site_* numbers only: narrow it to one of their sites, by
                    its id from `page.list` — never an invented id. Add
                    page_path for one page of it.
                  type: string
                  format: uuid
                  pattern: >-
                    ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$
                page_path:
                  description: >-
                    For site_* numbers only: narrow it to one page by its path,
                    like /pricing — that path on every site unless site_id is
                    also given.
                  type: string
                  minLength: 1
                  maxLength: 1024
                label:
                  description: 'For a button or a switch: the words on it.'
                  type: string
                  minLength: 1
                  maxLength: 200
                press_tool:
                  description: >-
                    For a button that presses a tool: the tool's name, like
                    'briefing.regenerate'. Pressing it runs that tool behind the
                    tool's own approval.
                  type: string
                  pattern: ^[a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)+$
                press_automation_id:
                  description: >-
                    For a button that starts an automation: its id, read from a
                    tool that listed it.
                  type: string
                  format: uuid
                  pattern: >-
                    ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$
                switch_automation_id:
                  description: >-
                    For a switch that turns an automation on and off: its id,
                    read from a tool that listed it.
                  type: string
                  format: uuid
                  pattern: >-
                    ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$
                switch_data_table_id:
                  description: >-
                    For a switch on one yes/no cell: the Data table's id. Pass
                    switch_row_id and switch_column with it.
                  type: string
                  format: uuid
                  pattern: >-
                    ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$
                switch_row_id:
                  description: 'For a switch on one yes/no cell: the row''s id.'
                  type: string
                  format: uuid
                  pattern: >-
                    ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$
                switch_column:
                  description: 'For a switch on one yes/no cell: the column''s key.'
                  type: string
                  pattern: ^[a-z][a-z0-9_]{0,63}$
                expires_in_days:
                  description: >-
                    Take it down again after this many days. 'for two weeks' is
                    14. Omit for a widget that stands until they remove it.
                  type: integer
                  minimum: 1
                  maximum: 366
                idempotency_key:
                  type: string
                  minLength: 1
                  maxLength: 200
                  description: >-
                    Deprecated on REST: send the `Idempotency-Key` header
                    instead. Still accepted until 2026-12-31; if both are sent
                    they must match.
                workspace:
                  description: >-
                    Which workspace to run in — its slug. Omit to use your
                    default. With more than one reachable workspace and no
                    default, the call is refused and the choices are listed.
                  type: string
                  minLength: 1
              required:
                - kind
                - title
              additionalProperties: false
      responses:
        '200':
          description: >-
            The call was admitted and dispatched. `ok` says whether the tool
            succeeded — a refusal the tool itself produced is still a 200,
            exactly as it is a successful JSON-RPC result over MCP.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
            x-request-id:
              description: >-
                This request's id: the `x-request-id` you sent when it was well
                formed, otherwise one generated for you. Quote it to support; it
                is recorded on every audit row the call wrote.
              schema:
                type: string
            RateLimit-Limit:
              description: Requests this key may make in a rolling minute.
              schema:
                type: integer
                minimum: 1
            RateLimit-Remaining:
              description: Requests left in the current rolling minute.
              schema:
                type: integer
                minimum: 0
            RateLimit-Reset:
              description: Whole seconds until the window frees more requests.
              schema:
                type: integer
                minimum: 1
            x-goosy-tool-error:
              description: >-
                `true` when a boundary step refused the call — workspace
                resolution failed or could not be read. A tool that ran and
                returned its own typed `ok: false` reports `false` here.
                **Branch on `ok` in the body for the outcome; this header is the
                transport-level hint.**
              schema:
                type: string
                enum:
                  - 'true'
                  - 'false'
          content:
            application/json:
              schema:
                oneOf:
                  - type: object
                    description: The tool ran and answered.
                    properties:
                      ok:
                        type: boolean
                        const: true
                      widget_id:
                        type: string
                      board_id:
                        anyOf:
                          - type: string
                          - type: 'null'
                      answer_note:
                        type: string
                      replayed:
                        type: boolean
                        description: >-
                          True when this is the first result of an earlier call
                          with the same idempotency_key, returned without
                          writing anything again.
                      workspace:
                        type: string
                        description: The slug of the workspace this call ran in.
                      working_in:
                        type: object
                        properties:
                          label:
                            type: string
                            description: 'The chip words — e.g. "working in: Acme Main".'
                          note:
                            type: string
                            description: >-
                              Why this workspace — e.g. "your default", "this
                              call only".
                          workspace:
                            type: string
                            description: The resolved workspace's slug.
                          source:
                            type: string
                            enum:
                              - call-override
                              - key-pin
                              - stored-default
                              - sole-reachable
                            description: >-
                              Which rung of the R7 precedence resolved the
                              workspace.
                        required:
                          - label
                          - note
                          - workspace
                          - source
                        description: >-
                          Which workspace this call ran in, and how that was
                          decided. Present on every workspace-scoped result.
                        additionalProperties: false
                    required:
                      - ok
                      - answer_note
                      - board_id
                      - replayed
                      - widget_id
                      - working_in
                      - workspace
                  - $ref: '#/components/schemas/ToolRefusal'
        '400':
          description: >-
            The request could not be used: the body is present but not a JSON
            object (`tenant_api.malformed_body`); it is a top-level array
            carrying more messages than this endpoint accepts
            (`tenant_mcp.batch_too_large`); or the `Idempotency-Key` header is
            malformed (`tenant_api.idempotency_key_invalid`), disagrees with the
            body's `idempotency_key` (`tenant_api.idempotency_key_conflict`), or
            was sent to an action that cannot replay a retry
            (`tenant_api.idempotency_unsupported`). Nothing ran.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
            x-request-id:
              description: >-
                This request's id: the `x-request-id` you sent when it was well
                formed, otherwise one generated for you. Quote it to support; it
                is recorded on every audit row the call wrote.
              schema:
                type: string
            Deprecation:
              description: >-
                RFC 9745: this refusal's nested `error` object is deprecated,
                since this instant (`@<unix seconds>`).
              schema:
                type: string
            Sunset:
              description: >-
                RFC 8594: the nested `error` object may be removed after this
                date (2026-12-31).
              schema:
                type: string
            Link:
              description: The page that says what to read instead (`rel="deprecation"`).
              schema:
                type: string
            RateLimit-Limit:
              description: Requests this key may make in a rolling minute.
              schema:
                type: integer
                minimum: 1
            RateLimit-Remaining:
              description: Requests left in the current rolling minute.
              schema:
                type: integer
                minimum: 0
            RateLimit-Reset:
              description: Whole seconds until the window frees more requests.
              schema:
                type: integer
                minimum: 1
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: >-
            No bearer credential, or one that did not resolve. Deliberately ONE
            undifferentiated answer for absent / unknown / revoked / expired, so
            the endpoint is never an oracle over the key space.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
            x-request-id:
              description: >-
                This request's id: the `x-request-id` you sent when it was well
                formed, otherwise one generated for you. Quote it to support; it
                is recorded on every audit row the call wrote.
              schema:
                type: string
            Deprecation:
              description: >-
                RFC 9745: this refusal's nested `error` object is deprecated,
                since this instant (`@<unix seconds>`).
              schema:
                type: string
            Sunset:
              description: >-
                RFC 8594: the nested `error` object may be removed after this
                date (2026-12-31).
              schema:
                type: string
            Link:
              description: The page that says what to read instead (`rel="deprecation"`).
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: >-
            The credential is good but the surface is not open to it — the
            platform or account API switch is off, or the holder lacks the
            `api.access` capability. The `code` says which.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
            x-request-id:
              description: >-
                This request's id: the `x-request-id` you sent when it was well
                formed, otherwise one generated for you. Quote it to support; it
                is recorded on every audit row the call wrote.
              schema:
                type: string
            Deprecation:
              description: >-
                RFC 9745: this refusal's nested `error` object is deprecated,
                since this instant (`@<unix seconds>`).
              schema:
                type: string
            Sunset:
              description: >-
                RFC 8594: the nested `error` object may be removed after this
                date (2026-12-31).
              schema:
                type: string
            Link:
              description: The page that says what to read instead (`rel="deprecation"`).
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: >-
            No such tool. The body names no tool and is identical for every
            unrecognised name.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
            x-request-id:
              description: >-
                This request's id: the `x-request-id` you sent when it was well
                formed, otherwise one generated for you. Quote it to support; it
                is recorded on every audit row the call wrote.
              schema:
                type: string
            Deprecation:
              description: >-
                RFC 9745: this refusal's nested `error` object is deprecated,
                since this instant (`@<unix seconds>`).
              schema:
                type: string
            Sunset:
              description: >-
                RFC 8594: the nested `error` object may be removed after this
                date (2026-12-31).
              schema:
                type: string
            Link:
              description: The page that says what to read instead (`rel="deprecation"`).
              schema:
                type: string
            RateLimit-Limit:
              description: Requests this key may make in a rolling minute.
              schema:
                type: integer
                minimum: 1
            RateLimit-Remaining:
              description: Requests left in the current rolling minute.
              schema:
                type: integer
                minimum: 0
            RateLimit-Reset:
              description: Whole seconds until the window frees more requests.
              schema:
                type: integer
                minimum: 1
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: >-
            Over this key's per-minute cap. Carries `Retry-After` and
            `error.retry_after_seconds`.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
            x-request-id:
              description: >-
                This request's id: the `x-request-id` you sent when it was well
                formed, otherwise one generated for you. Quote it to support; it
                is recorded on every audit row the call wrote.
              schema:
                type: string
            Deprecation:
              description: >-
                RFC 9745: this refusal's nested `error` object is deprecated,
                since this instant (`@<unix seconds>`).
              schema:
                type: string
            Sunset:
              description: >-
                RFC 8594: the nested `error` object may be removed after this
                date (2026-12-31).
              schema:
                type: string
            Link:
              description: The page that says what to read instead (`rel="deprecation"`).
              schema:
                type: string
            RateLimit-Limit:
              description: Requests this key may make in a rolling minute.
              schema:
                type: integer
                minimum: 1
            RateLimit-Remaining:
              description: Requests left in the current rolling minute.
              schema:
                type: integer
                minimum: 0
            RateLimit-Reset:
              description: Whole seconds until the window frees more requests.
              schema:
                type: integer
                minimum: 1
            Retry-After:
              description: Whole seconds to wait before retrying.
              schema:
                type: integer
                minimum: 1
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    ToolRefusal:
      type: object
      properties:
        ok:
          type: boolean
          const: false
        code:
          type: string
          description: >-
            The typed reason — e.g. `workspace_ambiguous`, `invalid_arguments`,
            or the tool's own failure code.
        message:
          type: string
          description: A sentence a person can act on.
        workspaces:
          description: 'On a workspace refusal: the slugs this key may pass as `workspace`.'
          type: array
          items:
            type: string
        issues:
          description: 'On `invalid_arguments`: which fields failed, and why.'
          type: array
          items:
            type: object
            properties:
              path:
                type: string
              message:
                type: string
            required:
              - path
              - message
            additionalProperties: false
      required:
        - ok
        - code
        - message
      description: A call that was admitted and dispatched, and did not succeed.
      additionalProperties: false
    Error:
      type: object
      properties:
        ok:
          type: boolean
          const: false
        code:
          type: string
          description: >-
            The typed refusal code — e.g. `tenant_mcp.surface_disabled`,
            `tenant_mcp.rate_limited`.
        message:
          type: string
          description: A sentence a person can act on.
        retry_after_seconds:
          description: 'On a 429: whole seconds to wait. Mirrors `Retry-After`.'
          type: number
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
            retry_after_seconds:
              type: number
          required:
            - code
            - message
          description: >-
            Deprecated: the same values as the top-level fields, kept until
            2026-12-31. Read `code` and `message` at the top level.
          additionalProperties: false
      required:
        - ok
        - code
        - message
        - error
      description: >-
        A request the boundary refused before dispatching anything. The same
        shape the MCP endpoint answers its own refusals with, and the same
        top-level fields a dispatched call's refusal carries, so one client
        branch covers both.
      additionalProperties: false
  securitySchemes:
    tenantApiKey:
      type: http
      scheme: bearer
      description: >-
        An API key minted at Settings › API & MCP. Send it as `Authorization:
        Bearer <key>`. A key carries its holder's own permissions, resolved on
        every call — revoking a membership closes the key's reach immediately.
        Keep it in an environment variable (`GOOSY_API_KEY`), never in a
        committed file.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.