{
  "openapi": "3.1.0",
  "info": {
    "title": "Freesbe API",
    "version": "2026-11-06",
    "description": "Everything a person or admin can do in Freesbe: messages, channels and DMs, people, meetings, booking pages, the punch clock, webhooks and more. Generated from https://freesbe.net/docs/api/, which has the guide, the realtime WebSocket and webhook signatures.",
    "contact": {
      "name": "Freesbe",
      "url": "https://freesbe.net/developers/"
    }
  },
  "externalDocs": {
    "url": "https://freesbe.net/docs/api/"
  },
  "servers": [
    {
      "url": "https://api.freesbe.net"
    }
  ],
  "security": [
    {
      "bearer": []
    }
  ],
  "tags": [
    {
      "name": "Account and profile",
      "description": "Who you are, across every workspace. These work with any token, even in a workspace that requires single sign-on or multi-factor authentication."
    },
    {
      "name": "Email sign-in and your address",
      "description": "These need a server that can send email (`email: true` in `/api/meta`), and answer 503 `unavailable` otherwise."
    },
    {
      "name": "Passkeys, Google and Microsoft",
      "description": "These follow the browser's WebAuthn and OAuth flows, so they're for the Freesbe apps. You can list, rename and remove passkeys from a script."
    },
    {
      "name": "Sessions and multi-factor authentication",
      "description": "In a workspace that requires multi-factor authentication, its endpoints answer 403 `mfa_required` until the token verifies a second step. A script verifies with an authenticator app: set one up once with `/api/me/totp`, then send a code to `/api/me/mfa/totp` after each sign-in, and again when the workspace asks."
    },
    {
      "name": "Workspaces and settings"
    },
    {
      "name": "People and roles"
    },
    {
      "name": "Invites"
    },
    {
      "name": "Email domains"
    },
    {
      "name": "Guests",
      "description": "Guests are people from outside the organization who join specific channels only. Anyone in the channel who isn't a guest can invite them."
    },
    {
      "name": "Channels",
      "description": "Channel names are lowercase letters, numbers, hyphens and underscores, up to 80 characters; Freesbe tidies what you send (`Q3 Launch!` becomes `q3-launch`). Private channels you're not in answer 404, as if they didn't exist."
    },
    {
      "name": "Direct messages",
      "description": "A DM is a channel with `kind: \"dm\"` and no name. Read and post in it with the channel and message endpoints."
    },
    {
      "name": "Messages and threads",
      "description": "Text is Slack-style mrkdwn, up to 40,000 characters. Mention people with `<@userId>` and the whole channel with `<!channel>`. Archived channels are read-only."
    },
    {
      "name": "Reactions"
    },
    {
      "name": "Keyword alerts",
      "description": "Words and phrases that alert you like a mention: a message in one of your channels with one of them notifies you, counts toward the mention badge and shows in Activity. They match whole words, ignoring case. Up to 50 per workspace, 40 characters each. Changes reach your other devices as a `keywords.changed` event. Apps can't use these."
    },
    {
      "name": "Link previews",
      "description": "Freesbe adds a preview for up to three web links in each message people send: an attachment with `fromUrl` (the link), `serviceName` (the site), `title`, `titleLink`, `text` (the page's description) and a picture in `thumbUrl`, or `imageUrl` for a link to a picture. Pictures load through Freesbe, so the site doesn't see who's reading. Previews arrive a moment after the message, as a `message.updated` event. Links in code, to private addresses, and those an integration previews get none."
    },
    {
      "name": "Custom emoji",
      "description": "A workspace's own pictures, written `:name:` in messages and used as reactions (`PUT /api/messages/{m}/reactions/%3Anorthwind%3A`). Names are 2 to 32 lowercase letters, numbers, `-`, `+` or `_`, and can't be a built-in emoji's name. A workspace has up to 500. Changes reach everyone as an `emoji.changed` event."
    },
    {
      "name": "Sidebar sections",
      "description": "Your own groups of channels and DMs in the sidebar. Only you see them; changes reach your other devices as `sidebar.sections` (the whole list) and `channel.section` events. Up to 50, with names of up to 40 characters. Apps can't use these."
    },
    {
      "name": "Notification sounds",
      "description": "The sounds are `freesbe`, `ding`, `pop`, `knock`, `bell`, `bubble`, `chord`, `marimba` and `none` (notify without a sound). Set one per conversation with the channel's `prefs`, or per person here; your other devices follow."
    },
    {
      "name": "Files",
      "description": "Upload first, then attach the file to a message within a day; files that are never attached are deleted. Until then only you can download it."
    },
    {
      "name": "Files (the file cabinet)",
      "description": "Files people keep outside conversations, in My files or the workspace's folders, shared with people and teams. Access is `view` (open and download), `edit` (also upload, add versions, rename and move) or `full` (also delete, restore, share and change who has access). The owner of My files, admins in the workspace's folders, and whoever uploaded a file (while they can open its folder) have `full`; making a top-level workspace folder adds a `full` share for its maker. A top-level workspace folder's `everyone` (`none`, `view` or `edit`) is what every member gets in it. Members only: guests get 404. Download a file at its `file.url`, the same as any other file."
    },
    {
      "name": "Status, availability and search",
      "description": "Who is online (`presence`) comes with `/boot` and then live over the WebSocket; there's no endpoint to set it, because it follows the apps people have open."
    },
    {
      "name": "To-dos",
      "description": "Each person's own to-do list in a workspace. Nobody else, admins included, can see or change it. `dueAt` is milliseconds (the apps use the end of the chosen day); `doneAt` is set when it's ticked off."
    },
    {
      "name": "Scheduled messages",
      "description": "Messages you write now to go out later. Only their author can see or change them until they're sent. `sendAt` is milliseconds, at least a minute ahead and at most 120 days. At its time the message is posted as if you'd just sent it, with the usual notifications and outgoing webhooks. One that can't be sent (you left the channel, it was archived) stays listed with `status: \"failed\"` and the reason in `error`."
    },
    {
      "name": "Pins and bookmarks",
      "description": "Everyone who can write in a channel or DM can pin its messages (up to 100) and keep links at its top as bookmarks (up to 50). Everyone who can read it sees them. Changes reach the conversation's members as `pins.changed` and `bookmarks.changed` events with its `channelId`. A pin goes when its message is deleted."
    },
    {
      "name": "Save for later and reminders",
      "description": "Your own Later list: messages you saved to come back to, each with an optional reminder (`remindAt`, in milliseconds). Only you see it. A reminder goes off once, as a `reminder.due` event to your apps and a push notification to your phone when you aren't using Freesbe; any change reaches your other devices as `saved.changed`. Up to 500 in progress per workspace. Apps can't use these."
    },
    {
      "name": "Drafts",
      "description": "What you've typed in a conversation and not sent, kept for all your devices: one per channel, DM or thread (`threadRootId`). Only you can see your drafts. Each change reaches your other devices as a `draft.changed` event. A workspace keeps up to 200 per person; the oldest make room. Apps can't use these."
    },
    {
      "name": "Canvases",
      "description": "Each channel and DM can have one canvas, a shared document. Its content travels only over the canvas WebSocket as Yjs updates: binary frames whose first byte is 0 for a document update or 1 for a presence (awareness) update from y-protocols. On connect the server sends `{\"t\":\"ready\",\"canEdit\":true}` and then the whole document as one update; send it what it's missing, then every local change. Members of the conversation can write; anyone who can read it can watch."
    },
    {
      "name": "Huddles and recordings",
      "description": "Huddles are live calls in a channel; in a DM they ring the other people. They need the realtime WebSocket (for the `connId`) and Cloudflare Realtime for the audio and video, so in practice the Freesbe apps run them. Scripts can follow them through the WebSocket events. Answers 503 when huddles aren't set up on the server. When the workspace has used its video allowance, `videoPaused` is set: cameras and screen sharing stop, and voice keeps working."
    },
    {
      "name": "AI summaries, translations and writing help",
      "description": "Summaries and translations written by AI, for the person asking only: nothing is posted or kept. Each request counts toward the workspace's monthly AI allowance, which starts again on its billing day; past it, or when an admin turned AI off, they answer 403. Up to 20 a minute per person (429)."
    },
    {
      "name": "Meetings",
      "description": "Scheduled calls with a link people outside the workspace can open in a browser. Invites go out by email with a calendar file."
    },
    {
      "name": "Calendar",
      "description": "Each person can connect one Google or Microsoft calendar, with permission to see only when they're busy, never what the events are. Freesbe then shows busy times when scheduling and can set \"In a meeting\" as their status. With permission to read events too, the [Calendar app](/docs/calendar-app/) sends a daily agenda, reminders and invitations to answer. The [Outlook add-in](/docs/outlook/) schedules Freesbe meetings from Outlook events with its own token."
    },
    {
      "name": "Bookings",
      "description": "A public page where anyone can book a 15, 30 or 60 minute call with you, like Calendly. Each person makes their own, up to 10 per workspace. A booking becomes an ordinary meeting, with its email and calendar invite, and avoids busy times in your connected calendar."
    },
    {
      "name": "Team booking pages",
      "description": "On the Corporate and Enterprise plans, admins make booking pages for several people. In `round_robin` mode a time is offered when anyone on the team is free, and the booking goes to one of the people free then: whoever had the fewest bookings in the last 30 days (`order: fewest`) or the first one in the list (`order: priority`). In `together` mode a time is offered only when everyone is free, and they all join the meeting. Each person can pause themselves. The public side is the same as any booking page (Bookings), and `GET /api/book/{slug}` adds `team` with the mode and the people on it."
    },
    {
      "name": "Custom domain",
      "description": "On the Corporate and Enterprise plans, a workspace can serve its booking pages, meeting links and invite links from its own subdomain, such as `meetme.northwind.example`. That address answers only the public booking and meeting endpoints for its own workspace, never the rest of the API."
    },
    {
      "name": "Punch clock",
      "description": "When an admin turns the punch clock on, the people it covers clock in and out. Times are milliseconds; every change after the fact needs a `reason` and is kept in the entry's history."
    },
    {
      "name": "Apps",
      "description": "Admins make apps from a Slack-shaped manifest. Each app has a bot user and a bot token (`fsb-bot-…`) that only reaches the endpoints its scopes allow; each endpoint below lists the scope it needs. See [apps and bot tokens](#apps) above."
    },
    {
      "name": "Sign in with Freesbe",
      "description": "Settings for letting people sign in to an app with their Freesbe account. The OpenID Connect endpoints themselves are at `https://id.freesbe.net`; see [Sign in with Freesbe](/docs/sign-in-with-freesbe/#for-developers)."
    },
    {
      "name": "AI agents",
      "description": "The pages behind connecting AI tools (Claude, ChatGPT, code editors) to a workspace. The MCP server itself is at `https://api.freesbe.net/mcp` and its OAuth endpoints at `https://id.freesbe.net`; see [AI agents](/docs/ai-agents/#for-developers). Permissions are the scopes listed there, and the [tools](/docs/ai-agents/#tools) an agent gets depend on them: `search`, `list_channels`, `read_channel`, `read_thread`, `send_message`, `send_dm`, `add_reaction`, `find_people`, `check_presence`, `find_free_time`, `ask`, `get_answer`, `list_questions`, `cancel_question` and `get_connection`. Messages come back as plain text with their author, channel and a link; what an agent posts carries a context block naming the agent and the person it acts for. Where the workspace lets agents post as the person (`postAsPerson`), the message is the person's, its context block has `viaAgent` set to the agent's name, and messages agents read back carry `via_ai_agent`."
    },
    {
      "name": "Webhooks",
      "description": "Admins see the webhooks for public channels and the private channels they're in. See [incoming](#incoming) and [outgoing](#outgoing) webhooks above for the formats."
    },
    {
      "name": "Payment alerts",
      "description": "Mercury, Stripe and Airwallex activity posted into a channel. See the [payment alerts guide](/docs/payment-alerts/). Admins see the alerts for public channels and the private channels they're in."
    },
    {
      "name": "Commerce: Shopify and Amazon",
      "description": "A store's orders posted into a channel. See the [Shopify and Amazon guide](/docs/commerce/). Alerts carry the order number, what was bought and the amounts, never the buyer's name, email or address. Admins see the stores for public channels and the private channels they're in."
    },
    {
      "name": "Kraken alerts",
      "description": "A Kraken account's deposits, withdrawals, trades and balances posted into a channel. Freesbe reads the account with a read-only API key every minute, and every five minutes once it has been quiet for an hour. See the [Kraken guide](/docs/kraken/). Admins see the alerts for public channels and the private channels they're in."
    },
    {
      "name": "Crypto wallets",
      "description": "Money in and out of public addresses on Bitcoin, Ethereum, Base, Arbitrum, Optimism, Polygon, BNB Chain, Avalanche, Solana and Tron, posted into a channel. See the [Crypto wallets guide](/docs/crypto-wallets/). Admins see the wallets that post to public channels and the private channels they're in."
    },
    {
      "name": "HubSpot",
      "description": "The HubSpot app: a connected HubSpot account, its deal and contact alerts and link previews. See the [HubSpot guide](/docs/hubspot/). `/hubspot` and **Log to HubSpot** run like any app's [slash command and message action](#ref-apps). Admins see the alerts for public channels and the private channels they're in."
    },
    {
      "name": "GitHub",
      "description": "The GitHub app: Freesbe's GitHub App installed on an organization, the repositories channels subscribe to, and link previews. See the [GitHub guide](/docs/github/). `/github` and **Create GitHub issue** run like any app's [slash command and message action](#ref-apps). Admins see the subscriptions for public channels and the private channels they're in."
    },
    {
      "name": "Jira",
      "description": "The Jira app: a connected Jira Cloud site, the projects channels subscribe to, and link previews. See the [Jira guide](/docs/jira/). `/jira` and **Create Jira issue** run like any app's [slash command and message action](#ref-apps). Admins see the subscriptions for public channels and the private channels they're in."
    },
    {
      "name": "GitLab",
      "description": "The GitLab app: a connected GitLab.com account or self-managed server, the projects channels subscribe to, and link previews. See the [GitLab guide](/docs/gitlab/). `/gitlab` and **Create GitLab issue** run like any app's [slash command and message action](#ref-apps). Admins see the subscriptions for public channels and the private channels they're in."
    },
    {
      "name": "monday.com",
      "description": "The monday.com app: a connected monday.com account, the boards channels subscribe to, and link previews. See the [monday.com guide](/docs/monday/). `/monday` and **Create monday.com item** run like any app's [slash command and message action](#ref-apps). Admins see the subscriptions for public channels and the private channels they're in."
    },
    {
      "name": "Salesforce",
      "description": "The Salesforce app: a connected Salesforce org, its opportunity, lead and case alerts and link previews, on the plans that include it. See the [Salesforce guide](/docs/salesforce/). `/salesforce` and **Log to Salesforce** run like any app's [slash command and message action](#ref-apps). Alerts come from Freesbe checking the org every five minutes, so there's no webhook. Admins see the alerts for public channels and the private channels they're in."
    },
    {
      "name": "Customer orders",
      "description": "A customer's orders from the workspace's WooCommerce store, next to their customer inbox conversation and on their phone calls. See the [customer orders guide](/docs/customer-orders/). Freesbe asks the store each time and keeps no orders. Lookups answer `store: null` until an admin sets the store up, and `customer: null` when the store doesn't know them. Apps can't call these."
    },
    {
      "name": "Customer inbox",
      "description": "Customers write in from a web chat on the workspace's site, and each conversation is a thread in a channel: the inbox bot's card starts it, the customer's messages are replies under their name (`fromCustomer`), and the team's replies in that thread go back to the customer. Send a reply with `note: true` ([post a message](#ref-messages)) to keep it inside the team. People see the conversations of the channels they can see. See the [customer inbox guide](/docs/customer-inbox/). Apps can't use these endpoints."
    },
    {
      "name": "Pipedrive",
      "description": "The Pipedrive app: a connected Pipedrive company, its deal and lead alerts and link previews. See the [Pipedrive guide](/docs/pipedrive/). `/pipedrive` and **Log to Pipedrive** run like any app's [slash command and message action](#ref-apps). Admins see the alerts for public channels and the private channels they're in."
    },
    {
      "name": "Zoho CRM",
      "description": "The Zoho CRM app: a connected Zoho CRM organization, in any Zoho data center, its deal, lead and contact alerts and link previews. See the [Zoho CRM guide](/docs/zoho-crm/). `/zoho` and **Log to Zoho CRM** run like any app's [slash command and message action](#ref-apps). Alerts come from Zoho CRM's change notifications, which Freesbe sets up and renews itself. Admins see the alerts for public channels and the private channels they're in."
    },
    {
      "name": "Zendesk",
      "description": "A workspace's Zendesk connection and its ticket alerts. See the [Zendesk guide](/docs/zendesk/). Admins see the alerts for public channels and the private channels they're in."
    },
    {
      "name": "Zoho Desk",
      "description": "The Zoho Desk app: a connected Zoho Desk help desk, in any Zoho data center, its ticket alerts and link previews. See the [Zoho Desk guide](/docs/zoho-desk/). **Create Zoho Desk ticket** runs like any app's [message action](#ref-apps). Alerts come from a webhook Freesbe adds to the help desk when an administrator connects it. Admins see the alerts for public channels and the private channels they're in."
    },
    {
      "name": "Zoho Books and Zoho Invoice",
      "description": "The Zoho Books and Zoho Invoice apps: a connected organization in either, in any Zoho data center, its invoice and payment alerts and link previews. See the [Zoho Books and Zoho Invoice guide](/docs/zoho-books/). The two have the same routes, under `zoho-books` and `zoho-invoice`; `{product}` below is one of them. Neither lets an app add a webhook, so Freesbe checks the organization every ten minutes while an alert is on. Admins see the alerts for public channels and the private channels they're in."
    },
    {
      "name": "Freshdesk",
      "description": "A workspace's Freshdesk connection and its ticket alerts. See the [Freshdesk guide](/docs/freshdesk/). `/freshdesk`, **Create Freshdesk ticket** and **Add to Freshdesk ticket** run like any app's [slash command and message actions](#ref-apps). Admins see the alerts for public channels and the private channels they're in."
    },
    {
      "name": "Monitoring",
      "description": "Monitoring tools posting problems into a channel: Zabbix, Grafana, Prometheus Alertmanager, PagerDuty, Opsgenie, Datadog, Sentry, Better Stack, New Relic, Uptime Kuma, UptimeRobot, and Freesbe's own status page. Each connection has its own secret URL the tool sends to, and posts one card per problem (or alert) that later updates and the recovery change in place. See the [Zabbix](/docs/zabbix/), [Grafana and Alertmanager](/docs/grafana/), [PagerDuty](/docs/pagerduty/), [Opsgenie](/docs/opsgenie/), [Datadog](/docs/datadog/), [Sentry](/docs/sentry/), [Better Stack](/docs/better-stack/), [New Relic](/docs/new-relic/), [Uptime Kuma](/docs/uptime-kuma/), [UptimeRobot](/docs/uptimerobot/) and [Freesbe status](/docs/status-page/) guides. Admins see the connections for public channels and the private channels they're in."
    },
    {
      "name": "News feeds",
      "description": "RSS, Atom and JSON feeds whose new items Freesbe posts as cards into a channel. Freesbe checks each feed itself, every 15 minutes and less often while it's quiet or failing, and posts only items it hasn't seen. See the [news feeds guide](/docs/rss-feeds/). Admins see the feeds for public channels and the private channels they're in."
    },
    {
      "name": "Zoho Recruit",
      "description": "The Zoho Recruit app: a connected Zoho Recruit organization, in any Zoho data center, its candidate, job opening and interview alerts and link previews. See the [Zoho Recruit guide](/docs/zoho-recruit/). Alerts come from Zoho Recruit's change notifications, which Freesbe sets up and renews itself. Admins see the alerts for public channels and the private channels they're in."
    },
    {
      "name": "Workflows",
      "description": "Workflows run steps for people: post a message, send a form, add someone to a channel, give a to-do, wait, ask for approval, ask a question with buttons, set a status, or branch with `if`. Guests can't make or run them. A workflow's maker and workspace admins can change it and see its runs; everyone else sees only the button workflows that are on. Text in steps can use `{{variables}}` such as `{{trigger.person}}`. See [Workflows](/docs/workflows) for what each trigger and step does."
    },
    {
      "name": "Phone",
      "description": "SIP credentials for desk phones and softphones, connecting your own sip.io account, and the phone system from Freesbe with its numbers. Until an admin sets up either, `provider` is `mock` and the credentials are for testing."
    },
    {
      "name": "Slack import",
      "description": "An admin uploads a Slack export zip in parts, then starts the import. Imported people get an account that waits for them; a sign-in link lets each one take theirs over."
    },
    {
      "name": "Realtime"
    }
  ],
  "paths": {
    "/api/meta": {
      "get": {
        "operationId": "getApiMeta",
        "tags": [
          "Account and profile"
        ],
        "summary": "The server's name and version, the sign-up policy (first, invite or open), the single sign-on providers it has, whether ",
        "description": "The server's name and version, the sign-up policy (`first`, `invite` or `open`), the single sign-on providers it has, whether it can send email, and whether the mobile and desktop apps talk to it (`phoneApps`, false on test copies, so a phone can't approve sign-ins there).\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample answer:\n\n```json\n{ \"name\": \"Freesbe\", \"version\": \"…\", \"signup\": \"invite\", \"sso\": [\"google\", \"microsoft\", \"apple\"], \"email\": true, \"turnstileSiteKey\": null, \"phoneApps\": true }\n```",
        "x-freesbe-access": "public",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/health": {
      "get": {
        "operationId": "getApiHealth",
        "tags": [
          "Account and profile"
        ],
        "summary": "Answers { \"ok\": true } while the API is up.",
        "description": "Answers `{ \"ok\": true }` while the API is up.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/auth/signup": {
      "post": {
        "operationId": "postApiAuthSignup",
        "tags": [
          "Account and profile"
        ],
        "summary": "Create an account.",
        "description": "Create an account. Needs an `inviteToken` unless sign-up is open; the invite also joins its workspace. `acceptTerms: true` records that the person agreed to the current Terms of Service and Privacy Policy; without it the apps ask them to agree before they go on. Answers 201 like login. 10 sign-ups a minute from one IP address.\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample request:\n\n```json\n{\n  \"email\": \"deploy-bot@northwind.example\",\n  \"name\": \"Deploy bot\",\n  \"password\": \"at least 8 characters\",\n  \"timezone\": \"Europe/London\",\n  \"inviteToken\": \"q7Zr…\",\n  \"acceptTerms\": true,\n  \"wantToken\": true\n}\n```",
        "x-freesbe-access": "public",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/auth/login": {
      "post": {
        "operationId": "postApiAuthLogin",
        "tags": [
          "Account and profile"
        ],
        "summary": "Sign in with an email and password.",
        "description": "Sign in with an email and password. Send `wantToken: true` to get a token in the answer. 10 tries a minute per address and per email.\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample request:\n\n```json\n{ \"email\": \"deploy-bot@northwind.example\", \"password\": \"…\", \"wantToken\": true }\n```\n\nExample answer:\n\n```json\n{ \"user\": { … }, \"workspaces\": [ … ], \"canCreateWorkspaces\": false,\n  \"importedHistory\": false, \"authMethod\": \"password\", \"mfaVerifiedAt\": null,\n  \"emailVerified\": true, \"token\": \"kX3q…\" }\n```",
        "x-freesbe-access": "public",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/auth/logout": {
      "post": {
        "operationId": "postApiAuthLogout",
        "tags": [
          "Account and profile"
        ],
        "summary": "End the session the token belongs to.",
        "description": "End the session the token belongs to. Answers 204.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me": {
      "get": {
        "operationId": "getApiMe",
        "tags": [
          "Account and profile"
        ],
        "summary": "The signed-in person, their workspaces, how this session signed in and whether it has verified a second step.",
        "description": "The signed-in person, their workspaces, how this session signed in and whether it has verified a second step.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{\n  \"user\": {\n    \"id\": \"01JB8Q3V7RZ4T5K2M9XWD6HY1C\",\n    \"email\": \"dana@northwind.example\",\n    \"name\": \"Dana Whitfield\",\n    \"avatarUrl\": \"/api/avatars/01JB8Q3V7RZ4T5K2M9XWD6HY1C?v=01JB9…\",\n    \"timezone\": \"Europe/London\"\n  },\n  \"workspaces\": [{ \"id\": \"01JB8Q…\", \"name\": \"Northwind Traders\", \"slug\": \"northwind\", \"role\": \"admin\", … }],\n  \"canCreateWorkspaces\": true,\n  \"importedHistory\": false,\n  \"authMethod\": \"password\",\n  \"mfaVerifiedAt\": null,\n  \"emailVerified\": true,\n  \"lobbyEmail\": true\n}\n```",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiMe",
        "tags": [
          "Account and profile"
        ],
        "summary": "Change your name (up to 80 characters) or timezone (an IANA zone), set your workingHours (seven days, Sunday first, each",
        "description": "Change your `name` (up to 80 characters) or `timezone` (an IANA zone), set your `workingHours` (seven days, Sunday first, each a list of `[start, end]` minutes after midnight in your time zone; `null` goes back to Monday to Friday 9 to 5), or turn off the email about guests waiting in your meetings' lobbies (`lobbyEmail`). Answers like `GET /api/me`.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample request:\n\n```json\n{ \"name\": \"Dana Whitfield\", \"timezone\": \"America/New_York\" }\n```",
        "x-freesbe-access": "signed-in",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/unread": {
      "get": {
        "operationId": "getApiMeUnread",
        "tags": [
          "Account and profile"
        ],
        "summary": "What waits for you in each of your workspaces: unread when a channel or DM you're in (and haven't muted) has messages yo",
        "description": "What waits for you in each of your workspaces: `unread` when a channel or DM you're in (and haven't muted) has messages you haven't read, and `attention`, the mentions of you in channels plus unread direct messages; `inbox`, the open customer conversations that are yours or nobody's; and `latestCustomer`, the newest customer message among them that should alert you (null in a muted inbox channel or while your notifications there are paused). The apps show it on the workspace icons and alert on new customer messages.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"workspaces\": [{ \"workspaceId\": \"01J…\", \"unread\": true, \"attention\": 2, \"inbox\": 1, \"latestCustomer\": { \"conversationId\": \"01J…\", \"at\": 1793900000000, \"from\": \"Jordan Fields\", \"source\": \"Website\" } }] }\n```",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/password": {
      "put": {
        "operationId": "putApiMePassword",
        "tags": [
          "Account and profile"
        ],
        "summary": "Change your password, or set one on an account made with Google or Microsoft (leave out currentPassword).",
        "description": "Change your password, or set one on an account made with Google or Microsoft (leave out `currentPassword`). Signs out every other session. Answers 204.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample request:\n\n```json\n{ \"currentPassword\": \"…\", \"newPassword\": \"…\" }\n```",
        "x-freesbe-access": "signed-in",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/avatar": {
      "put": {
        "operationId": "putApiMeAvatar",
        "tags": [
          "Account and profile"
        ],
        "summary": "Set your picture: the raw PNG, JPEG, GIF or WebP bytes with their Content-Type, up to 2 MB.",
        "description": "Set your picture: the raw PNG, JPEG, GIF or WebP bytes with their `Content-Type`, up to 2 MB. Answers like `GET /api/me`.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample request:\n\n```json\ncurl -X PUT $API/api/me/avatar \\\n  -H \"Authorization: Bearer $FREESBE_TOKEN\" \\\n  -H 'Content-Type: image/png' --data-binary @dana.png\n```",
        "x-freesbe-access": "signed-in",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiMeAvatar",
        "tags": [
          "Account and profile"
        ],
        "summary": "Remove your picture, so your initials show.",
        "description": "Remove your picture, so your initials show. Answers like `GET /api/me`.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/avatar/{provider}": {
      "get": {
        "operationId": "getApiMeAvatarByProvider",
        "tags": [
          "Account and profile"
        ],
        "summary": "The photo Google or Microsoft (google or microsoft) shared the last time you signed in with it, as image bytes, kept eve",
        "description": "The photo Google or Microsoft (`google` or `microsoft`) shared the last time you signed in with it, as image bytes, kept even when you use another picture. Answers 404 when there's none. To use it, upload it with `PUT /api/me/avatar`.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/photo-handoffs": {
      "post": {
        "operationId": "postApiMePhotoHandoffs",
        "tags": [
          "Account and profile"
        ],
        "summary": "A one-time link for taking your picture with your phone, shown as a QR code.",
        "description": "A one-time link for taking your picture with your phone, shown as a QR code. `url` opens a page in the phone's browser that sends one photo back. It works once, for 10 minutes. Nothing changes until you upload the picture with `PUT /api/me/avatar`.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"code\": \"kq3V…\", \"url\": \"https://app.freesbe.net/snap#kq3V…\", \"expiresAt\": 1761462600000 }\n```",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/photo-handoffs/{code}": {
      "get": {
        "operationId": "getApiMePhotoHandoffsByCode",
        "tags": [
          "Account and profile"
        ],
        "summary": "Whether the phone sent the photo: waiting, ready, or gone (expired, cancelled or already picked up).",
        "description": "Whether the phone sent the photo: `waiting`, `ready`, or `gone` (expired, cancelled or already picked up).\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"state\": \"ready\" }\n```",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiMePhotoHandoffsByCode",
        "tags": [
          "Account and profile"
        ],
        "summary": "Cancel the link, and drop a photo the phone already sent.",
        "description": "Cancel the link, and drop a photo the phone already sent. Answers 204.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/photo-handoffs/{code}/photo": {
      "post": {
        "operationId": "postApiMePhotoHandoffsByCodePhoto",
        "tags": [
          "Account and profile"
        ],
        "summary": "The phone's photo as raw image bytes, once.",
        "description": "The phone's photo as raw image bytes, once. The link is used up.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/photo-handoffs/{code}": {
      "get": {
        "operationId": "getApiPhotoHandoffsByCode",
        "tags": [
          "Account and profile"
        ],
        "summary": "For the phone's page: the first name of the person whose picture it takes.",
        "description": "For the phone's page: the first name of the person whose picture it takes. 404 once the link expired or was used.\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample answer:\n\n```json\n{ \"name\": \"Dana\", \"expiresAt\": 1761462600000 }\n```",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      },
      "put": {
        "operationId": "putApiPhotoHandoffsByCode",
        "tags": [
          "Account and profile"
        ],
        "summary": "For the phone's page: the photo, as raw JPEG, PNG or WebP bytes with their Content-Type, up to 8 MB.",
        "description": "For the phone's page: the photo, as raw JPEG, PNG or WebP bytes with their `Content-Type`, up to 8 MB. One per link. Answers 204.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/avatars/{userId}": {
      "get": {
        "operationId": "getApiAvatarsByUserId",
        "tags": [
          "Account and profile"
        ],
        "summary": "Someone's picture, if you share a workspace with them.",
        "description": "Someone's picture, if you share a workspace with them. `avatarUrl` on people points here.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/sign-in": {
      "get": {
        "operationId": "getApiMeSignIn",
        "tags": [
          "Account and profile"
        ],
        "summary": "How you can sign in: whether you have a password, your linked Google and Microsoft accounts, your passkeys, and whether ",
        "description": "How you can sign in: whether you have a password, your linked Google and Microsoft accounts, your passkeys, and whether an authenticator app is set up.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"hasPassword\": true,\n  \"identities\": [{ \"provider\": \"google\", \"email\": \"dana@northwind.example\", \"createdAt\": …, \"lastUsedAt\": … }],\n  \"passkeys\": [{ \"id\": \"01JB…\", \"name\": \"MacBook\", \"backedUp\": true, \"createdAt\": …, \"lastUsedAt\": … }],\n  \"totp\": true }\n```",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/identities/{provider}": {
      "delete": {
        "operationId": "deleteApiMeIdentitiesByProvider",
        "tags": [
          "Account and profile"
        ],
        "summary": "Unlink your google or microsoft account.",
        "description": "Unlink your `google` or `microsoft` account. Answers 204.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/claims": {
      "post": {
        "operationId": "postApiMeClaims",
        "tags": [
          "Account and profile"
        ],
        "summary": "When importedHistory is true, emails you a link for each Slack account imported under your address, to add its history t",
        "description": "When `importedHistory` is true, emails you a link for each Slack account imported under your address, to add its history to your account. Answers 204.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/auth/email-code": {
      "post": {
        "operationId": "postApiAuthEmailCode",
        "tags": [
          "Email sign-in and your address"
        ],
        "summary": "Email a one-time sign-in code.",
        "description": "Email a one-time sign-in code. Answers 204 whether or not the address has an account, so it doesn't reveal who does. 10 codes a day per address.\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample request:\n\n```json\n{ \"email\": \"dana@northwind.example\" }\n```",
        "x-freesbe-access": "public",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/auth/email-code/verify": {
      "post": {
        "operationId": "postApiAuthEmailCodeVerify",
        "tags": [
          "Email sign-in and your address"
        ],
        "summary": "Sign in with the emailed code.",
        "description": "Sign in with the emailed code. Answers like login.\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample request:\n\n```json\n{ \"email\": \"dana@northwind.example\", \"code\": \"482913\", \"wantToken\": true }\n```",
        "x-freesbe-access": "public",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/auth/verify-email": {
      "post": {
        "operationId": "postApiAuthVerifyEmail",
        "tags": [
          "Email sign-in and your address"
        ],
        "summary": "Verify an address from the link in a verification email (its token).",
        "description": "Verify an address from the link in a verification email (its `token`). Answers `{ \"email\": \"…\" }`.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/me/email/verification": {
      "post": {
        "operationId": "postApiMeEmailVerification",
        "tags": [
          "Email sign-in and your address"
        ],
        "summary": "Email yourself a new verification code and link.",
        "description": "Email yourself a new verification code and link. Answers 204.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/email/verify": {
      "post": {
        "operationId": "postApiMeEmailVerify",
        "tags": [
          "Email sign-in and your address"
        ],
        "summary": "Verify your address with the emailed code.",
        "description": "Verify your address with the emailed `code`. Answers like `GET /api/me`.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample request:\n\n```json\n{ \"code\": \"482913\" }\n```",
        "x-freesbe-access": "signed-in",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/email": {
      "put": {
        "operationId": "putApiMeEmail",
        "tags": [
          "Email sign-in and your address"
        ],
        "summary": "Start changing your address: emails a code to the new one.",
        "description": "Start changing your address: emails a code to the new one. Needs `currentPassword` when the account has a password. Answers 204.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample request:\n\n```json\n{ \"email\": \"dana.whitfield@northwind.example\", \"currentPassword\": \"…\" }\n```",
        "x-freesbe-access": "signed-in",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/email/confirm": {
      "post": {
        "operationId": "postApiMeEmailConfirm",
        "tags": [
          "Email sign-in and your address"
        ],
        "summary": "Finish the change with the code sent to the new address.",
        "description": "Finish the change with the `code` sent to the new address. Answers like `GET /api/me`.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample request:\n\n```json\n{ \"code\": \"482913\" }\n```",
        "x-freesbe-access": "signed-in",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/auth/passkey/options": {
      "post": {
        "operationId": "postApiAuthPasskeyOptions",
        "tags": [
          "Passkeys, Google and Microsoft"
        ],
        "summary": "WebAuthn options for navigator.credentials.get().",
        "description": "WebAuthn options for `navigator.credentials.get()`.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/auth/passkey/login": {
      "post": {
        "operationId": "postApiAuthPasskeyLogin",
        "tags": [
          "Passkeys, Google and Microsoft"
        ],
        "summary": "Sign in with the passkey's assertion (response).",
        "description": "Sign in with the passkey's assertion (`response`). Answers like login.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/passkeys": {
      "get": {
        "operationId": "getApiMePasskeys",
        "tags": [
          "Passkeys, Google and Microsoft"
        ],
        "summary": "Your passkeys: id, name, backedUp, createdAt, lastUsedAt.",
        "description": "Your passkeys: `id`, `name`, `backedUp`, `createdAt`, `lastUsedAt`.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiMePasskeys",
        "tags": [
          "Passkeys, Google and Microsoft"
        ],
        "summary": "Save a new passkey from the browser's response, with an optional name.",
        "description": "Save a new passkey from the browser's `response`, with an optional `name`.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/passkeys/options": {
      "post": {
        "operationId": "postApiMePasskeysOptions",
        "tags": [
          "Passkeys, Google and Microsoft"
        ],
        "summary": "WebAuthn options for navigator.credentials.create().",
        "description": "WebAuthn options for `navigator.credentials.create()`. Refused with a token: add passkeys from the app.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/passkeys/{id}": {
      "patch": {
        "operationId": "patchApiMePasskeysById",
        "tags": [
          "Passkeys, Google and Microsoft"
        ],
        "summary": "Rename a passkey.",
        "description": "Rename a passkey.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample request:\n\n```json\n{ \"name\": \"Work laptop\" }\n```",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiMePasskeysById",
        "tags": [
          "Passkeys, Google and Microsoft"
        ],
        "summary": "Remove a passkey.",
        "description": "Remove a passkey. Answers 204.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/auth/oauth/{provider}/start": {
      "get": {
        "operationId": "getApiAuthOauthByProviderStart",
        "tags": [
          "Passkeys, Google and Microsoft"
        ],
        "summary": "Open in the browser to sign in with google, microsoft or apple.",
        "description": "Open in the browser to sign in with `google`, `microsoft` or `apple`. `?next=/path` returns there, `?invite=<token>` signs up through an invite and `?link=1` links the account instead.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.\n\n---\n\nOpen in the browser to connect a calendar. Comes back to `?next=` with `?calendar=connected` or `?calendar_error=`. Add `&events=1&workspace={w}` to also let the Calendar app read events and answer invitations, and turn it on in that workspace; without that permission it comes back with `?calendar_error=events`.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/auth/oauth/{provider}/callback": {
      "get": {
        "operationId": "getApiAuthOauthByProviderCallback",
        "tags": [
          "Passkeys, Google and Microsoft"
        ],
        "summary": "Where Google and Microsoft send people back.",
        "description": "Where Google and Microsoft send people back.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/auth/oauth/apple/callback": {
      "post": {
        "operationId": "postApiAuthOauthAppleCallback",
        "tags": [
          "Passkeys, Google and Microsoft"
        ],
        "summary": "Where Apple posts its answer (a form with code, state and, the first time, user).",
        "description": "Where Apple posts its answer (a form with `code`, `state` and, the first time, `user`). Answers 303 to the GET callback with the same fields.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/auth/handoff": {
      "post": {
        "operationId": "postApiAuthHandoff",
        "tags": [
          "Passkeys, Google and Microsoft"
        ],
        "summary": "The desktop app's sign-in through the system browser: a one-time code for a PKCE challenge.",
        "description": "The desktop app's sign-in through the system browser: a one-time code for a PKCE `challenge`.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/auth/handoff/redeem": {
      "post": {
        "operationId": "postApiAuthHandoffRedeem",
        "tags": [
          "Passkeys, Google and Microsoft"
        ],
        "summary": "The desktop app trades the code and its verifier for a session.",
        "description": "The desktop app trades the `code` and its `verifier` for a session.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/sessions": {
      "get": {
        "operationId": "getApiMeSessions",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Everywhere you're signed in: device, app, sign-in method, address and rough location, when it started and was last used.",
        "description": "Everywhere you're signed in: device, app, sign-in method, address and rough location, when it started and was last used. `current` marks this one.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"sessions\": [\n  { \"id\": \"…\", \"current\": true, \"method\": \"password\", \"createdAt\": …, \"lastActiveAt\": …,\n    \"ip\": \"203.0.113.24\", \"location\": \"London, United Kingdom\", … }\n] }\n```",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiMeSessions",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Sign out every other session, keeping this one.",
        "description": "Sign out every other session, keeping this one. Answers 204.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/sessions/{id}": {
      "delete": {
        "operationId": "deleteApiMeSessionsById",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Sign out one session.",
        "description": "Sign out one session. Answers 204.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/alerts": {
      "get": {
        "operationId": "getApiMeAlerts",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Which of your devices alert you for new messages and reminders (Preferences → Notifications → Alert me on).",
        "description": "Which of your devices alert you for new messages and reminders (Preferences → Notifications → Alert me on). `alertOn` is `using` (the device you're using, the default), `all` (every device) or `chosen` (only the devices whose `alerts` switch is on). `devices` lists everywhere you're signed in, each a session, with the name its app reported (`name`, or null). Calls ring on every device whatever this says.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"alertOn\": \"chosen\", \"devices\": [\n  { \"id\": \"…\", \"current\": true, \"name\": \"Maya's MacBook Air\", \"client\": \"desktop\", \"os\": \"macOS\",\n    \"browser\": null, \"lastActiveAt\": …, \"alerts\": true }\n] }\n```",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiMeAlerts",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Change any of them: alertOn, devices (session ids to true or false) and deviceName, this device's own name (up to 60 cha",
        "description": "Change any of them: `alertOn`, `devices` (session ids to true or false) and `deviceName`, this device's own name (up to 60 characters; null forgets it). Your open apps follow straight away. Answers like `GET /api/me/alerts`.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample request:\n\n```json\n{ \"alertOn\": \"chosen\", \"devices\": { \"…\": false } }\n```",
        "x-freesbe-access": "signed-in",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/terms": {
      "post": {
        "operationId": "postApiMeTerms",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Agree to the current Terms of Service and Privacy Policy.",
        "description": "Agree to the current Terms of Service and Privacy Policy. Send the `version` you were shown; an older one answers 409. Signed-in browser sessions only. `GET /api/me` has `termsVersion`, the version you last agreed to, or null. Answers like `GET /api/me`.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample request:\n\n```json\n{ \"version\": \"2026-10-28\" }\n```",
        "x-freesbe-access": "signed-in",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/security-activity": {
      "get": {
        "operationId": "getApiMeSecurityActivity",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Your security activity, newest first, 50 at a time: each sign-in, second step, sign-out and change to how you sign in (e",
        "description": "Your security activity, newest first, 50 at a time: each sign-in, second step, sign-out and change to how you sign in (`event`: `sign_in`, `sign_in.failed`, `mfa.verified`, `mfa.failed`, `sign_out`, `session.ended`, `sessions.ended`, `password.set`, `password.changed`, `email.changed`, `authenticator.added`, `authenticator.removed`, `passkey.added`, `passkey.removed`, `sso.linked`, `sso.unlinked`, `signed_out_by_admin`, `sign_in.denied` when you said a New sign-in alert wasn't you, `sign_in.confirmed` when you said it was, `sign_in.approved` and `sign_in.rejected` when your phone answered a sign-in or verification request), with what happened (`detail`: the sign-in `method`, `newDevice` and `newCountry` on a sign-in that sent a New sign-in alert, a passkey's `name`, the `provider`, and on phone answers the `approver` phone, the `kind` of request, the `device` and `location` that asked, and `wrongNumber` or `reported`), the browser or app, the IP address and where it was. Narrow it with `?event=`, `?from=` and `?to=` (times in milliseconds) and `?limit=` (up to 5000). When `more` is true, pass the last event's `id` as `?before=` for the next page. Events are kept for a year.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{\n  \"events\": [\n    {\n      \"id\": \"01JB8ZK2W1E9R4M3T6Y7U8I9OP\",\n      \"at\": 1792729800000,\n      \"userId\": \"01JB8ZH7L9M1N3P5Q7R9S1T3UV\",\n      \"event\": \"sign_in\",\n      \"detail\": { \"method\": \"passkey\" },\n      \"ip\": \"203.0.113.24\",\n      \"country\": \"GB\",\n      \"location\": \"London, United Kingdom\",\n      \"client\": \"web\",\n      \"browser\": \"Chrome\",\n      \"os\": \"Windows\"\n    }\n  ],\n  \"more\": false\n}\n```",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/deletion": {
      "get": {
        "operationId": "getApiMeDeletion",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Whether your account is being deleted (pending, with the purge date), what stops you deleting it (blockers: workspaces y",
        "description": "Whether your account is being deleted (`pending`, with the purge date), what stops you deleting it (`blockers`: workspaces you own, `owner` with other people in them or `alone`), and the workspaces you'd leave.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"pending\": null, \"blockers\": [], \"workspaces\": [{ \"id\": \"01JB…\", \"name\": \"Northwind Traders\" }] }\n```",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiMeDeletion",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Deletes your account in 30 days: you leave every workspace and every session, passkey and app or agent grant ends now.",
        "description": "Deletes your account in 30 days: you leave every workspace and every session, passkey and app or agent grant ends now. Signed-in browser sessions only, with a second factor verified in the last 15 minutes (`mfa_required`). Answers 409 while you own a workspace. Until the purge, signing in works but every other endpoint answers 403 `account_deleting`.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample request:\n\n```json\n{ \"reason\": \"Moving to another team\" }\n```\n\nExample answer:\n\n```json\n{ \"purgeAt\": 1795322400000 }\n```",
        "x-freesbe-access": "signed-in",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiMeDeletion",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Keeps your account, if it's still waiting to be deleted.",
        "description": "Keeps your account, if it's still waiting to be deleted. Workspaces' admins reactivate you. Answers 204.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/mfa": {
      "get": {
        "operationId": "getApiMeMfa",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "When this session last verified a second step, and which ways it can: phone (a phone set up to approve sign-ins), passke",
        "description": "When this session last verified a second step, and which ways it can: `phone` (a phone set up to approve sign-ins), `passkey`, `totp`, `email`, `password`. `setup` means none yet: setting up a passkey or authenticator app counts.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"verifiedAt\": null, \"phone\": false, \"passkey\": false, \"totp\": true, \"email\": true, \"password\": false, \"setup\": false }\n```",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/mfa/totp": {
      "post": {
        "operationId": "postApiMeMfaTotp",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Verify with a code from your authenticator app.",
        "description": "Verify with a `code` from your authenticator app. Each code works once. Answers like `GET /api/me`.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample request:\n\n```json\n{ \"code\": \"123456\" }\n```",
        "x-freesbe-access": "signed-in",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/mfa/email": {
      "post": {
        "operationId": "postApiMeMfaEmail",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Email a code to verify with.",
        "description": "Email a code to verify with. Not after signing in with an emailed code. Answers 204.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/mfa/email/verify": {
      "post": {
        "operationId": "postApiMeMfaEmailVerify",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Verify with the emailed code.",
        "description": "Verify with the emailed `code`. Answers like `GET /api/me`.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/mfa/password": {
      "post": {
        "operationId": "postApiMeMfaPassword",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Verify with your password, only after signing in with an emailed code.",
        "description": "Verify with your `password`, only after signing in with an emailed code. Answers like `GET /api/me`.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/mfa/passkey/options": {
      "post": {
        "operationId": "postApiMeMfaPasskeyOptions",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "WebAuthn options to verify with one of your passkeys.",
        "description": "WebAuthn options to verify with one of your passkeys.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/mfa/passkey": {
      "post": {
        "operationId": "postApiMeMfaPasskey",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Verify with the passkey's assertion.",
        "description": "Verify with the passkey's assertion.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/mfa/phone": {
      "post": {
        "operationId": "postApiMeMfaPhone",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Ask your phones to approve this session's second step.",
        "description": "Ask your phones to approve this session's second step. Show the `number`: the phone asks for it among three. Lasts two minutes; at most two can wait at once, and none for 15 minutes after the phone reports one that wasn't you.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"id\": \"01JC8Z6Y0QH3W8T2M5N7P9R1S3\", \"number\": 47, \"expiresAt\": 1792771320000, \"phones\": 1 }\n```",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/mfa/phone/{id}": {
      "post": {
        "operationId": "postApiMeMfaPhoneById",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Whether the phone answered: pending, denied, expired, or approved with me (like GET /api/me), which verifies this sessio",
        "description": "Whether the phone answered: `pending`, `denied`, `expired`, or `approved` with `me` (like `GET /api/me`), which verifies this session once. `DELETE` stops waiting.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"status\": \"pending\" }\n```",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/auth/phone": {
      "post": {
        "operationId": "postApiAuthPhone",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Sign in with no password: ask that person's phones to approve.",
        "description": "Sign in with no password: ask that person's phones to approve. Show the `number` and keep the `secret` for the checks. Answers the same whether or not the address has an account or a phone, so it doesn't reveal who does. `DELETE` with `{ id, secret }` stops waiting.\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample request:\n\n```json\n{ \"email\": \"dana@northwind.example\" }\n```\n\nExample answer:\n\n```json\n{ \"id\": \"01JC8Z6Y0QH3W8T2M5N7P9R1S3\", \"secret\": \"…\", \"number\": 63, \"expiresAt\": 1792771320000 }\n```",
        "x-freesbe-access": "public",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/auth/phone/check": {
      "post": {
        "operationId": "postApiAuthPhoneCheck",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Whether the phone answered: pending or denied, or approved with auth (like login), which signs in once.",
        "description": "Whether the phone answered: `pending` or `denied`, or `approved` with `auth` (like login), which signs in once. Counts as the second step. Stop asking at `expiresAt`.\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample request:\n\n```json\n{ \"id\": \"01JC8Z6Y0QH3W8T2M5N7P9R1S3\", \"secret\": \"…\", \"wantToken\": true }\n```\n\nExample answer:\n\n```json\n{ \"status\": \"pending\" }\n```",
        "x-freesbe-access": "public",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/me/approver-devices": {
      "get": {
        "operationId": "getApiMeApproverDevices",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Your phones that approve sign-ins.",
        "description": "Your phones that approve sign-ins. `DELETE /api/me/approver-devices/{id}` removes one (from another device, it needs a second step verified in the last hour, like other sign-in methods). Phones are set up in the mobile app.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"devices\": [{ \"id\": \"01JC8Z…\", \"name\": \"iPhone\", \"platform\": \"ios\", \"createdAt\": 1792540320000, \"lastUsedAt\": 1792760520000, \"current\": false }] }\n```",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/mfa/launch": {
      "post": {
        "operationId": "postApiMeMfaLaunch",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "The app calls this each time it opens.",
        "description": "The app calls this each time it opens. For workspaces that ask each time Freesbe opens, it forgets this session's verification.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/totp": {
      "post": {
        "operationId": "postApiMeTotp",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Start setting up an authenticator app: a new Base32 secret and an otpauth:// uri for a QR code.",
        "description": "Start setting up an authenticator app: a new Base32 `secret` and an `otpauth://` `uri` for a QR code.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"secret\": \"JBSWY3DPEHPK3PXP…\", \"uri\": \"otpauth://totp/Freesbe:deploy-bot%40northwind.example?secret=…\" }\n```",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiMeTotp",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Turn the authenticator app on with a first code from it.",
        "description": "Turn the authenticator app on with a first `code` from it. This counts as verifying. Answers like `GET /api/me`.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample request:\n\n```json\n{ \"code\": \"123456\" }\n```",
        "x-freesbe-access": "signed-in",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiMeTotp",
        "tags": [
          "Sessions and multi-factor authentication"
        ],
        "summary": "Remove the authenticator app.",
        "description": "Remove the authenticator app. Answers 204.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces": {
      "get": {
        "operationId": "getApiWorkspaces",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "The workspaces you belong to, with your role in each.",
        "description": "The workspaces you belong to, with your `role` in each.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspaces",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "Create a workspace and become its owner, when canCreateWorkspaces is true.",
        "description": "Create a workspace and become its owner, when `canCreateWorkspaces` is true. `region` is where its data is stored: `eu` or `us` (guaranteed to stay in the region), or `apac` or `oc` (Asia-Pacific or Oceania, placed close to the team without that guarantee; see Data residency in the guides). It can't be changed afterwards; without it, the region closest to where the request comes from is used. The workspace's `region` is null for workspaces made before regions. Answers 201.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample request:\n\n```json\n{ \"name\": \"Northwind Traders\", \"region\": \"eu\" }\n```\n\nExample answer:\n\n```json\n{\n  \"workspace\": {\n    \"id\": \"01JB8Q…\",\n    \"name\": \"Northwind Traders\",\n    \"slug\": \"northwind\",\n    \"role\": \"admin\",\n    \"requireSso\": null,\n    \"identityProvider\": { \"id\": \"nwOkta7Rk2Qm9Xc4Lp8Vt\", \"preset\": \"okta\" },\n    \"requireMfa\": true,\n    \"mfaReverifyHours\": 168,\n    \"adminCenterMfa\": \"strong\",\n    \"logoUrl\": \"/api/workspace-logos/01JB8Q…/01JBA…\",\n    \"recordings\": true,\n    \"recordingRetentionDays\": 90,\n    \"recordingControl\": \"starter\",\n    \"lobbyRemindMin\": 2,\n    \"lobbyEmailMin\": 5,\n    \"editWindowMin\": null,\n    \"membersCanDelete\": true,\n    \"membersCanLeave\": true,\n    \"adminsCanDelete\": true,\n    \"plan\": \"business\",\n    \"lobbyMusic\": \"lofi\",\n    \"readReceipts\": \"small\",\n    \"readReceiptsOptOut\": true,\n    \"showReadReceipts\": true\n  }\n}\n```",
        "x-freesbe-access": "signed-in",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}": {
      "get": {
        "operationId": "getApiWorkspacesByW",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "One workspace.",
        "description": "One workspace.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{\n  \"workspace\": {\n    \"id\": \"01JB8Q…\",\n    \"name\": \"Northwind Traders\",\n    \"slug\": \"northwind\",\n    \"role\": \"admin\",\n    \"requireSso\": null,\n    \"identityProvider\": { \"id\": \"nwOkta7Rk2Qm9Xc4Lp8Vt\", \"preset\": \"okta\" },\n    \"requireMfa\": true,\n    \"mfaReverifyHours\": 168,\n    \"adminCenterMfa\": \"strong\",\n    \"logoUrl\": \"/api/workspace-logos/01JB8Q…/01JBA…\",\n    \"recordings\": true,\n    \"recordingRetentionDays\": 90,\n    \"recordingControl\": \"starter\",\n    \"lobbyRemindMin\": 2,\n    \"lobbyEmailMin\": 5,\n    \"editWindowMin\": null,\n    \"membersCanDelete\": true,\n    \"membersCanLeave\": true,\n    \"adminsCanDelete\": true,\n    \"plan\": \"business\",\n    \"lobbyMusic\": \"lofi\",\n    \"readReceipts\": \"small\",\n    \"readReceiptsOptOut\": true,\n    \"showReadReceipts\": true\n  }\n}\n```",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "team:read",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiWorkspacesByW",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "Change the name, require single sign-on (requireSso: google, microsoft, any, sso:<id> for the workspace's own identity p",
        "description": "Change the `name`, require single sign-on (`requireSso`: `google`, `microsoft`, `any`, `sso:<id>` for the workspace's own identity provider once its test sign-in went through, or null; the provider itself is set up in the Admin Center, not through the API), require multi-factor authentication (`requireMfa`, and `mfaReverifyHours`: null, 0, 12, 24 or 168), choose what opening the Admin Center takes (`adminCenterMfa`: `strong`, the default, for a passkey, a phone approval or an authenticator app code, or `any` second step; signed-in sessions only, never a token, and `any` needs a strong step verified in the last 15 minutes, `strong_mfa_required` otherwise), allow huddle and meeting `recordings`, give them `transcripts` and AI notes, transcribe every huddle (`autoTranscribe`), share meetings' notes outside the workspace by a private link (`guestTranscripts`, with `guestTranscriptEmails` to email meeting guests theirs automatically, `guestTranscriptDays`: the longest a link works, 1, 3, 7, 14 or 30, and `guestTranscriptVideo` to let links play the recording; turning these on asks people with an approving phone again), and delete recordings after `recordingRetentionDays` (30, 90, 365 or null), choose who can start and stop recordings (`recordingControl`: `everyone`, `starter`, the default, or `hosts`), and turn AI summaries and translations on or off (`ai`). `lobbyRemindMin` (0, 1, 2, 3, 5 or 10) and `lobbyEmailMin` (0, 5, 10, 15 or 30) set when a meeting's hosts get a louder alert and an email about a guest waiting in its lobby; 0 is off. `lobbyMusic` picks what guests hear while they wait in a meeting's lobby: `lofi` (the default), `drift`, `sunny`, `classic`, `bossa` or `off`. `workflowBuilders` is `members` or `admins`: who can make workflows. `editWindowMin` (null for any time, 0 for never, 5, 60, 1440 or 10080) is how many minutes people can edit a message after sending it, `membersCanDelete` lets members and guests delete their own messages, and `adminsCanDelete` lets owners and admins delete anyone's message in a channel. `membersCanLeave` (on by default) lets members and admins leave the workspace on their own; guests always can. `readReceipts` is where people see who read their messages: `off` (the default), `small` (DMs and channels of up to 20 people) or `all` (bigger channels show a count, not names); `readReceiptsOptOut` lets each person turn their own off. `fileRules` sets which files `members` and `guests` can share: each has a `preset` (`any`, `safe` or `only`), `kinds` for `only`, and `allow` and `block` extension lists (lists and `only` need Corporate or Enterprise; see File types in the guides). Your own session must meet a new sign-in rule first, so you can't lock yourself out.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"requireMfa\": true, \"mfaReverifyHours\": 168, \"recordingRetentionDays\": 90 }\n```\n\nExample answer:\n\n```json\n{\n  \"workspace\": {\n    \"id\": \"01JB8Q…\",\n    \"name\": \"Northwind Traders\",\n    \"slug\": \"northwind\",\n    \"role\": \"admin\",\n    \"requireSso\": null,\n    \"identityProvider\": { \"id\": \"nwOkta7Rk2Qm9Xc4Lp8Vt\", \"preset\": \"okta\" },\n    \"requireMfa\": true,\n    \"mfaReverifyHours\": 168,\n    \"adminCenterMfa\": \"strong\",\n    \"logoUrl\": \"/api/workspace-logos/01JB8Q…/01JBA…\",\n    \"recordings\": true,\n    \"recordingRetentionDays\": 90,\n    \"recordingControl\": \"starter\",\n    \"lobbyRemindMin\": 2,\n    \"lobbyEmailMin\": 5,\n    \"editWindowMin\": null,\n    \"membersCanDelete\": true,\n    \"membersCanLeave\": true,\n    \"adminsCanDelete\": true,\n    \"plan\": \"business\",\n    \"lobbyMusic\": \"lofi\",\n    \"readReceipts\": \"small\",\n    \"readReceiptsOptOut\": true,\n    \"showReadReceipts\": true\n  }\n}\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/read-receipts": {
      "put": {
        "operationId": "putApiWorkspacesByWReadReceipts",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "Turn your own read receipts on or off with show.",
        "description": "Turn your own read receipts on or off with `show`. Off works both ways: others don't see how far you read, and you don't see how far they did. Refused with 403 when admins turned `readReceiptsOptOut` off. Answers with the workspace, whose `showReadReceipts` is your choice.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"show\": false }\n```\n\nExample answer:\n\n```json\n{\n  \"workspace\": {\n    \"id\": \"01JB8Q…\",\n    \"name\": \"Northwind Traders\",\n    \"slug\": \"northwind\",\n    \"role\": \"admin\",\n    \"requireSso\": null,\n    \"identityProvider\": { \"id\": \"nwOkta7Rk2Qm9Xc4Lp8Vt\", \"preset\": \"okta\" },\n    \"requireMfa\": true,\n    \"mfaReverifyHours\": 168,\n    \"adminCenterMfa\": \"strong\",\n    \"logoUrl\": \"/api/workspace-logos/01JB8Q…/01JBA…\",\n    \"recordings\": true,\n    \"recordingRetentionDays\": 90,\n    \"recordingControl\": \"starter\",\n    \"lobbyRemindMin\": 2,\n    \"lobbyEmailMin\": 5,\n    \"editWindowMin\": null,\n    \"membersCanDelete\": true,\n    \"membersCanLeave\": true,\n    \"adminsCanDelete\": true,\n    \"plan\": \"business\",\n    \"lobbyMusic\": \"lofi\",\n    \"readReceipts\": \"small\",\n    \"readReceiptsOptOut\": true,\n    \"showReadReceipts\": true\n  }\n}\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/message-deletions": {
      "get": {
        "operationId": "getApiWorkspacesByWMessageDeletions",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "The last 100 messages owners and admins deleted for someone else, newest first: the channel, whose message it was (autho",
        "description": "The last 100 messages owners and admins deleted for someone else, newest first: the channel, whose message it was (`authorId`, or `authorName` for an app), who deleted it and when, whether it was in a thread and how many files it had. What it said isn't kept. An admin's `DELETE /api/messages/{m}/files/{f}` on someone else's message is listed too, with `fileName` set to the file's name (the message itself stays); `fileName` is null when the whole message was deleted.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{\n  \"deletions\": [\n    {\n      \"id\": \"01JB8ZK2W1E9R4M3T6Y7U8I9OP\",\n      \"channelId\": \"01JB8ZJ4Q6S0D2F4G6H8J0K2LM\",\n      \"channelName\": \"general\",\n      \"messageId\": \"01JB8ZK0A2B4C6D8E0F2G4H6JK\",\n      \"authorId\": \"01JB8ZH9N1P3Q5R7S9T1V3W5XY\",\n      \"authorName\": \"Tom Becker\",\n      \"deletedBy\": \"01JB8ZH7L9M1N3P5Q7R9S1T3UV\",\n      \"deletedAt\": 1792729800000,\n      \"inThread\": false,\n      \"fileCount\": 0,\n      \"fileName\": null\n    }\n  ]\n}\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/remote-control/sessions": {
      "get": {
        "operationId": "getApiWorkspacesByWRemoteControlSessions",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "The remote control log: the last 100 requests to control someone's shared screen, newest first.",
        "description": "The remote control log: the last 100 requests to control someone's shared screen, newest first. `kind` is `huddle` or `meeting` (a support session, where `sharerName` is the name the customer gave). `startedAt` is null when the request was declined or never answered, and `endReason` is `declined`, `expired`, `stopped`, `left`, `share_stopped` or `turned_off`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"sessions\": [ { \"id\": \"01JC4T…\", \"kind\": \"huddle\", \"channelId\": \"01JB8S…\", \"viewerId\": \"01JB8Q…\",\n  \"sharerId\": \"01JB8R…\", \"sharerName\": null, \"requestedAt\": 1792729800000, \"startedAt\": 1792729806000,\n  \"endedAt\": 1792730400000, \"endedBy\": \"01JB8R…\", \"endReason\": \"stopped\" } ] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/exports": {
      "get": {
        "operationId": "getApiWorkspacesByWExports",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "The workspace's last 20 data exports, newest first: what each covers (scope public or all, includeFiles, from, to), its ",
        "description": "The workspace's last 20 data exports, newest first: what each covers (`scope` `public` or `all`, `includeFiles`, `from`, `to`), its `status` (`queued`, `running`, `ready`, `failed` or `expired`), progress, and its zips (`parts`) once ready. `canExportAll` says whether you can include private channels and DMs, and `allNeeds` why not (`owner` or `plan`).\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"exports\": [ { \"id\": \"01JC5E…\", \"scope\": \"public\", \"includeFiles\": true, \"from\": null, \"to\": null,\n  \"status\": \"ready\", \"createdBy\": \"01JB8Q…\", \"createdAt\": 1792729800000, \"finishedAt\": 1792730100000,\n  \"expiresAt\": 1793334900000, \"error\": null,\n  \"progress\": { \"channels\": 84, \"channelsDone\": 84, \"messages\": 41250, \"files\": 312 },\n  \"parts\": [ { \"n\": 1, \"size\": 734003200 } ] } ], \"canExportAll\": false, \"allNeeds\": \"plan\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWExports",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "Start an export in Slack's export format.",
        "description": "Start an export in Slack's export format. `scope` `all` (private channels and DMs too) is for owners on plans that include it, and emails every owner. One export runs at a time (409) and a workspace can start one a day (429). `from` and `to` limit it to messages in that time.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"scope\": \"public\", \"includeFiles\": true, \"from\": null }\n```\n\nExample answer:\n\n```json\n{ \"export\": { \"id\": \"01JC5E…\", \"status\": \"queued\", … } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/exports/{id}/parts/{n}/link": {
      "post": {
        "operationId": "postApiWorkspacesByWExportsByIdPartsByNLink",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "Only for the admin who started the export: a download link for zip n of a ready export, working for 15 minutes without s",
        "description": "Only for the admin who started the export: a download link for zip `n` of a ready export, working for 15 minutes without signing in. Needs a second factor verified in the last 15 minutes: `mfa_required` otherwise. Each link is recorded in the audit log.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"url\": \"https://app.freesbe.net/api/export-downloads/kQ3…\", \"expiresAt\": 1792730700000 }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "n",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/audit": {
      "get": {
        "operationId": "getApiWorkspacesByWAudit",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "The audit log, newest first, 50 at a time: what owners and admins changed (action: settings.changed, member.role, member",
        "description": "The audit log, newest first, 50 at a time: what owners and admins changed (`action`: `settings.changed`, `member.role`, `member.deactivated`, `member.reactivated`, `invite.created`, `invite.emailed`, `invite.revoked`, `webhook.created`, `webhook.deleted`, `app.created`, `app.deleted`), who did it (`actorId`), to whom (`targetId`), what changed (`detail`) and the IP address. When `more` is true, pass the last entry's `id` as `?before=` for the next page. Entries are kept for a year.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{\n  \"entries\": [\n    {\n      \"id\": \"01JB8ZK2W1E9R4M3T6Y7U8I9OP\",\n      \"at\": 1792729800000,\n      \"actorId\": \"01JB8ZH7L9M1N3P5Q7R9S1T3UV\",\n      \"action\": \"member.role\",\n      \"targetId\": \"01JB8ZH9N1P3Q5R7S9T1V3W5XY\",\n      \"detail\": { \"role\": \"admin\", \"from\": \"member\" },\n      \"ip\": \"203.0.113.24\"\n    }\n  ],\n  \"more\": false\n}\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/security-activity": {
      "get": {
        "operationId": "getApiWorkspacesByWSecurityActivity",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "Members' security activity, newest first, 50 at a time: their sign-ins, second steps, sign-outs and changes to how they ",
        "description": "Members' security activity, newest first, 50 at a time: their sign-ins, second steps, sign-outs and changes to how they sign in, only from when they joined the workspace. The same events and filters as `GET /api/me/security-activity`, plus `?user=` for one member.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"events\": [{ \"id\": \"…\", \"at\": 1792729800000, \"userId\": \"…\", \"event\": \"sign_in.failed\", \"detail\": { \"method\": \"password\" }, \"ip\": \"203.0.113.24\", \"country\": \"GB\", … }], \"more\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/logo": {
      "put": {
        "operationId": "putApiWorkspacesByWLogo",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "Set the logo: raw PNG, JPEG, GIF or WebP bytes with their Content-Type, up to 2 MB.",
        "description": "Set the logo: raw PNG, JPEG, GIF or WebP bytes with their `Content-Type`, up to 2 MB.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWLogo",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "Remove the logo, so the workspace's initials show.",
        "description": "Remove the logo, so the workspace's initials show.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspace-logos/{w}/{version}": {
      "get": {
        "operationId": "getApiWorkspaceLogosByWByVersion",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "The logo image.",
        "description": "The logo image. `logoUrl` points here; the version can't be guessed, so only people who saw the URL can fetch it.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "version",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/boot": {
      "get": {
        "operationId": "getApiWorkspacesByWBoot",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "Everything the app needs to start in one call: you, the workspace, members, your channels and DMs with unread counts, st",
        "description": "Everything the app needs to start in one call: you, the workspace, members, your channels and DMs with unread counts, statuses, presence, live huddles, the event cursor `seq` for the WebSocket, and which features are on.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/cache-key": {
      "get": {
        "operationId": "getApiWorkspacesByWCacheKey",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "The key the app encrypts its local cache of the workspace with.",
        "description": "The key the app encrypts its local cache of the workspace with. It changes when you lose access.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/allowance": {
      "get": {
        "operationId": "getApiWorkspacesByWAllowance",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "The usage period's video, and storage, against the workspace's limits (period: its first day start, last day end, and re",
        "description": "The usage period's video, and storage, against the workspace's limits (`period`: its first day `start`, last day `end`, and `resets`, the billing day allowances start again, as UTC dates), and why cameras and screen sharing are paused, if they are (`paused`, `cap`, `allowance` or `budget`, the workspace's spending limit).\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"period\": { \"start\": \"2026-11-14\", \"end\": \"2026-12-13\", \"resets\": \"2026-12-14\" },\n  \"videoGb\": 41.2, \"videoGbLimit\": 200, \"storageGb\": 3.8,\n  \"storageGbLimit\": 50, \"videoPaused\": null }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/billing": {
      "get": {
        "operationId": "getApiWorkspacesByWBilling",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "The workspace's plan and subscription, add-ons (addOns) and the usage period's use past the plan's allowances (usage, ch",
        "description": "The workspace's plan and subscription, add-ons (`addOns`) and the usage period's use past the plan's allowances (`usage`, charged when the period ends; `usagePeriod` has its `start`, `end` and `resets` days, from the workspace's billing day): `status` (`none`, `trialing`, `active`, `past_due`, `canceled` or `comped`), yearly or monthly `interval`, `seats` (active members, not guests) and `seatsBilled`, what the workspace gets (`limits` and `features`, its plan's with any changes Freesbe made for it), the plans on sale (`plans`, from the pricing catalog), when the trial or period ends, and up to 24 invoices, newest first. Amounts are in cents. `enforced` says whether the plan's limits apply yet. `history` is the same as `GET /api/workspaces/{w}/billing/history`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"plan\": \"business\", \"planName\": \"Business\", \"status\": \"active\",\n  \"interval\": \"year\", \"seats\": 8, \"seatsBilled\": 8,\n  \"limits\": { \"members\": 500, \"historyDays\": null, ... }, \"features\": [\"groupVideo\", ...],\n  \"plans\": [{ \"id\": \"free\", \"name\": \"Free\", \"prices\": {}, ... }, ...],\n  \"trialEndsAt\": null, \"periodEndsAt\": 1803945600000, \"canceling\": false,\n  \"pastDueSince\": null, \"invoices\": [{ \"id\": \"in_1\", \"number\": \"NWT-0001\",\n  \"status\": \"paid\", \"total\": 38400, \"tax\": 0, \"currency\": \"usd\", ... }],\n  \"paymentsOn\": true, \"enforced\": false,\n  \"addOns\": [{ \"id\": \"phone\", \"name\": \"Phone system\", \"per\": \"seat\", \"units\": null,\n    \"prices\": { \"month\": 1000, \"year\": 9600 }, \"quantity\": 1, \"billedQuantity\": 8,\n    \"needs\": [], ... }],\n  \"usage\": [{ \"id\": \"phone_minutes\", \"name\": \"Extra phone minutes\", \"unit\": \"minutes\",\n    \"used\": 8420, \"included\": 8000, \"extra\": 420, \"price\": 2, \"per\": 1, \"amount\": 840 }],\n  \"usagePeriod\": { \"start\": \"2026-11-14\", \"end\": \"2026-12-13\", \"resets\": \"2026-12-14\" },\n  \"history\": { \"hidden\": null, \"upcoming\": null } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/billing/history": {
      "get": {
        "operationId": "getApiWorkspacesByWBillingHistory",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "Messages the plan's history hides (Free shows the last 90 days; older ones are kept, never deleted).",
        "description": "Messages the plan's history hides (Free shows the last 90 days; older ones are kept, never deleted). `hidden`: hidden now, those from before `before`. `upcoming`: when older messages will start being hidden (`at`), why (`canceling`, `unpaid`, `trial` or `starting`) and which (`before`). Each is null unless there are messages it applies to.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"hidden\": null, \"upcoming\": { \"at\": 1803945600000, \"reason\": \"canceling\",\n  \"days\": 90, \"before\": 1796169600000 } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/billing/add-ons/{addOn}": {
      "put": {
        "operationId": "putApiWorkspacesByWBillingAddOnsByAddOn",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "Adds an add-on to the workspace's subscription, changes how many (for add-ons bought by the unit, like call center agent",
        "description": "Adds an add-on to the workspace's subscription, changes how many (for add-ons bought by the unit, like call center agents), or removes it with `quantity` 0. Add-ons charged per person or counted by Freesbe (phone numbers) take 1 or 0. 409 without a paid plan, when it needs another add-on first, or when the card is declined. Returns the Billing page's data.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"quantity\": 3 }\n```\n\nExample answer:\n\n```json\n{ \"plan\": \"business\", \"addOns\": [...], ... }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "addOn",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/billing/checkout": {
      "post": {
        "operationId": "postApiWorkspacesByWBillingCheckout",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "Where to send an admin to pay for plan (a plan in the catalog that's bought by card, like business) yearly or monthly (i",
        "description": "Where to send an admin to pay for `plan` (a plan in the catalog that's bought by card, like `business`) yearly or monthly (`interval`: `year` or `month`): Stripe Checkout, or, when the workspace already pays, Stripe's page to confirm the switch. `returnPath` is the app page to come back to. 503 until payments are set up on the server.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"plan\": \"business\", \"interval\": \"year\", \"returnPath\": \"/northwind/c/general\" }\n```\n\nExample answer:\n\n```json\n{ \"url\": \"https://checkout.stripe.com/c/pay/cs_…\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/billing/portal": {
      "post": {
        "operationId": "postApiWorkspacesByWBillingPortal",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "A link to Stripe's billing portal for the workspace: card, billing details, invoices and cancelling.",
        "description": "A link to Stripe's billing portal for the workspace: card, billing details, invoices and cancelling. 409 when the workspace has never paid.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"returnPath\": \"/northwind/c/general\" }\n```\n\nExample answer:\n\n```json\n{ \"url\": \"https://billing.stripe.com/p/session/…\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/catalog": {
      "get": {
        "operationId": "getApiCatalog",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "The published pricing catalog: every plan with its prices in cents per person (month, year), limits (null is no limit) a",
        "description": "The published pricing catalog: every plan with its prices in cents per person (`month`, `year`), limits (null is no limit) and features, plus add-ons and metered prices. Cached for 5 minutes.\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample answer:\n\n```json\n{ \"catalog\": { \"version\": 3, \"currency\": \"usd\", \"defaultPlan\": \"free\",\n  \"plans\": [{ \"id\": \"business\", \"name\": \"Business\", \"prices\": { \"month\": 500, \"year\": 4800 },\n  \"limits\": { \"members\": 500, ... }, \"features\": [\"groupVideo\", ...], ... }, ...],\n  \"addOns\": [], \"meters\": [...] } }\n```",
        "x-freesbe-access": "public",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/internal/status-signals": {
      "get": {
        "operationId": "getApiInternalStatusSignals",
        "tags": [
          "Workspaces and settings"
        ],
        "summary": "For [status.freesbe.net](https://status.freesbe.net/) only: the counts it turns into the AI, email, webhook and phone ra",
        "description": "For [status.freesbe.net](https://status.freesbe.net/) only: the counts it turns into the AI, email, webhook and phone rates, to a caller whose `X-Status-Secret` header matches the status page's shared secret. Anyone else gets 401. What the status page itself shows is at [status.freesbe.net/api/summary.json](https://status.freesbe.net/api/summary.json) and `/api/status.json`, open to everyone.\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample answer:\n\n```json\n{ \"at\": 1762156800000, \"ai\": { \"failed\": 1, \"total\": 840 }, \"email\": { \"failed\": 0, \"total\": 312 },\n  \"webhooks\": { \"failed\": 2, \"total\": 1460 }, \"phone\": { \"failed\": 0, \"total\": 212 } }\n```",
        "x-freesbe-access": "public",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/members": {
      "get": {
        "operationId": "getApiWorkspacesByWMembers",
        "tags": [
          "People and roles"
        ],
        "summary": "Everyone in the workspace, deactivated people included.",
        "description": "Everyone in the workspace, deactivated people included. Guests get the people they share channels with. On a phone system from Freesbe, `extension` is the number colleagues dial to reach them.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"members\": [ { \"userId\": \"01JB8R…\", \"name\": \"Priya Raman\", \"role\": \"member\", \"title\": \"Support lead\", \"extension\": \"102\", … } ] }\n```",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "users:read",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/members/{userId}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWMembersByUserId",
        "tags": [
          "People and roles"
        ],
        "summary": "Anyone can set their own title.",
        "description": "Anyone can set their own `title`. Admins change anyone's title, make someone an `admin` or `member` (a guest made a member joins the whole workspace), and set `deactivated`. People admins change titles and `deactivated` for members and guests, never admins. The owner's role can't change this way (see `/owner`), and nobody can deactivate themselves. Admins (and people admins, for members and guests) can also set someone's account `name` and `email`, only when their address and the new one are at one of the workspace's verified email domains, and never their own or the owner's; the old address is told about a new one. Changing a role, `deactivated` or `email` needs a recent second step.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"role\": \"admin\" }\n```\n\nExample answer:\n\n```json\n{\n  \"member\": {\n    \"userId\": \"01JB8R…\",\n    \"name\": \"Priya Raman\",\n    \"email\": \"priya@northwind.example\",\n    \"avatarUrl\": null,\n    \"timezone\": \"Asia/Singapore\",\n    \"role\": \"member\",\n    \"title\": \"Support lead\",\n    \"deactivated\": false,\n    \"pending\": false,\n    \"company\": null\n  }\n}\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/members/{userId}/admin-roles": {
      "put": {
        "operationId": "putApiWorkspacesByWMembersByUserIdAdminRoles",
        "tags": [
          "People and roles"
        ],
        "summary": "Gives a member limited admin roles, replacing what they had: billing, phone, people and helpdesk, each opening its own p",
        "description": "Gives a member limited admin roles, replacing what they had: `billing`, `phone`, `people` and `helpdesk`, each opening its own part of the Admin Center. An empty list takes them away. Members only (owners and admins can do it all); giving roles needs Corporate or Enterprise. Signed-in browser sessions only. The member's `adminRoles` lists them, and the workspace's `adminRoles` says which ones work for you now.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"roles\": [\"phone\", \"billing\"] }\n```\n\nExample answer:\n\n```json\n{\n  \"member\": {\n    \"userId\": \"01JB8R…\",\n    \"name\": \"Priya Raman\",\n    \"email\": \"priya@northwind.example\",\n    \"avatarUrl\": null,\n    \"timezone\": \"Asia/Singapore\",\n    \"role\": \"member\",\n    \"title\": \"Support lead\",\n    \"deactivated\": false,\n    \"pending\": false,\n    \"company\": null\n  }\n}\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/members/{userId}/sessions": {
      "get": {
        "operationId": "getApiWorkspacesByWMembersByUserIdSessions",
        "tags": [
          "People and roles"
        ],
        "summary": "Where a member is signed in, for signing out a lost or stolen phone or computer: each session's device (client: web, des",
        "description": "Where a member is signed in, for signing out a lost or stolen phone or computer: each session's device (`client`: `web`, `desktop`, `mobile` or `script`, with `browser` and `os`), versions (`appVersion` for the Freesbe apps, `browserVersion`, `osVersion`), sign-in method, IP address and rough location, when it started and was last used. Owners, admins, and members with the People or Helpdesk admin role (members and guests only). `signOut` says what you can do: `now`, `ask` (the owner: a second admin approves) or `no`. For the owner, `request` is the open request to sign them out, if any, and `approvers` counts the admins who could approve one.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{\n  \"sessions\": [\n    { \"id\": \"…\", \"client\": \"mobile\", \"os\": \"iOS\", \"appVersion\": \"1.0.0\", \"osVersion\": \"18.1\",\n      \"method\": \"passkey\", \"createdAt\": …, \"lastActiveAt\": …,\n      \"ip\": \"192.0.2.88\", \"location\": \"Lisbon, Portugal\", … }\n  ],\n  \"signOut\": \"now\", \"request\": null, \"approvers\": 0\n}\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWMembersByUserIdSessions",
        "tags": [
          "People and roles"
        ],
        "summary": "Signs a member out everywhere: every session ends in every workspace they use, their phones stop getting notifications, ",
        "description": "Signs a member out everywhere: every session ends in every workspace they use, their phones stop getting notifications, and this workspace's calendar add-ins sign out. They can sign in again. Not yourself, and not an owner of this or any other workspace (see `sign-out-requests`). They get an email, their security activity shows it, and the audit log records it. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/members/{userId}/sessions/{id}": {
      "delete": {
        "operationId": "deleteApiWorkspacesByWMembersByUserIdSessionsById",
        "tags": [
          "People and roles"
        ],
        "summary": "Signs one of a member's sessions out, like the one above.",
        "description": "Signs one of a member's sessions out, like the one above. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/members/{userId}/sign-out-requests": {
      "post": {
        "operationId": "postApiWorkspacesByWMembersByUserIdSignOutRequests",
        "tags": [
          "People and roles"
        ],
        "summary": "Asks to sign the owner out of one session (sessionId) or every one (sessionId: null), with a reason the approver sees.",
        "description": "Asks to sign the owner out of one session (`sessionId`) or every one (`sessionId: null`), with a `reason` the approver sees. No admin signs the owner out alone: another admin approves within 24 hours, and the other admins get an email. One open request at a time (409).\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"sessionId\": null, \"reason\": \"Maya's phone was stolen\" }\n```\n\nExample answer:\n\n```json\n{ \"request\": { \"id\": \"…\", \"userId\": \"…\", \"sessionId\": null, \"requestedBy\": \"…\", \"reason\": \"…\", \"createdAt\": …, \"expiresAt\": … } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/sign-out-requests/{id}": {
      "post": {
        "operationId": "postApiWorkspacesByWSignOutRequestsById",
        "tags": [
          "People and roles"
        ],
        "summary": "Approves a request to sign the owner out, which happens at once.",
        "description": "Approves a request to sign the owner out, which happens at once. Neither the admin who asked nor the owner can approve it. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWSignOutRequestsById",
        "tags": [
          "People and roles"
        ],
        "summary": "Declines a request to sign the owner out, or withdraws your own.",
        "description": "Declines a request to sign the owner out, or withdraws your own. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/owner": {
      "post": {
        "operationId": "postApiWorkspacesByWOwner",
        "tags": [
          "People and roles"
        ],
        "summary": "Hands the workspace to another admin or member who has signed in: they become the owner and you become an admin.",
        "description": "Hands the workspace to another admin or member who has signed in: they become the owner and you become an admin. Needs a second factor verified in the last 15 minutes (`mfa_required`). Answers 204.\n\nWho can call it: Its owner. Only the person it belongs to, such as the maker of a booking page.\n\nExample request:\n\n```json\n{ \"userId\": \"01JB8S…\" }\n```",
        "x-freesbe-access": "owner",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/leave": {
      "post": {
        "operationId": "postApiWorkspacesByWLeave",
        "tags": [
          "People and roles"
        ],
        "summary": "Leaves the workspace.",
        "description": "Leaves the workspace. Your messages stay, you lose access, and a new invite brings you back. The owner hands the workspace over first (`/owner`). Members and admins can't leave while the workspace turned off `membersCanLeave`; guests always can. Answers 204.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/closure": {
      "get": {
        "operationId": "getApiWorkspacesByWClosure",
        "tags": [
          "People and roles"
        ],
        "summary": "Whether the workspace is being closed (closure: stage closing until closesAt, then closed and read-only until purgeAt), ",
        "description": "Whether the workspace is being closed (`closure`: `stage` `closing` until `closesAt`, then `closed` and read-only until `purgeAt`), when the paid period ends, and the add-ons and phone system closing would end.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"closure\": null, \"periodEnd\": 1795322400000, \"addOns\": [\"Phone system\"], \"phoneSystem\": true }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWClosure",
        "tags": [
          "People and roles"
        ],
        "summary": "Closes the workspace: the plan stops renewing and it goes read-only when the paid period ends (at once on Free), then ev",
        "description": "Closes the workspace: the plan stops renewing and it goes read-only when the paid period ends (at once on Free), then everything in it is deleted 30 days later. `name` must be the workspace's name. Signed-in browser sessions only, with a second factor verified in the last 15 minutes (`mfa_required`). While closed, changes answer 403 `workspace_closed`; reading, exports, the billing portal and marking read still work. A workspace Freesbe's team holds answers the same way with 403 `workspace_on_hold` (waiting for documents) or `workspace_suspended`; under review only invites, phone numbers and customer inbox changes answer 403 `workspace_under_review` (see the account status guide).\n\nWho can call it: Its owner. Only the person it belongs to, such as the maker of a booking page.\n\nExample request:\n\n```json\n{ \"name\": \"Northwind Traders\", \"reason\": \"Moving to another tool\" }\n```\n\nExample answer:\n\n```json\n{ \"closure\": { \"stage\": \"closing\", \"requestedAt\": 1794112800000, \"closesAt\": 1795322400000, \"closedAt\": null, \"purgeAt\": null, \"by\": \"01JB8R…\" }, \"periodEnd\": 1795322400000, \"addOns\": [], \"phoneSystem\": false }\n```",
        "x-freesbe-access": "owner",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWClosure",
        "tags": [
          "People and roles"
        ],
        "summary": "Reopens a closing or closed workspace until its deletion starts.",
        "description": "Reopens a closing or closed workspace until its deletion starts. In the paid period the plan renews again; once closed it's back on Free. Needs a second factor verified in the last 15 minutes. Answers 204.\n\nWho can call it: Its owner. Only the person it belongs to, such as the maker of a booking page.",
        "x-freesbe-access": "owner",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/profiles": {
      "get": {
        "operationId": "getApiWorkspacesByWProfiles",
        "tags": [
          "People and roles"
        ],
        "summary": "Profile fields and everyone's values, by user id: department, location, manager (a user id), phone, pronouns and the wor",
        "description": "Profile fields and everyone's values, by user id: department, location, manager (a user id), phone, pronouns and the workspace's own fields. Dates are YYYY-MM-DD. Guests get only fields not hidden from guests, for the people they share channels with.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"fields\": [ { \"id\": \"01JC2…\", \"preset\": \"department\", \"label\": null, \"kind\": \"text\", \"options\": [], \"locked\": true, \"hiddenFromGuests\": true } ], \"profiles\": { \"01JB8R…\": { \"01JC2…\": \"Engineering\" } } }\n```",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "users:read",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/profile-fields": {
      "get": {
        "operationId": "getApiWorkspacesByWProfileFields",
        "tags": [
          "People and roles"
        ],
        "summary": "The workspace's profile fields, in the order profiles show them.",
        "description": "The workspace's profile fields, in the order profiles show them. `preset` is `pronouns`, `department`, `location`, `manager`, `phone` or null for a field admins added; `kind` is `text`, `link`, `date`, `person`, `options` or `phone`.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "users:read",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWProfileFields",
        "tags": [
          "People and roles"
        ],
        "summary": "Saves every field, in order: keep a field by its id, add one without an id, and leave one out to delete it with its valu",
        "description": "Saves every field, in order: keep a field by its `id`, add one without an `id`, and leave one out to delete it with its values. Set `label`, `options` (for `options` fields), `locked` (only admins fill it in) and `hiddenFromGuests`. Adding your own fields and locking fields need Business, Corporate or Enterprise.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"fields\": [ { \"id\": \"01JC2…\", \"kind\": \"text\", \"locked\": true }, { \"kind\": \"options\", \"label\": \"Region\", \"options\": [\"EMEA\", \"Americas\"] } ] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/teams": {
      "get": {
        "operationId": "getApiWorkspacesByWTeams",
        "tags": [
          "People and roles"
        ],
        "summary": "The workspace's teams, by name: who's on each one (memberIds, active people only) and the channels that keep it in them ",
        "description": "The workspace's teams, by name: who's on each one (`memberIds`, active people only) and the channels that keep it in them that you can see (`channelIds`). Guests get only the teams they're on.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"teams\": [ { \"id\": \"01JD4…\", \"name\": \"Sales\", \"description\": \"Account managers and sales leads\", \"memberIds\": [\"01JB8R…\"], \"channelIds\": [\"01JB9C…\"], \"createdAt\": 1793952000000 } ] }\n```",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "users:read",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWTeams",
        "tags": [
          "People and roles"
        ],
        "summary": "Makes a team: a name no other team has, an optional description, and the people on it (memberIds, guests too).",
        "description": "Makes a team: a `name` no other team has, an optional `description`, and the people on it (`memberIds`, guests too). Admins and people admins. Teams need Business, Corporate or Enterprise.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"name\": \"Sales\", \"description\": \"Account managers and sales leads\", \"memberIds\": [\"01JB8R…\", \"01JB8S…\"] }\n```\n\nExample answer:\n\n```json\n{ \"team\": { \"id\": \"01JD4…\", \"name\": \"Sales\", \"description\": \"Account managers and sales leads\", \"memberIds\": [\"01JB8R…\", \"01JB8S…\"], \"channelIds\": [\"01JB9C…\"], \"createdAt\": 1793952000000 } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/teams/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWTeamsById",
        "tags": [
          "People and roles"
        ],
        "summary": "Changes a team's name, description or the people on it: memberIds replaces the list.",
        "description": "Changes a team's `name`, `description` or the people on it: `memberIds` replaces the list. People put on the team join every channel that keeps it; people taken off leave the channels they're in only because of this team (not ones they joined themselves, were added to by hand, or have through another team). Deactivated people stay on it.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"memberIds\": [\"01JB8R…\", \"01JB8S…\", \"01JB8T…\"] }\n```\n\nExample answer:\n\n```json\n{ \"team\": { \"id\": \"01JD4…\", \"name\": \"Sales\", \"description\": \"Account managers and sales leads\", \"memberIds\": [\"01JB8R…\", \"01JB8S…\"], \"channelIds\": [\"01JB9C…\"], \"createdAt\": 1793952000000 } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWTeamsById",
        "tags": [
          "People and roles"
        ],
        "summary": "Deletes a team.",
        "description": "Deletes a team. Everyone stays in the channels it put them in; those channels stop keeping it. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/members/{userId}/profile": {
      "put": {
        "operationId": "putApiWorkspacesByWMembersByUserIdProfile",
        "tags": [
          "People and roles"
        ],
        "summary": "Sets someone's values by field id; null or an empty string clears one.",
        "description": "Sets someone's values by field id; null or an empty string clears one. Anyone can set their own fields that aren't locked; admins set anyone's. Answers with all of that person's values.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"values\": { \"01JC2…\": \"Engineering\", \"01JC3…\": \"01JB8S…\" } }\n```\n\nExample answer:\n\n```json\n{ \"values\": { \"01JC2…\": \"Engineering\", \"01JC3…\": \"01JB8S…\" } }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/profiles/bulk": {
      "post": {
        "operationId": "postApiWorkspacesByWProfilesBulk",
        "tags": [
          "People and roles"
        ],
        "summary": "Sets values for up to 500 people at once, as people: [{ userId, values }].",
        "description": "Sets values for up to 500 people at once, as `people: [{ userId, values }]`. Nothing is saved if any value doesn't fit its field.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"people\": [ { \"userId\": \"01JB8R…\", \"values\": { \"01JC2…\": \"Engineering\" } } ] }\n```\n\nExample answer:\n\n```json\n{ \"updated\": 1 }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/invites": {
      "get": {
        "operationId": "getApiWorkspacesByWInvites",
        "tags": [
          "Invites"
        ],
        "summary": "Open invite links and emailed invites, guest invites included.",
        "description": "Open invite links and emailed invites, guest invites included.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWInvites",
        "tags": [
          "Invites"
        ],
        "summary": "Create an invite link to share: role (member or admin), expiresInDays (default 7, at most 30), maxUses (null for unlimit",
        "description": "Create an invite link to share: `role` (`member` or `admin`), `expiresInDays` (default 7, at most 30), `maxUses` (null for unlimited). The `token` and `url` are only in this answer.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"role\": \"member\", \"expiresInDays\": 7, \"maxUses\": 10 }\n```\n\nExample answer:\n\n```json\n{\n  \"invite\": {\n    \"id\": \"01JBD2…\",\n    \"token\": \"q7Zr…\",\n    \"url\": \"https://app.freesbe.net/invite/q7Zr…\",\n    \"role\": \"member\",\n    \"channelIds\": [],\n    \"createdBy\": \"01JB8Q…\",\n    \"createdAt\": 1761200000000,\n    \"expiresAt\": 1761804800000,\n    \"maxUses\": 10,\n    \"uses\": 0,\n    \"sentTo\": null,\n    \"needsApproval\": false\n  }\n}\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/invites/email": {
      "post": {
        "operationId": "postApiWorkspacesByWInvitesEmail",
        "tags": [
          "Invites"
        ],
        "summary": "Email up to 50 people their own single-use invite, with an optional role.",
        "description": "Email up to 50 people their own single-use invite, with an optional `role`. Says who was sent one, who's already in, and who couldn't be emailed or was held back by the email limits.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"emails\": [\"sam@acme.example\", \"priya@northwind.example\"], \"role\": \"member\" }\n```\n\nExample answer:\n\n```json\n{\n  \"sent\": [\"sam@acme.example\"],\n  \"skipped\": [\"priya@northwind.example\"],\n  \"failed\": [],\n  \"limited\": []\n}\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/invites/teammates": {
      "get": {
        "operationId": "getApiWorkspacesByWInvitesTeammates",
        "tags": [
          "Invites"
        ],
        "summary": "Up to 8 people, by name, who share another workspace with you and aren't in this one or invited to it yet, matching q (p",
        "description": "Up to 8 people, by name, who share another workspace with you and aren't in this one or invited to it yet, matching `q` (part of a name or email address). Only full members of workspaces where you're a full member are listed, never guests. Each comes with the other workspaces you share. Apps can't call this.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"teammates\": [ { \"userId\": \"01JB8R…\", \"name\": \"Priya Shah\", \"email\": \"priya@northwind.example\", \"avatarUrl\": null, \"workspaces\": [\"Northwind Labs\"] } ] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/invites/{id}": {
      "delete": {
        "operationId": "deleteApiWorkspacesByWInvitesById",
        "tags": [
          "Invites"
        ],
        "summary": "Revoke an invite.",
        "description": "Revoke an invite. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/invites/{token}": {
      "get": {
        "operationId": "getApiInvitesByToken",
        "tags": [
          "Invites"
        ],
        "summary": "What an invite link shows: the workspace, who sent it, whether it still works, and for guest invites the channels and wh",
        "description": "What an invite link shows: the workspace, who sent it, whether it still works, and for guest invites the channels and whether someone has to let the guest in.\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample answer:\n\n```json\n{ \"workspace\": { \"id\": \"01JB8Q…\", \"name\": \"Northwind Traders\", \"logoUrl\": null },\n  \"invitedBy\": \"Dana Whitfield\", \"valid\": true, \"guest\": false, \"channels\": [], \"needsApproval\": false }\n```",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/invites/{token}/accept": {
      "post": {
        "operationId": "postApiInvitesByTokenAccept",
        "tags": [
          "Invites"
        ],
        "summary": "Join the workspace with an invite.",
        "description": "Join the workspace with an invite. A guest invite that needs approval answers 202 `{ \"workspace\": null, \"pending\": true }` until someone in the channel lets you in.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/email-domains": {
      "get": {
        "operationId": "getApiWorkspacesByWEmailDomains",
        "tags": [
          "Email domains"
        ],
        "summary": "The workspace's email domains, each with the TXT record that verifies it, and the people waiting for an admin to let the",
        "description": "The workspace's email domains, each with the TXT record that verifies it, and the people waiting for an admin to let them in.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWEmailDomains",
        "tags": [
          "Email domains"
        ],
        "summary": "Add a domain people at your company have addresses at.",
        "description": "Add a domain people at your company have addresses at. `role` is `member` or `admin`; `approval` makes an admin let each person in (always on for admins). Answers 201 with the domain and its TXT record.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"domain\": \"northwind.example\", \"role\": \"member\", \"approval\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/email-domains/{id}/check": {
      "post": {
        "operationId": "postApiWorkspacesByWEmailDomainsByIdCheck",
        "tags": [
          "Email domains"
        ],
        "summary": "Look for the domain's TXT record now instead of waiting for the next check.",
        "description": "Look for the domain's TXT record now instead of waiting for the next check.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/email-domains/{id}/dns": {
      "get": {
        "operationId": "getApiWorkspacesByWEmailDomainsByIdDns",
        "tags": [
          "Email domains"
        ],
        "summary": "Where the domain's DNS is managed and how to add its record there: the zone, its nameServers, the provider when Freesbe ",
        "description": "Where the domain's DNS is managed and how to add its record there: the `zone`, its `nameServers`, the `provider` when Freesbe knows it (like `namecheap`) and its `providerName`, the record's `host` relative to the zone, and `oneClick`, a link to the provider's Domain Connect page that adds the record, when the provider supports it.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"dns\": { \"zone\": \"northwind.example\", \"nameServers\": [\"dns1.registrar-servers.com\", \"dns2.registrar-servers.com\"], \"provider\": \"namecheap\", \"providerName\": \"Namecheap\", \"host\": \"_freesbe-verification\", \"oneClick\": null } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/email-domains/{id}": {
      "delete": {
        "operationId": "deleteApiWorkspacesByWEmailDomainsById",
        "tags": [
          "Email domains"
        ],
        "summary": "Remove a domain.",
        "description": "Remove a domain. People who already joined stay.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/guest-invites": {
      "post": {
        "operationId": "postApiChannelsByCGuestInvites",
        "tags": [
          "Guests"
        ],
        "summary": "An invite link that makes people guests in this channel.",
        "description": "An invite link that makes people guests in this channel. `approval` (default true) means someone in the channel lets each guest in. Also `expiresInDays` and `maxUses`. Not for DMs, and not for guests.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"approval\": true, \"expiresInDays\": 14, \"maxUses\": null }\n```\n\nExample answer:\n\n```json\n{ \"invite\": { \"role\": \"guest\", \"channelIds\": [\"01JB8S…\"], \"needsApproval\": true, \"url\": \"https://app.freesbe.net/invite/…\", … } }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/guest-invites/email": {
      "post": {
        "operationId": "postApiChannelsByCGuestInvitesEmail",
        "tags": [
          "Guests"
        ],
        "summary": "Email up to 50 people their own guest invite to the channel, with approval.",
        "description": "Email up to 50 people their own guest invite to the channel, with `approval`. Answers like the workspace email invites.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"emails\": [\"jordan@acme.example\"], \"approval\": false }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/invites/{token}/request": {
      "get": {
        "operationId": "getApiInvitesByTokenRequest",
        "tags": [
          "Guests"
        ],
        "summary": "Where your request to join through a guest invite stands: none, pending, approved (with the workspace) or declined.",
        "description": "Where your request to join through a guest invite stands: `none`, `pending`, `approved` (with the `workspace`) or `declined`.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/guest-requests/{id}/approve": {
      "post": {
        "operationId": "postApiGuestRequestsByIdApprove",
        "tags": [
          "Guests"
        ],
        "summary": "Let a waiting guest in.",
        "description": "Let a waiting guest in. The id is the `requestId` of the `guest_request` system message posted in the channel. Answers 204, or 409 when someone already answered.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/guest-requests/{id}/decline": {
      "post": {
        "operationId": "postApiGuestRequestsByIdDecline",
        "tags": [
          "Guests"
        ],
        "summary": "Turn a waiting guest away.",
        "description": "Turn a waiting guest away. Answers 204.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/channels": {
      "get": {
        "operationId": "getApiWorkspacesByWChannels",
        "tags": [
          "Channels"
        ],
        "summary": "Every public channel, plus your private channels and DMs, each with your unread state.",
        "description": "Every public channel, plus your private channels and DMs, each with your unread state. Guests get only their own.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"channels\": [ { \"id\": \"01JB8S…\", \"kind\": \"public\", \"name\": \"deploys\", \"unreadCount\": 3, … } ] }\n```",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "channels:read",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWChannels",
        "tags": [
          "Channels"
        ],
        "summary": "Create a channel: name, kind (public or private), an optional topic and the memberIds to add besides you.",
        "description": "Create a channel: `name`, `kind` (`public` or `private`), an optional `topic` and the `memberIds` to add besides you. Answers 201, or 409 when the name is taken.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"name\": \"acme-rollout\", \"kind\": \"private\", \"topic\": \"Acme Corp onboarding\", \"memberIds\": [\"01JB8R…\"] }\n```\n\nExample answer:\n\n```json\n{\n  \"channel\": {\n    \"id\": \"01JB8S…\",\n    \"workspaceId\": \"01JB8Q…\",\n    \"kind\": \"public\",\n    \"name\": \"deploys\",\n    \"topic\": \"Release notes and rollbacks\",\n    \"isGeneral\": false,\n    \"createdBy\": \"01JB8Q…\",\n    \"createdAt\": 1761200000000,\n    \"archivedAt\": null,\n    \"lastMessageId\": \"01JBC4…\",\n    \"lastMessageAt\": 1761210000000,\n    \"memberCount\": 14,\n    \"isMember\": true,\n    \"lastReadId\": \"01JBC1…\",\n    \"unread\": true,\n    \"unreadCount\": 3,\n    \"mentionCount\": 0,\n    \"muted\": false,\n    \"notify\": \"default\",\n    \"sound\": null\n  }\n}\n```",
        "x-freesbe-access": "full-members",
        "x-freesbe-app-scope": "channels:manage",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}": {
      "get": {
        "operationId": "getApiChannelsByC",
        "tags": [
          "Channels"
        ],
        "summary": "One channel, with your unread state and notification settings.",
        "description": "One channel, with your unread state and notification settings.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample answer:\n\n```json\n{\n  \"channel\": {\n    \"id\": \"01JB8S…\",\n    \"workspaceId\": \"01JB8Q…\",\n    \"kind\": \"public\",\n    \"name\": \"deploys\",\n    \"topic\": \"Release notes and rollbacks\",\n    \"isGeneral\": false,\n    \"createdBy\": \"01JB8Q…\",\n    \"createdAt\": 1761200000000,\n    \"archivedAt\": null,\n    \"lastMessageId\": \"01JBC4…\",\n    \"lastMessageAt\": 1761210000000,\n    \"memberCount\": 14,\n    \"isMember\": true,\n    \"lastReadId\": \"01JBC1…\",\n    \"unread\": true,\n    \"unreadCount\": 3,\n    \"mentionCount\": 0,\n    \"muted\": false,\n    \"notify\": \"default\",\n    \"sound\": null\n  }\n}\n```",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "channels:read",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiChannelsByC",
        "tags": [
          "Channels"
        ],
        "summary": "Change the topic (channel members, up to 250 characters) or the name (its creator or admins).",
        "description": "Change the `topic` (channel members, up to 250 characters) or the `name` (its creator or admins). Posts a note in the channel.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"topic\": \"Release notes, rollbacks and on-call\" }\n```",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "channels:manage",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/join": {
      "post": {
        "operationId": "postApiChannelsByCJoin",
        "tags": [
          "Channels"
        ],
        "summary": "Join a public channel.",
        "description": "Join a public channel.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "channels:join",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/leave": {
      "post": {
        "operationId": "postApiChannelsByCLeave",
        "tags": [
          "Channels"
        ],
        "summary": "Leave a channel.",
        "description": "Leave a channel. Not DMs, and not the general channel. Answers 204.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "channels:join",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/archive": {
      "post": {
        "operationId": "postApiChannelsByCArchive",
        "tags": [
          "Channels"
        ],
        "summary": "Archive a channel: it becomes read-only.",
        "description": "Archive a channel: it becomes read-only. Not the general channel.\n\nWho can call it: Creator or admins. The person who created the channel, or a workspace owner or admin.",
        "x-freesbe-access": "manager",
        "x-freesbe-app-scope": "channels:manage",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/unarchive": {
      "post": {
        "operationId": "postApiChannelsByCUnarchive",
        "tags": [
          "Channels"
        ],
        "summary": "Reopen an archived channel.",
        "description": "Reopen an archived channel.\n\nWho can call it: Creator or admins. The person who created the channel, or a workspace owner or admin.",
        "x-freesbe-access": "manager",
        "x-freesbe-app-scope": "channels:manage",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/auto-join": {
      "put": {
        "operationId": "putApiChannelsByCAutoJoin",
        "tags": [
          "Channels"
        ],
        "summary": "Keep the whole workspace in the channel: everyone who isn't in it yet joins now, and people who join the workspace later",
        "description": "Keep the whole workspace in the channel: everyone who isn't in it yet joins now, and people who join the workspace later are added on their own. `\"members\"` leaves guests out, `\"everyone\"` adds them too, `null` stops adding people (nobody is removed). The channel then carries `autoJoin`. Not the general channel, which already has everyone. People can still leave. Posts one note in the channel.\n\nWho can call it: Creator or admins. The person who created the channel, or a workspace owner or admin.\n\nExample request:\n\n```json\n{ \"autoJoin\": \"members\" }\n```\n\nExample answer:\n\n```json\n{\n  \"channel\": {\n    \"id\": \"01JB8S…\",\n    \"workspaceId\": \"01JB8Q…\",\n    \"kind\": \"public\",\n    \"name\": \"deploys\",\n    \"topic\": \"Release notes and rollbacks\",\n    \"isGeneral\": false,\n    \"createdBy\": \"01JB8Q…\",\n    \"createdAt\": 1761200000000,\n    \"archivedAt\": null,\n    \"lastMessageId\": \"01JBC4…\",\n    \"lastMessageAt\": 1761210000000,\n    \"memberCount\": 14,\n    \"isMember\": true,\n    \"lastReadId\": \"01JBC1…\",\n    \"unread\": true,\n    \"unreadCount\": 3,\n    \"mentionCount\": 0,\n    \"muted\": false,\n    \"notify\": \"default\",\n    \"sound\": null\n  }\n}\n```",
        "x-freesbe-access": "manager",
        "x-freesbe-app-scope": "channels:manage",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/teams/{teamId}": {
      "put": {
        "operationId": "putApiChannelsByCTeamsByTeamId",
        "tags": [
          "Channels"
        ],
        "summary": "Keeps a team in the channel: everyone on it who isn't in the channel yet joins now, and people put on the team later joi",
        "description": "Keeps a team in the channel: everyone on it who isn't in the channel yet joins now, and people put on the team later join too. The channel then lists it in `teamIds`. Not the general channel. People can still leave. Posts one note in the channel.\n\nWho can call it: Creator or admins. The person who created the channel, or a workspace owner or admin.\n\nExample answer:\n\n```json\n{\n  \"channel\": {\n    \"id\": \"01JB8S…\",\n    \"workspaceId\": \"01JB8Q…\",\n    \"kind\": \"public\",\n    \"name\": \"deploys\",\n    \"topic\": \"Release notes and rollbacks\",\n    \"isGeneral\": false,\n    \"createdBy\": \"01JB8Q…\",\n    \"createdAt\": 1761200000000,\n    \"archivedAt\": null,\n    \"lastMessageId\": \"01JBC4…\",\n    \"lastMessageAt\": 1761210000000,\n    \"memberCount\": 14,\n    \"isMember\": true,\n    \"lastReadId\": \"01JBC1…\",\n    \"unread\": true,\n    \"unreadCount\": 3,\n    \"mentionCount\": 0,\n    \"muted\": false,\n    \"notify\": \"default\",\n    \"sound\": null\n  }\n}\n```",
        "x-freesbe-access": "manager",
        "x-freesbe-app-scope": "channels:manage",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "teamId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiChannelsByCTeamsByTeamId",
        "tags": [
          "Channels"
        ],
        "summary": "Stops keeping the team in the channel.",
        "description": "Stops keeping the team in the channel. Nobody is removed; people it put there stay as if someone had added them.\n\nWho can call it: Creator or admins. The person who created the channel, or a workspace owner or admin.\n\nExample answer:\n\n```json\n{\n  \"channel\": {\n    \"id\": \"01JB8S…\",\n    \"workspaceId\": \"01JB8Q…\",\n    \"kind\": \"public\",\n    \"name\": \"deploys\",\n    \"topic\": \"Release notes and rollbacks\",\n    \"isGeneral\": false,\n    \"createdBy\": \"01JB8Q…\",\n    \"createdAt\": 1761200000000,\n    \"archivedAt\": null,\n    \"lastMessageId\": \"01JBC4…\",\n    \"lastMessageAt\": 1761210000000,\n    \"memberCount\": 14,\n    \"isMember\": true,\n    \"lastReadId\": \"01JBC1…\",\n    \"unread\": true,\n    \"unreadCount\": 3,\n    \"mentionCount\": 0,\n    \"muted\": false,\n    \"notify\": \"default\",\n    \"sound\": null\n  }\n}\n```",
        "x-freesbe-access": "manager",
        "x-freesbe-app-scope": "channels:manage",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "teamId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/members": {
      "get": {
        "operationId": "getApiChannelsByCMembers",
        "tags": [
          "Channels"
        ],
        "summary": "The user ids of everyone in the channel.",
        "description": "The user ids of everyone in the channel.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample answer:\n\n```json\n{ \"userIds\": [\"01JB8Q…\", \"01JB8R…\"] }\n```",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "channels:read",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiChannelsByCMembers",
        "tags": [
          "Channels"
        ],
        "summary": "Add people (userIds, up to 500) to a channel you're in.",
        "description": "Add people (`userIds`, up to 500) to a channel you're in. Not DMs; guests can't add people.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"userIds\": [\"01JB8T…\"] }\n```",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "channels:manage",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/members/{userId}": {
      "delete": {
        "operationId": "deleteApiChannelsByCMembersByUserId",
        "tags": [
          "Channels"
        ],
        "summary": "Remove someone from the channel.",
        "description": "Remove someone from the channel. Answers 204.\n\nWho can call it: Creator or admins. The person who created the channel, or a workspace owner or admin.",
        "x-freesbe-access": "manager",
        "x-freesbe-app-scope": "channels:manage",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/prefs": {
      "put": {
        "operationId": "putApiChannelsByCPrefs",
        "tags": [
          "Channels"
        ],
        "summary": "Your own settings for the channel: muted, notify (default, all, mentions or none) and the notification sound (null for y",
        "description": "Your own settings for the channel: `muted`, `notify` (`default`, `all`, `mentions` or `none`) and the notification `sound` (null for your default).\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"muted\": false, \"notify\": \"mentions\", \"sound\": \"marimba\" }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/section": {
      "put": {
        "operationId": "putApiChannelsByCSection",
        "tags": [
          "Channels"
        ],
        "summary": "Put the conversation in one of your sidebar sections, or back under Channels or Direct messages with null.",
        "description": "Put the conversation in one of your sidebar sections, or back under Channels or Direct messages with null. It comes back as `sectionId` on the channel. Answers 204. Apps can't use this.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"sectionId\": \"01JC2…\" }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/read": {
      "post": {
        "operationId": "postApiChannelsByCRead",
        "tags": [
          "Channels"
        ],
        "summary": "Mark the channel read up to lastReadId, the newest message you've seen.",
        "description": "Mark the channel read up to `lastReadId`, the newest message you've seen. It only moves forward, and your other devices clear the same unread state. Answers 204.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"lastReadId\": \"01JBC4…\" }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/unread": {
      "post": {
        "operationId": "postApiChannelsByCUnread",
        "tags": [
          "Channels"
        ],
        "summary": "Mark the channel unread from messageId on (a message in the channel, not a thread reply): the read cursor moves back to ",
        "description": "Mark the channel unread from `messageId` on (a message in the channel, not a thread reply): the read cursor moves back to just before it. Answers with the channel and its new `unreadCount` and `mentionCount`, and your other devices get a `read.updated` event with `counts`. Read receipts don't move back. Apps can't use this.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"messageId\": \"01JBC4…\" }\n```\n\nExample answer:\n\n```json\n{ \"channel\": { \"id\": \"01JBC2…\", \"lastReadId\": \"01JBC3…\", \"unread\": true, \"unreadCount\": 3, \"mentionCount\": 1, … } }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/receipts": {
      "get": {
        "operationId": "getApiChannelsByCReceipts",
        "tags": [
          "Channels"
        ],
        "summary": "Read receipts: how far the others in the conversation have read.",
        "description": "Read receipts: how far the others in the conversation have read. `mode` is `names`, `count` (a big channel: show how many, not who) or `off` (the workspace doesn't show receipts here, you turned yours off, or you aren't a member), with an empty `readers` list. A message was seen by everyone whose `lastReadId` is the same or newer. People who turned their receipts off aren't listed. Changes arrive as `receipt.updated` events.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample answer:\n\n```json\n{\n  \"mode\": \"names\",\n  \"readers\": [\n    { \"userId\": \"01JB8R…\", \"lastReadId\": \"01JBC4…\" },\n    { \"userId\": \"01JB8S…\", \"lastReadId\": null }\n  ]\n}\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/dms": {
      "post": {
        "operationId": "postApiWorkspacesByWDms",
        "tags": [
          "Direct messages"
        ],
        "summary": "Find or open the DM with exactly these people (userIds, up to 8 besides you).",
        "description": "Find or open the DM with exactly these people (`userIds`, up to 8 besides you). An empty list opens your own notes. Guests can only message people they share a channel with.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"userIds\": [\"01JB8R…\", \"01JB8T…\"] }\n```\n\nExample answer:\n\n```json\n{ \"channel\": { \"id\": \"01JBD9…\", \"kind\": \"dm\", \"name\": null, \"memberIds\": [\"01JB8Q…\", \"01JB8R…\", \"01JB8T…\"], … } }\n```",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "im:write",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/messages": {
      "get": {
        "operationId": "getApiChannelsByCMessages",
        "tags": [
          "Messages and threads"
        ],
        "summary": "A page of top-level messages, oldest first: the newest 50 by default.",
        "description": "A page of top-level messages, oldest first: the newest 50 by default. Page with `?before=<id>`, `?after=<id>` or `?from=<id>`, jump with `?around=<id>`, and set `?limit=` from 1 to 100. `hasMore` says there are more in that direction. On a plan with limited history (Free: 90 days), older messages are left out, here and everywhere else (search, threads, single messages answer 404): the page that reaches them has `historyHidden` (`days`, and `before`, the time messages before it are hidden) and `hasMore` false.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample answer:\n\n```json\n{ \"messages\": [ { \"id\": \"01JBC4…\", \"body\": \"Release *2.4* is out :tada:\", … } ], \"hasMore\": true }\n```",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "channels:history",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiChannelsByCMessages",
        "tags": [
          "Messages and threads"
        ],
        "summary": "Post a message, or a thread reply with threadRootId.",
        "description": "Post a message, or a thread reply with `threadRootId`. Attach up to 10 uploaded `fileIds`. Sending the same `clientMsgId` again returns the first message instead of posting twice. In a [customer inbox](#ref-inbox) conversation's thread the reply goes to the customer, unless `note` is true. You have to be in the channel. Apps can also send a card as Slack `blocks` or `attachments`, with `body` as its notification text. A message a person sent from the phone app or a browser on a phone or tablet comes back with `sentFrom: \"mobile\"`, here and wherever messages are listed; it's absent otherwise. Answers 201.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{\n  \"body\": \"Rollback done, <@01JB8R…> can you confirm?\",\n  \"threadRootId\": \"01JBC4…\",\n  \"clientMsgId\": \"deploy-8812\",\n  \"fileIds\": [\"01JBC9…\"]\n}\n```\n\nExample answer:\n\n```json\n{\n  \"message\": {\n    \"id\": \"01JBC4…\",\n    \"channelId\": \"01JB8S…\",\n    \"kind\": \"user\",\n    \"userId\": \"01JB8Q…\",\n    \"botName\": null,\n    \"botIcon\": null,\n    \"body\": \"Release *2.4* is out :tada:\",\n    \"attachments\": [],\n    \"files\": [],\n    \"system\": null,\n    \"threadRootId\": null,\n    \"replyCount\": 0,\n    \"lastReplyAt\": null,\n    \"replyUserIds\": [],\n    \"reactions\": [{ \"emoji\": \"🎉\", \"userIds\": [\"01JB8R…\"] }],\n    \"clientMsgId\": \"deploy-8812\",\n    \"createdAt\": 1761210000000,\n    \"editedAt\": null,\n    \"deletedAt\": null\n  }\n}\n```",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "chat:write",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/messages/{m}": {
      "get": {
        "operationId": "getApiMessagesByM",
        "tags": [
          "Messages and threads"
        ],
        "summary": "One message, with its reactions, files and thread counts.",
        "description": "One message, with its reactions, files and thread counts.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample answer:\n\n```json\n{\n  \"message\": {\n    \"id\": \"01JBC4…\",\n    \"channelId\": \"01JB8S…\",\n    \"kind\": \"user\",\n    \"userId\": \"01JB8Q…\",\n    \"botName\": null,\n    \"botIcon\": null,\n    \"body\": \"Release *2.4* is out :tada:\",\n    \"attachments\": [],\n    \"files\": [],\n    \"system\": null,\n    \"threadRootId\": null,\n    \"replyCount\": 0,\n    \"lastReplyAt\": null,\n    \"replyUserIds\": [],\n    \"reactions\": [{ \"emoji\": \"🎉\", \"userIds\": [\"01JB8R…\"] }],\n    \"clientMsgId\": \"deploy-8812\",\n    \"createdAt\": 1761210000000,\n    \"editedAt\": null,\n    \"deletedAt\": null\n  }\n}\n```",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "channels:history",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiMessagesByM",
        "tags": [
          "Messages and threads"
        ],
        "summary": "Edit your own message's body, within the workspace's editWindowMin.",
        "description": "Edit your own message's `body`, within the workspace's `editWindowMin`. Sets `editedAt`.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"body\": \"Release *2.4.1* is out :tada:\" }\n```",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "chat:write",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiMessagesByM",
        "tags": [
          "Messages and threads"
        ],
        "summary": "Delete your own message (unless the workspace turned off membersCanDelete; owners and admins always can), or, as an owne",
        "description": "Delete your own message (unless the workspace turned off `membersCanDelete`; owners and admins always can), or, as an owner or admin, anyone's message in a channel you can see (not in DMs, and not when `adminsCanDelete` is off). A thread's first message stays as a placeholder while it has replies, and a message an admin deleted stays as a placeholder with `deletedByAdmin: true`; admin deletions are logged. Answers 204.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "chat:write",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/messages/{m}/files/{f}": {
      "delete": {
        "operationId": "deleteApiMessagesByMFilesByF",
        "tags": [
          "Messages and threads"
        ],
        "summary": "Delete one file from a message, for whoever may delete the message (the same rules as DELETE /api/messages/{m}).",
        "description": "Delete one file from a message, for whoever may delete the message (the same rules as `DELETE /api/messages/{m}`). The rest of the message stays and everyone gets `message.updated`; a message left with no text, files, attachments or blocks is deleted as `DELETE /api/messages/{m}` would. An owner or admin deleting a file from someone else's message is logged in `GET /api/workspaces/{w}/message-deletions`. Answers 204.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "chat:write",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "f",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/messages/{m}/replies": {
      "get": {
        "operationId": "getApiMessagesByMReplies",
        "tags": [
          "Messages and threads"
        ],
        "summary": "A thread: its first message and up to 1,000 replies, oldest first, and lastReadId, how far you've read in it (replies af",
        "description": "A thread: its first message and up to 1,000 replies, oldest first, and `lastReadId`, how far you've read in it (replies after it are new; null if you never opened it). Pass `?channel=` with the thread's channel id when you know it: the answer comes back faster, and a thread that isn't in that channel is a 404.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample answer:\n\n```json\n{ \"root\": { \"id\": \"01JBC4…\", \"replyCount\": 2, … }, \"replies\": [ { … }, { … } ], \"lastReadId\": \"01JBC5…\" }\n```",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "channels:history",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/messages/{m}/thread-read": {
      "post": {
        "operationId": "postApiMessagesByMThreadRead",
        "tags": [
          "Messages and threads"
        ],
        "summary": "Mark the thread that m starts read up to lastReadId, its newest reply you've seen (or m itself).",
        "description": "Mark the thread that `m` starts read up to `lastReadId`, its newest reply you've seen (or `m` itself). It only moves forward, your other devices get a `thread.read` event, and your phones take the thread's notification away. Answers 204. Apps can't use this.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"lastReadId\": \"01JBC5…\" }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/messages/{m}/thread-unread": {
      "post": {
        "operationId": "postApiMessagesByMThreadUnread",
        "tags": [
          "Messages and threads"
        ],
        "summary": "Mark the thread that m starts unread from messageId on (one of its replies, or m itself for all of them): those replies ",
        "description": "Mark the thread that `m` starts unread from `messageId` on (one of its replies, or `m` itself for all of them): those replies count as new again until you open the thread. Your other devices get a `thread.read` event with `unread`. Apps can't use this.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"messageId\": \"01JBC5…\" }\n```\n\nExample answer:\n\n```json\n{ \"rootId\": \"01JBC4…\", \"lastReadId\": \"01JBC4…\" }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/messages/{m}/forward": {
      "post": {
        "operationId": "postApiMessagesByMForward",
        "tags": [
          "Messages and threads"
        ],
        "summary": "Forward a message you can read to a conversation you're in (channelId), with your own comment above it.",
        "description": "Forward a message you can read to a conversation you're in (`channelId`), with your own `comment` above it. The copy carries the original as an attachment with `forwarded` (`messageId`, `channelId`, `threadRootId`, `userId`, `channelName`, `createdAt`, `fileNames`); files stay in the original conversation. Forwarding a forward with no comment passes the original on.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"channelId\": \"01JB8T…\", \"comment\": \"Can we do this for Acme Corp too?\" }\n```\n\nExample answer:\n\n```json\n{ \"message\": { \"id\": \"01JBD7…\", \"body\": \"Can we do this for Acme Corp too?\",\n  \"attachments\": [ { \"authorName\": \"Lena Fischer\", \"text\": \"Northwind wants the blue tins\",\n  \"footer\": \"#sales\", \"forwarded\": { \"messageId\": \"01JBA2…\", \"channelId\": \"01JB8S…\", … } } ], … } }\n```",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "chat:write",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/messages/{m}/notify-anyway": {
      "post": {
        "operationId": "postApiMessagesByMNotifyAnyway",
        "tags": [
          "Messages and threads"
        ],
        "summary": "Notify anyway: alert the other person in a 1:1 DM about your own message even though they paused notifications.",
        "description": "Notify anyway: alert the other person in a 1:1 DM about your own message even though they paused notifications. Works for a day after sending and once a message; asking again does nothing. Answers 204. Not open to apps.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/messages/{m}/reactions/{emoji}": {
      "put": {
        "operationId": "putApiMessagesByMReactionsByEmoji",
        "tags": [
          "Reactions"
        ],
        "summary": "React with one emoji: the character itself, URL-encoded (%F0%9F%8E%89 for 🎉).",
        "description": "React with one emoji: the character itself, URL-encoded (`%F0%9F%8E%89` for 🎉). Doing it twice is harmless. Answers 204, or 409 when the message has all the different reactions it can take.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\ncurl -X PUT \"$API/api/messages/$MESSAGE/reactions/%F0%9F%8E%89\" \\\n  -H \"Authorization: Bearer $FREESBE_TOKEN\"\n```",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "reactions:write",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "emoji",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiMessagesByMReactionsByEmoji",
        "tags": [
          "Reactions"
        ],
        "summary": "Remove your reaction.",
        "description": "Remove your reaction. Answers 204.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "reactions:write",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "emoji",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/keywords": {
      "get": {
        "operationId": "getApiWorkspacesByWKeywords",
        "tags": [
          "Keyword alerts"
        ],
        "summary": "Your keywords.",
        "description": "Your keywords.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"keywords\": [\"Northwind\", \"price list\"] }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWKeywords",
        "tags": [
          "Keyword alerts"
        ],
        "summary": "Replace them.",
        "description": "Replace them. Blanks and repeats are dropped. Answers the saved list.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"keywords\": [\"Northwind\", \"price list\", \"launch\"] }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/messages/{m}/link-preview": {
      "delete": {
        "operationId": "deleteApiMessagesByMLinkPreview",
        "tags": [
          "Link previews"
        ],
        "summary": "Remove the preview of one link from your own message, for good: editing the message doesn't bring it back.",
        "description": "Remove the preview of one link from your own message, for good: editing the message doesn't bring it back. Answers 204.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "url",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/link-previews/{id}/image": {
      "get": {
        "operationId": "getApiLinkPreviewsByIdImage",
        "tags": [
          "Link previews"
        ],
        "summary": "A preview's picture, fetched by Freesbe.",
        "description": "A preview's picture, fetched by Freesbe. `thumbUrl` and `imageUrl` point here.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/emoji": {
      "get": {
        "operationId": "getApiWorkspacesByWEmoji",
        "tags": [
          "Custom emoji"
        ],
        "summary": "Every custom emoji, by name.",
        "description": "Every custom emoji, by name. The `url` loads the picture without signing in.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"emoji\": [ { \"name\": \"northwind\", \"url\": \"/api/custom-emoji/01JB…/01JC…\", \"createdBy\": \"01JB8R…\", \"createdAt\": 1767225600000 } ] }\n```",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "team:read",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWEmoji",
        "tags": [
          "Custom emoji"
        ],
        "summary": "Add one: raw PNG, JPEG, GIF or WebP bytes with their Content-Type, up to 256 KB.",
        "description": "Add one: raw PNG, JPEG, GIF or WebP bytes with their `Content-Type`, up to 256 KB. Guests can't. Answers 201 with `{ \"emoji\": { … } }`, or 409 when the name is taken. Apps can't add emoji.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\ncurl -X POST \"$API/api/workspaces/$WORKSPACE/emoji?name=northwind\" \\\n  -H \"Authorization: Bearer $FREESBE_TOKEN\" -H \"Content-Type: image/png\" --data-binary @northwind.png\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/emoji/{name}": {
      "delete": {
        "operationId": "deleteApiWorkspacesByWEmojiByName",
        "tags": [
          "Custom emoji"
        ],
        "summary": "Remove one you added; owners and admins can remove any.",
        "description": "Remove one you added; owners and admins can remove any. Reactions that used it stay and show its name. Answers 204.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/custom-emoji/{w}/{id}": {
      "get": {
        "operationId": "getApiCustomEmojiByWById",
        "tags": [
          "Custom emoji"
        ],
        "summary": "The picture.",
        "description": "The picture. Its id can't be guessed, and the picture behind it never changes.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/sidebar-sections": {
      "get": {
        "operationId": "getApiWorkspacesByWSidebarSections",
        "tags": [
          "Sidebar sections"
        ],
        "summary": "Your sections, in sidebar order.",
        "description": "Your sections, in sidebar order.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"sections\": [ { \"id\": \"01JC2…\", \"name\": \"Customers\", \"emoji\": \"🤝\" } ] }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWSidebarSections",
        "tags": [
          "Sidebar sections"
        ],
        "summary": "Add a section at the end.",
        "description": "Add a section at the end. Answers 201 with `{ \"section\": { … } }`.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"name\": \"Customers\", \"emoji\": \"🤝\" }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/sidebar-sections/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWSidebarSectionsById",
        "tags": [
          "Sidebar sections"
        ],
        "summary": "Rename it, or change its emoji (null for none).",
        "description": "Rename it, or change its emoji (null for none).\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"name\": \"Clients\" }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWSidebarSectionsById",
        "tags": [
          "Sidebar sections"
        ],
        "summary": "Delete it.",
        "description": "Delete it. Its conversations go back under Channels and Direct messages. Answers 204.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/sidebar-sections/{id}/position": {
      "put": {
        "operationId": "putApiWorkspacesByWSidebarSectionsByIdPosition",
        "tags": [
          "Sidebar sections"
        ],
        "summary": "Move it, counted from 0.",
        "description": "Move it, counted from 0. Answers the whole list.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"position\": 0 }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/sounds": {
      "get": {
        "operationId": "getApiWorkspacesByWSounds",
        "tags": [
          "Notification sounds"
        ],
        "summary": "The sounds you picked for messages from particular people, by user id.",
        "description": "The sounds you picked for messages from particular people, by user id.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"sounds\": { \"01JB8R…\": \"bell\" } }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/sounds/{userId}": {
      "put": {
        "operationId": "putApiWorkspacesByWSoundsByUserId",
        "tags": [
          "Notification sounds"
        ],
        "summary": "Pick the sound for messages from one person, or null for your default.",
        "description": "Pick the sound for messages from one person, or null for your default. Answers the whole list.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"sound\": \"bell\" }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/files": {
      "post": {
        "operationId": "postApiWorkspacesByWFiles",
        "tags": [
          "Files"
        ],
        "summary": "Upload the raw bytes with their Content-Type and a Content-Length, up to 50 MB.",
        "description": "Upload the raw bytes with their `Content-Type` and a `Content-Length`, up to 50 MB. Add `&width=&height=` for images when you know them. Answers 201, 403 `file_blocked` when the workspace's file type rules turn the file away (checked by name and by contents), or 413 when the workspace is out of storage.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\ncurl -X POST \"$API/api/workspaces/$WORKSPACE/files?name=q3-report.pdf\" \\\n  -H \"Authorization: Bearer $FREESBE_TOKEN\" \\\n  -H 'Content-Type: application/pdf' \\\n  --data-binary @q3-report.pdf\n```\n\nExample answer:\n\n```json\n{ \"file\": { \"id\": \"01JBC9…\", \"name\": \"q3-report.pdf\", \"mime\": \"application/pdf\",\n  \"size\": 482113, \"url\": \"/api/files/01JBC9…\" } }\n```",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "files:write",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/files/{id}": {
      "get": {
        "operationId": "getApiFilesById",
        "tags": [
          "Files"
        ],
        "summary": "Download a file from a channel you can see.",
        "description": "Download a file from a channel you can see. Images, audio, video and plain text open inline; add `?download=1` to always download. Supports `Range`.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "files:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/files/{id}/preview": {
      "get": {
        "operationId": "getApiFilesByIdPreview",
        "tags": [
          "Files"
        ],
        "summary": "The picture of a PDF's first page, or a photo's smaller copy (at most 2048 pixels on its longest side), when the file ha",
        "description": "The picture of a PDF's first page, or a photo's smaller copy (at most 2048 pixels on its longest side), when the file has one: its `previewUrl`. Same access as the file. Apps need `files:read`.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "files:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiFilesByIdPreview",
        "tags": [
          "Files"
        ],
        "summary": "Add a picture of a PDF's first page to a PDF you uploaded, before you send it: the raw PNG, JPEG or WebP bytes (at most ",
        "description": "Add a picture of a PDF's first page to a PDF you uploaded, before you send it: the raw PNG, JPEG or WebP bytes (at most 1 MB) with its `Content-Type`, and `?width=&height=` of the page so messages keep their shape. Freesbe doesn't draw PDFs itself; the apps do this as they upload one. For a photo (JPEG, PNG, WebP or HEIC, not GIF), send a smaller copy instead, at most 2048 pixels on its longest side and 2 MB: conversations show and copy it, and the file itself stays the original for downloads. A photo keeps its own `width` and `height`. Returns the file with its `previewUrl`. Apps need `files:write`.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"file\": { \"id\": \"01JBC9…\", \"name\": \"quote.pdf\", \"mime\": \"application/pdf\", \"size\": 48211,\n  \"width\": 595, \"height\": 842, \"url\": \"/api/files/01JBC9…\", \"previewUrl\": \"/api/files/01JBC9…/preview\" } }\n```",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "files:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/files": {
      "get": {
        "operationId": "getApiChannelsByCFiles",
        "tags": [
          "Files"
        ],
        "summary": "The files shared in a channel or DM you can see, threads included, newest first: what its Files tab shows.",
        "description": "The files shared in a channel or DM you can see, threads included, newest first: what its Files tab shows. Filter with `kind` (`images`, `media` for video and audio, `documents`, `other`) and `q` (part of the name). Up to `limit` (default 50, at most 100) at a time; pass `next` as `before` for older ones. Files of deleted messages aren't listed. Apps need `files:read`.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample answer:\n\n```json\n{ \"files\": [{ \"id\": \"01JBC9…\", \"name\": \"spring-catalog.pdf\", \"mime\": \"application/pdf\",\n  \"size\": 482113, \"url\": \"/api/files/01JBC9…\", \"messageId\": \"01JBC8…\", \"threadRootId\": null,\n  \"uploaderId\": \"01JB8Q…\", \"createdAt\": 1761238800000 }], \"next\": null }\n```",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "files:read",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/cabinet": {
      "get": {
        "operationId": "getApiWorkspacesByWCabinet",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "A list from Files: view=mine (My files), shared (Shared with me), workspace, recent or trash; or a folder's contents wit",
        "description": "A list from Files: `view=mine` (My files), `shared` (Shared with me), `workspace`, `recent` or `trash`; or a folder's contents with `folder=`; or folders and files whose names have `q` in them, wherever you can open them. Each entry has its `access` (`view`, `edit` or `full`), and a folder list says whether you can add to it (`canAdd`).\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"folder\": null, \"path\": [], \"canAdd\": true,\n  \"folders\": [{ \"kind\": \"folder\", \"id\": \"01JC1F…\", \"name\": \"Taxes 2025\", \"place\": \"mine\",\n    \"ownerId\": \"01JB8Q…\", \"parentId\": null, \"access\": \"full\", \"shared\": true, \"updatedAt\": 1762300000000 }],\n  \"items\": [{ \"kind\": \"item\", \"id\": \"01JC1G…\", \"name\": \"notes.txt\", \"place\": \"mine\", \"access\": \"full\",\n    \"versions\": 1, \"file\": { \"id\": \"01JC1H…\", \"name\": \"notes.txt\", \"mime\": \"text/plain\", \"size\": 120,\n    \"url\": \"/api/files/01JC1H…\" } }] }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/cabinet/folders": {
      "post": {
        "operationId": "postApiWorkspacesByWCabinetFolders",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "Make a folder: name, and parentId for a folder inside another, or place (mine or workspace) for one at the top.",
        "description": "Make a folder: `name`, and `parentId` for a folder inside another, or `place` (`mine` or `workspace`) for one at the top. A top-level workspace folder takes `everyone` too (`edit` when left out). Needs edit on the folder it goes in.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/cabinet/items": {
      "post": {
        "operationId": "postApiWorkspacesByWCabinetItems",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "Upload a file to Files: the raw bytes with Content-Type and Content-Length, and ?name=, plus folder= (or place= for the ",
        "description": "Upload a file to Files: the raw bytes with `Content-Type` and `Content-Length`, and `?name=`, plus `folder=` (or `place=` for the top of My files or the workspace's). Up to 50 MB, checked against the workspace's file type rules for members.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/cabinet/save": {
      "post": {
        "operationId": "postApiWorkspacesByWCabinetSave",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "Keep a copy of a file from a conversation you're in: fileId, and folderId (leave it out for the top of My files).",
        "description": "Keep a copy of a file from a conversation you're in: `fileId`, and `folderId` (leave it out for the top of My files).\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/cabinet/folders/{id}": {
      "patch": {
        "operationId": "patchApiCabinetFoldersById",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "Rename a folder (name) or move it (parentId, null for the top), with edit.",
        "description": "Rename a folder (`name`) or move it (`parentId`, null for the top), with edit. Folders move within the same place: My files or the workspace's; moving to another top-level workspace folder needs full. `everyone` (`none`, `view` or `edit`) sets what every member gets in a top-level workspace folder, with full.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiCabinetFoldersById",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "Move a folder, with everything in it, to the trash for 30 days.",
        "description": "Move a folder, with everything in it, to the trash for 30 days. From the trash, `?forever=1` deletes it now. Needs full.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/cabinet/items/{id}": {
      "patch": {
        "operationId": "patchApiCabinetItemsById",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "Rename a file (name) or move it to another folder (parentId), with edit.",
        "description": "Rename a file (`name`) or move it to another folder (`parentId`), with edit.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiCabinetItemsById",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "Move a file to the trash for 30 days; ?forever=1 from the trash deletes it and every version now.",
        "description": "Move a file to the trash for 30 days; `?forever=1` from the trash deletes it and every version now. Needs full.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/cabinet/{kind}/{id}/restore": {
      "post": {
        "operationId": "postApiCabinetByKindByIdRestore",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "Take a folder (folders) or file (items) out of the trash, back where it was, or to the top when that folder is gone too.",
        "description": "Take a folder (`folders`) or file (`items`) out of the trash, back where it was, or to the top when that folder is gone too. Needs full.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "kind",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/cabinet/items/{id}/versions": {
      "get": {
        "operationId": "getApiCabinetItemsByIdVersions",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "A file's versions, newest first, with the current one marked.",
        "description": "A file's versions, newest first, with the current one marked. Up to 20 are kept.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiCabinetItemsByIdVersions",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "Upload a new version of a file, the same way as a new file.",
        "description": "Upload a new version of a file, the same way as a new file. The name in Files stays.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/cabinet/items/{id}/versions/{file}/restore": {
      "post": {
        "operationId": "postApiCabinetItemsByIdVersionsByFileRestore",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "Make an earlier version the current one again.",
        "description": "Make an earlier version the current one again.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "file",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/cabinet/items/{id}/attach": {
      "post": {
        "operationId": "postApiCabinetItemsByIdAttach",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "A copy of a file to send in a message: returns the file like an upload does, for fileIds.",
        "description": "A copy of a file to send in a message: returns the file like an upload does, for `fileIds`.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/cabinet/{kind}/{id}/shares": {
      "get": {
        "operationId": "getApiCabinetByKindByIdShares",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "Who has access to a folder or file: shares on it and on folders above it (inheritedFrom), everyone for the workspace's (",
        "description": "Who has access to a folder or file: shares on it and on folders above it (`inheritedFrom`), `everyone` for the workspace's (`everyoneFrom` when it's set on a folder above), and `canShare`.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "kind",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiCabinetByKindByIdShares",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "Share it with a person (userId) or a team (teamId) to view, edit or full.",
        "description": "Share it with a person (`userId`) or a team (`teamId`) to `view`, `edit` or `full`. Needs full. Guests can't be added.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "kind",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/cabinet/shares/{id}": {
      "patch": {
        "operationId": "patchApiCabinetSharesById",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "Change a share's access.",
        "description": "Change a share's `access`. Needs full.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiCabinetSharesById",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "Stop sharing with that person or team.",
        "description": "Stop sharing with that person or team. Needs full.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/cabinet/{kind}/{id}/links": {
      "get": {
        "operationId": "getApiCabinetByKindByIdLinks",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "Secure send: the links sending this folder or file to people outside the workspace, and this month's usage (used, includ",
        "description": "Secure send: the links sending this folder or file to people outside the workspace, and this month's `usage` (`used`, `included`, `metered`, `resets`). Needs full.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "kind",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiCabinetByKindByIdLinks",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "Secure send: send a folder or file to people outside the workspace, one link each, emailed to them.",
        "description": "Secure send: send a folder or file to people outside the workspace, one link each, emailed to them. They open it with a code we email to that address. `days` (up to the workspace's longest), `allowDownload` (false to only view in the browser) and `downloadLimit` are optional. Each address counts as one share. Needs full and the Secure send add-on. Returns each link's `url`, which is shown only now.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"emails\": [\"dana@contoso.example\"], \"note\": \"Your 2025 return, ready to sign.\", \"days\": 14, \"allowDownload\": true }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "kind",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/cabinet/links": {
      "get": {
        "operationId": "getApiWorkspacesByWCabinetLinks",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "The Secure send links you sent, newest first, with what each opens, when it was first and last opened, and its downloads",
        "description": "The Secure send links you sent, newest first, with what each opens, when it was first and last opened, and its downloads. Admins add `?all=1` for everyone's.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/cabinet/links/{id}/events": {
      "get": {
        "operationId": "getApiCabinetLinksByIdEvents",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "A link's activity: when it was sent, codes asked for, wrong codes, opens, and each file viewed or downloaded, with the c",
        "description": "A link's activity: when it was sent, codes asked for, wrong codes, opens, and each file viewed or downloaded, with the country and device. For whoever sent it, admins, and people with full access.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/cabinet/links/{id}": {
      "delete": {
        "operationId": "deleteApiCabinetLinksById",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "Stop a Secure send link working, at once, in every browser it's open in.",
        "description": "Stop a Secure send link working, at once, in every browser it's open in.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/share-policy": {
      "get": {
        "operationId": "getApiWorkspacesByWSharePolicy",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "The Secure send policy: who may send files outside (everyone, admins or nobody), the longest a link lasts (maxDays), and",
        "description": "The Secure send policy: who may send files outside (`everyone`, `admins` or `nobody`), the longest a link lasts (`maxDays`), and `blockedDomains`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWSharePolicy",
        "tags": [
          "Files (the file cabinet)"
        ],
        "summary": "Change the Secure send policy.",
        "description": "Change the Secure send policy. `nobody` also stops every link already sent; a shorter `maxDays` applies to new links.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"who\": \"everyone\", \"maxDays\": 30, \"blockedDomains\": [\"competitor.example\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/status": {
      "put": {
        "operationId": "putApiWorkspacesByWStatus",
        "tags": [
          "Status, availability and search"
        ],
        "summary": "Set your status in a workspace.",
        "description": "Set your status in a workspace. Fields you leave out stay as they are: `text` (up to 100 characters), `emoji`, `expiresAt` (when the text and emoji clear), `dndUntil` (Do Not Disturb until then; null turns it off) and `manualAway`.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"text\": \"At the Acme Corp warehouse\", \"emoji\": \"🚚\", \"expiresAt\": 1761238800000, \"dndUntil\": null }\n```\n\nExample answer:\n\n```json\n{ \"status\": { \"userId\": \"01JB8Q…\", \"text\": \"At the Acme Corp warehouse\", \"emoji\": \"🚚\",\n  \"expiresAt\": 1761238800000, \"dndUntil\": null, \"manualAway\": false } }\n```",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "users:write",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/search": {
      "get": {
        "operationId": "getApiWorkspacesByWSearch",
        "tags": [
          "Status, availability and search"
        ],
        "summary": "Search the messages you can see for 2 to 200 characters, newest first, optionally in one channel with &channelId=.",
        "description": "Search the messages you can see for 2 to 200 characters, newest first, optionally in one channel with `&channelId=`. `q` can hold filters: `from:@name` (or `from:me`), `in:#channel`, `after:yyyy-mm-dd`, `before:yyyy-mm-dd`, `on:yyyy-mm-dd` and `has:file`; after and before leave out the day itself. Answers the matching `results`, the `channels` they're in, and the `filters` as understood, with any names that matched nobody in `unknown`.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"results\": [ { \"id\": \"01JBC4…\", \"channelId\": \"01JB8S…\", \"body\": \"Release *2.4* is out\", … } ],\n  \"channels\": [ { \"id\": \"01JB8S…\", \"name\": \"deploys\", … } ],\n  \"filters\": { \"from\": [ { \"id\": \"01JB8Q…\", \"name\": \"Maya Chen\" } ], \"in\": [], \"after\": null, \"before\": null,\n    \"hasFile\": false, \"unknown\": [] } }\n```",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "search:read",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/ask": {
      "post": {
        "operationId": "postApiWorkspacesByWAsk",
        "tags": [
          "Status, availability and search"
        ],
        "summary": "Ask Freesbe: an answer to a question (2 to 200 characters, filters allowed) written by AI from the messages you can see,",
        "description": "Ask Freesbe: an answer to a `question` (2 to 200 characters, filters allowed) written by AI from the messages you can see, optionally only in `channelId`, in `language` when the question doesn't make it clear. Each of the `sentences` lists the `sources` it comes from, numbered from 1 in the order of `sources`. `status` is `unknown` when the messages found don't answer it. `search` is the question as a search with the filters it understood typed out. Counts as one AI request; 403 when admins turned AI off or the month's requests are used up. Not for guests. With `Accept: text/event-stream` it streams server-sent events: `{ \"type\": \"text\", \"text\" }` pieces of the answer as it's written (one sentence a line, each ending with its source numbers like `[1][3]`), then `{ \"type\": \"done\", … }` with the whole answer as above, or `{ \"type\": \"error\", \"message\" }`. The answer is written within 30 seconds or fails with a \"took too long\" message.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"question\": \"When is the Northwind launch?\", \"language\": \"en\" }\n```\n\nExample answer:\n\n```json\n{ \"status\": \"answered\",\n  \"sentences\": [ { \"text\": \"The launch is on April 14.\", \"sources\": [1] } ],\n  \"sources\": [ { \"id\": \"01JBC4…\", \"channelId\": \"01JB8S…\", \"body\": \"Yes, *April 14* still works.\", … } ],\n  \"channels\": [ { \"id\": \"01JB8S…\", \"name\": \"spring-launch\", … } ],\n  \"filters\": { \"from\": [], \"in\": [], \"after\": null, \"before\": null, \"hasFile\": false, \"unknown\": [] },\n  \"search\": \"When is the Northwind launch?\" }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/activity": {
      "get": {
        "operationId": "getApiWorkspacesByWActivity",
        "tags": [
          "Status, availability and search"
        ],
        "summary": "Mentions of you (including @channel and @here), huddles in your DMs that you missed (system messages of type huddle_miss",
        "description": "Mentions of you (including `@channel` and `@here`), huddles in your DMs that you missed (system messages of type `huddle_missed`) and replies in threads you started or replied in, newest first, 50 at a time, with the `channels` they're in and `threadReads`: how far you've read in each of those threads that you've opened, by its first message's id (later replies are new). Page back with `before`, the oldest message id you have.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"items\": [ { \"id\": \"01JBC9…\", \"channelId\": \"01JB8S…\", \"body\": \"<@01JB8Q…> can you approve this?\", … } ],\n  \"channels\": [ { \"id\": \"01JB8S…\", \"name\": \"support\", … } ],\n  \"threadReads\": { \"01JBC4…\": \"01JBC5…\" } }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/sent": {
      "get": {
        "operationId": "getApiWorkspacesByWSent",
        "tags": [
          "Status, availability and search"
        ],
        "summary": "Your own messages and replies, newest first, 50 at a time, in conversations you're still in, with the channels they're i",
        "description": "Your own messages and replies, newest first, 50 at a time, in conversations you're still in, with the `channels` they're in. Page back with `before`, the oldest message id you have. The app's Drafts & sent page shows these under Sent.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"items\": [ { \"id\": \"01JBD2…\", \"channelId\": \"01JB8S…\", \"body\": \"Shipped the Acme Corp order\", … } ],\n  \"channels\": [ { \"id\": \"01JB8S…\", \"name\": \"sales\", … } ] }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/calls": {
      "get": {
        "operationId": "getApiWorkspacesByWCalls",
        "tags": [
          "Status, availability and search"
        ],
        "summary": "Your calls: huddles in your DMs that have ended, newest first, 50 at a time.",
        "description": "Your calls: huddles in your DMs that have ended, newest first, 50 at a time. `direction` is `out` when you called; `answered` says whether you joined (incoming) or someone else did (outgoing). Page back with `before`, the oldest call's `startedAt`. Activity → Calls in the app lists these with your phone system calls. Not for apps.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"calls\": [ { \"huddleId\": \"01JBE1…\", \"channelId\": \"01JB9D…\", \"callerId\": \"01JB8Q…\", \"direction\": \"in\", \"answered\": false,\n    \"startedAt\": 1767016320000, \"durationMs\": 30000, \"participantIds\": [\"01JB8Q…\"] } ],\n  \"more\": false }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/todos": {
      "get": {
        "operationId": "getApiWorkspacesByWTodos",
        "tags": [
          "To-dos"
        ],
        "summary": "Your open to-dos, the soonest due first and undated ones after, then the 50 you finished most recently.",
        "description": "Your open to-dos, the soonest due first and undated ones after, then the 50 you finished most recently.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"todos\": [ { \"id\": \"01JBF2…\", \"text\": \"Send Globex the revised freight quote\",\n  \"notes\": \"Use the *new lane rates* from Lena's sheet.\", \"dueAt\": 1761325199999, \"doneAt\": null, \"messageId\": null, \"channelId\": null, \"createdAt\": 1761238800000 } ] }\n```",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "todos:read",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWTodos",
        "tags": [
          "To-dos"
        ],
        "summary": "Add a to-do: text (the one-line title) up to 500 characters, optional notes up to 10,000 characters in message formattin",
        "description": "Add a to-do: `text` (the one-line title) up to 500 characters, optional `notes` up to 10,000 characters in message formatting (mrkdwn, line breaks kept), optional `dueAt`, and optional `messageId` to make it from a message you can see. With a `messageId`, `text` can be empty and the message's text is used; a long or multi-line message also goes whole into `notes`. Up to 500 open to-dos each.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"text\": \"Approve spring catalog prices\", \"notes\": \"Check the *Acme Corp* discount first.\", \"dueAt\": 1761325199999 }\n```\n\nExample answer:\n\n```json\n{ \"todo\": { \"id\": \"01JBF3…\", \"text\": \"Approve spring catalog prices\", \"dueAt\": 1761325199999, \"doneAt\": null, … } }\n```",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "todos:write",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/todos/ai": {
      "post": {
        "operationId": "postApiWorkspacesByWTodosAi",
        "tags": [
          "To-dos"
        ],
        "summary": "AI help for a to-do in the editor, counted like other AI requests (not for guests, and only while the workspace has AI a",
        "description": "AI help for a to-do in the editor, counted like other AI requests (not for guests, and only while the workspace has AI and allowance left). `action` is `write` (notes from the title), `plan` (numbered steps, plus a `dueDate` when the to-do says when it's needed; pass `today` as yyyy-mm-dd) or `summarize` (what the message a to-do was made from and its thread say; needs `todoId`). Send `title` and the current `notes`. Nothing is saved: put the answer in the to-do with PATCH.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"action\": \"plan\", \"title\": \"Ask Tom about a second forklift\", \"notes\": \"Before the budget meeting Thursday\", \"today\": \"2026-10-23\" }\n```\n\nExample answer:\n\n```json\n{ \"notes\": \"1. Count the hours both shifts wait for the forklift\\n2. …\", \"dueDate\": \"2026-10-29\" }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/todos/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWTodosById",
        "tags": [
          "To-dos"
        ],
        "summary": "Change text, notes or dueAt (null clears either), or tick it off with done: true (false reopens it).",
        "description": "Change `text`, `notes` or `dueAt` (null clears either), or tick it off with `done: true` (`false` reopens it).\n\nWho can call it: Its owner. Only the person it belongs to, such as the maker of a booking page.\n\nExample request:\n\n```json\n{ \"done\": true }\n```\n\nExample answer:\n\n```json\n{ \"todo\": { \"id\": \"01JBF3…\", \"doneAt\": 1761242400000, … } }\n```",
        "x-freesbe-access": "owner",
        "x-freesbe-app-scope": "todos:write",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWTodosById",
        "tags": [
          "To-dos"
        ],
        "summary": "Delete one of your to-dos.",
        "description": "Delete one of your to-dos. Answers 204.\n\nWho can call it: Its owner. Only the person it belongs to, such as the maker of a booking page.",
        "x-freesbe-access": "owner",
        "x-freesbe-app-scope": "todos:write",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/scheduled-messages": {
      "get": {
        "operationId": "getApiWorkspacesByWScheduledMessages",
        "tags": [
          "Scheduled messages"
        ],
        "summary": "Your scheduled messages, soonest first, including ones that failed.",
        "description": "Your scheduled messages, soonest first, including ones that failed.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"scheduled\": [ { \"id\": \"01JBG1…\", \"channelId\": \"01JB8S…\", \"threadRootId\": null,\n  \"body\": \"Weekly sync is at 10:00 today\", \"files\": [], \"sendAt\": 1761440400000,\n  \"status\": \"scheduled\", \"error\": null, \"createdAt\": 1761238800000 } ] }\n```",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "chat:write",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWScheduledMessages",
        "tags": [
          "Scheduled messages"
        ],
        "summary": "Schedule a message in a channel, DM or thread (threadRootId) you can post in.",
        "description": "Schedule a message in a channel, DM or thread (`threadRootId`) you can post in. `body` is written like a message's; `fileIds` are uploads that aren't attached yet. Up to 100 each.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"channelId\": \"01JB8S…\", \"body\": \"Weekly sync is at 10:00 today\", \"sendAt\": 1761440400000 }\n```\n\nExample answer:\n\n```json\n{ \"scheduled\": { \"id\": \"01JBG1…\", \"status\": \"scheduled\", … } }\n```",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "chat:write",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/scheduled-messages/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWScheduledMessagesById",
        "tags": [
          "Scheduled messages"
        ],
        "summary": "Change the body or move sendAt.",
        "description": "Change the `body` or move `sendAt`. A failed one given a new `sendAt` is scheduled again.\n\nWho can call it: Its owner. Only the person it belongs to, such as the maker of a booking page.\n\nExample request:\n\n```json\n{ \"sendAt\": 1761526800000 }\n```\n\nExample answer:\n\n```json\n{ \"scheduled\": { \"id\": \"01JBG1…\", \"sendAt\": 1761526800000, … } }\n```",
        "x-freesbe-access": "owner",
        "x-freesbe-app-scope": "chat:write",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWScheduledMessagesById",
        "tags": [
          "Scheduled messages"
        ],
        "summary": "Delete it so it's never sent.",
        "description": "Delete it so it's never sent. Answers 204.\n\nWho can call it: Its owner. Only the person it belongs to, such as the maker of a booking page.",
        "x-freesbe-access": "owner",
        "x-freesbe-app-scope": "chat:write",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/scheduled-messages/{id}/send": {
      "post": {
        "operationId": "postApiWorkspacesByWScheduledMessagesByIdSend",
        "tags": [
          "Scheduled messages"
        ],
        "summary": "Send it now instead.",
        "description": "Send it now instead. Answers 201 with the posted message.\n\nWho can call it: Its owner. Only the person it belongs to, such as the maker of a booking page.\n\nExample answer:\n\n```json\n{ \"message\": { \"id\": \"01JBG4…\", \"body\": \"Weekly sync is at 10:00 today\", … } }\n```",
        "x-freesbe-access": "owner",
        "x-freesbe-app-scope": "chat:write",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/pins": {
      "get": {
        "operationId": "getApiChannelsByCPins",
        "tags": [
          "Pins and bookmarks"
        ],
        "summary": "The conversation's pinned messages, newest pin first.",
        "description": "The conversation's pinned messages, newest pin first.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample answer:\n\n```json\n{ \"pins\": [ { \"message\": { \"id\": \"01JBA2…\", \"body\": \"Q4 launch plan for Northwind\", … },\n  \"pinnedBy\": \"01JB8Q…\", \"pinnedAt\": 1761238800000 } ] }\n```",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "channels:history",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/messages/{m}/pin": {
      "put": {
        "operationId": "putApiMessagesByMPin",
        "tags": [
          "Pins and bookmarks"
        ],
        "summary": "Pin a message in its conversation.",
        "description": "Pin a message in its conversation. Pinning one that's pinned does nothing. Answers 204.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "pins:write",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiMessagesByMPin",
        "tags": [
          "Pins and bookmarks"
        ],
        "summary": "Unpin it.",
        "description": "Unpin it. Answers 204.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "pins:write",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/bookmarks": {
      "get": {
        "operationId": "getApiChannelsByCBookmarks",
        "tags": [
          "Pins and bookmarks"
        ],
        "summary": "The links kept at the top of the conversation, left to right.",
        "description": "The links kept at the top of the conversation, left to right.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample answer:\n\n```json\n{ \"bookmarks\": [ { \"id\": \"01JBB4…\", \"channelId\": \"01JB8S…\", \"title\": \"Price list\",\n  \"url\": \"https://northwind.example/prices\", \"createdBy\": \"01JB8Q…\", \"createdAt\": 1761238800000 } ] }\n```",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "channels:history",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiChannelsByCBookmarks",
        "tags": [
          "Pins and bookmarks"
        ],
        "summary": "Add a link at the end.",
        "description": "Add a link at the end. `url` must be a web address (`https://` is added when it's missing); without a `title` the link's address names it.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"title\": \"Price list\", \"url\": \"https://northwind.example/prices\" }\n```\n\nExample answer:\n\n```json\n{ \"bookmark\": { \"id\": \"01JBB4…\", … } }\n```",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "bookmarks:write",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/bookmarks/{id}": {
      "patch": {
        "operationId": "patchApiChannelsByCBookmarksById",
        "tags": [
          "Pins and bookmarks"
        ],
        "summary": "Rename it, change its link, or move it to position (0 is first).",
        "description": "Rename it, change its link, or move it to `position` (0 is first).\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"title\": \"Northwind price list\", \"position\": 0 }\n```\n\nExample answer:\n\n```json\n{ \"bookmark\": { \"id\": \"01JBB4…\", … } }\n```",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "bookmarks:write",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiChannelsByCBookmarksById",
        "tags": [
          "Pins and bookmarks"
        ],
        "summary": "Remove it.",
        "description": "Remove it. Answers 204.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.",
        "x-freesbe-access": "channel",
        "x-freesbe-app-scope": "bookmarks:write",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/saved": {
      "get": {
        "operationId": "getApiWorkspacesByWSaved",
        "tags": [
          "Save for later and reminders"
        ],
        "summary": "In progress (open): reminders that went off first, then upcoming ones soonest first, then the rest newest first.",
        "description": "In progress (`open`): reminders that went off first, then upcoming ones soonest first, then the rest newest first. `done` lists the newest 100 completed. `message` is null for one that was deleted or is in a conversation you left.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"items\": [ { \"messageId\": \"01JBA2…\", \"channelId\": \"01JB8S…\", \"message\": { … },\n  \"createdAt\": 1761238800000, \"remindAt\": 1761296400000, \"remindedAt\": null, \"doneAt\": null } ],\n  \"channels\": [ { \"id\": \"01JB8S…\", \"name\": \"sales\", … } ] }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/messages/{m}/save": {
      "put": {
        "operationId": "putApiMessagesByMSave",
        "tags": [
          "Save for later and reminders"
        ],
        "summary": "Save a message you can read, or change its reminder.",
        "description": "Save a message you can read, or change its reminder. Saving a completed one brings it back.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"remindAt\": 1761296400000 }\n```\n\nExample answer:\n\n```json\n{ \"item\": { \"messageId\": \"01JBA2…\", \"remindAt\": 1761296400000, … } }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiMessagesByMSave",
        "tags": [
          "Save for later and reminders"
        ],
        "summary": "Change the reminder (remindAt, null to take it off) or mark it done.",
        "description": "Change the reminder (`remindAt`, null to take it off) or mark it `done`. A new time sets the reminder off again.\n\nWho can call it: Its owner. Only the person it belongs to, such as the maker of a booking page.\n\nExample request:\n\n```json\n{ \"done\": true }\n```\n\nExample answer:\n\n```json\n{ \"item\": { \"messageId\": \"01JBA2…\", \"doneAt\": 1761300000000, … } }\n```",
        "x-freesbe-access": "owner",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiMessagesByMSave",
        "tags": [
          "Save for later and reminders"
        ],
        "summary": "Take it out of Later.",
        "description": "Take it out of Later. Answers 204, also when it wasn't there.\n\nWho can call it: Its owner. Only the person it belongs to, such as the maker of a booking page.",
        "x-freesbe-access": "owner",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/drafts": {
      "get": {
        "operationId": "getApiWorkspacesByWDrafts",
        "tags": [
          "Drafts"
        ],
        "summary": "Your drafts, newest first.",
        "description": "Your drafts, newest first.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"drafts\": [ { \"channelId\": \"01JB8S…\", \"threadRootId\": null,\n  \"body\": \"Can you check the Northwind order before\", \"files\": [], \"updatedAt\": 1761238800000 } ] }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWDrafts",
        "tags": [
          "Drafts"
        ],
        "summary": "Save the draft for a conversation you can see, replacing the one there.",
        "description": "Save the draft for a conversation you can see, replacing the one there. `body` is written like a message's. `fileIds` are the uploads waiting to go with it (up to 10, from `POST /api/workspaces/{w}/files`, in order): the draft keeps them, and they aren't cleaned up while it does. Ones that aren't yours or were already sent are left out. An empty `body` with no files deletes it and answers `{ \"draft\": null }`.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"channelId\": \"01JB8S…\", \"threadRootId\": null, \"body\": \"Can you check the Northwind order before\", \"fileIds\": [\"01JB8T…\"] }\n```\n\nExample answer:\n\n```json\n{ \"draft\": { \"channelId\": \"01JB8S…\", \"updatedAt\": 1761238800000, … } }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWDrafts",
        "tags": [
          "Drafts"
        ],
        "summary": "Forget a draft, for example once it's sent.",
        "description": "Forget a draft, for example once it's sent. Leave out `threadRootId` for the conversation's own. Answers 204, also when there was none.\n\nWho can call it: Its owner. Only the person it belongs to, such as the maker of a booking page.",
        "x-freesbe-access": "owner",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "channelId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "threadRootId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/canvas": {
      "get": {
        "operationId": "getApiChannelsByCCanvas",
        "tags": [
          "Canvases"
        ],
        "summary": "The conversation's canvas, or null before anyone has opened it to write, and whether you can edit it.",
        "description": "The conversation's canvas, or `null` before anyone has opened it to write, and whether you can edit it.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"canvas\": { \"id\": \"01JBG1…\", \"channelId\": \"01JB8S…\", \"createdBy\": \"01JB8Q…\", \"createdAt\": 1761238800000,\n  \"updatedAt\": 1761242400000, \"updatedBy\": \"01JB8R…\" }, \"canEdit\": true }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/canvas/ws": {
      "get": {
        "operationId": "getApiChannelsByCCanvasWs",
        "tags": [
          "Canvases"
        ],
        "summary": "Opens the canvas WebSocket (send Upgrade: websocket).",
        "description": "Opens the canvas WebSocket (send `Upgrade: websocket`). A member who can post starts the canvas by connecting; others get 404 until it exists. Changes from people who can only read are refused with `{\"t\":\"error\",\"code\":\"read_only\"}`. A canvas holds up to 4 MB, and one frame up to 512 KB.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/huddle/join": {
      "post": {
        "operationId": "postApiChannelsByCHuddleJoin",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "Join the channel's huddle, starting one if needed.",
        "description": "Join the channel's huddle, starting one if needed. `connId` is from the WebSocket's hello, so a dropped connection leaves the call. Up to 20 people. `merged: true` when moving into a merged call (see merge below): a new DM huddle then doesn't ring the others, who are on their way.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"connId\": \"01JBF0…\" }\n```\n\nExample answer:\n\n```json\n{\n  \"huddle\": {\n    \"id\": \"01JBF1…\",\n    \"channelId\": \"01JB8S…\",\n    \"startedBy\": \"01JB8Q…\",\n    \"startedAt\": 1761210000000,\n    \"participants\": [\n      { \"userId\": \"01JB8Q…\", \"joinedAt\": 1761210000000, \"muted\": false,\n        \"track\": { \"sessionId\": \"…\", \"trackName\": \"…\" }, \"video\": null, \"screen\": null }\n    ],\n    \"recording\": null,\n    \"videoPaused\": null\n  }\n}\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/huddle/leave": {
      "post": {
        "operationId": "postApiChannelsByCHuddleLeave",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "Leave the huddle.",
        "description": "Leave the huddle. Works even if you were just removed from the channel. Answers 204.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/call-quality": {
      "post": {
        "operationId": "postApiWorkspacesByWCallQuality",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "How a huddle sounded for you, sent by the apps as you leave: the huddleId and a report measured from the connection (pac",
        "description": "How a huddle sounded for you, sent by the apps as you leave: the `huddleId` and a `report` measured from the connection (packet loss, made-up audio, jitter, round trip, an estimated MOS). Nothing about what was said. Answers 204.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"huddleId\": \"01JBE7…\", \"report\": { \"id\": \"5f0c…\", \"app\": \"web\", \"os\": \"mac\", \"seconds\": 1260, \"lossPct\": 0.4, \"concealedPct\": 0.2, \"rttMs\": 48, \"mos\": 4.38, \"grade\": \"good\", … } }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/call-quality/{id}/rating": {
      "post": {
        "operationId": "postApiCallQualityByIdRating",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "Thumbs up or down after a huddle or meeting: rating 1 or -1 and, for -1, issues (echo, noise, choppy, quiet, delay).",
        "description": "Thumbs up or down after a huddle or meeting: `rating` 1 or -1 and, for -1, `issues` (`echo`, `noise`, `choppy`, `quiet`, `delay`). The report's random `id` is the permission, for an hour after it was sent. Answers 204.\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample request:\n\n```json\n{ \"rating\": -1, \"issues\": [\"choppy\"] }\n```",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/channels/{c}/huddle/decline": {
      "post": {
        "operationId": "postApiChannelsByCHuddleDecline",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "Turn down a DM call that's ringing for you.",
        "description": "Turn down a DM call that's ringing for you. Answers 204.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/huddles/{id}/merge": {
      "post": {
        "operationId": "postApiHuddlesByIdMerge",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "Merge the call ringing you (callId, its huddle id) into the huddle {id} you're in.",
        "description": "Merge the call ringing you (`callId`, its huddle id) into the huddle `{id}` you're in. From a DM or group DM, it opens the group DM of everyone in both calls; from a channel, the callers join its huddle (403 when they can't see the channel). Everyone who moves gets a `huddle.merged` event and joins `channelId` with `merged: true`, which doesn't ring anyone. The call isn't counted as missed. 404 when the call no longer rings you, 409 when you aren't in `{id}` or the merged call would have more than 20 people.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"callId\": \"01JBE9…\" }\n```\n\nExample answer:\n\n```json\n{ \"channelId\": \"01JBEA…\" }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/huddles/{id}/state": {
      "put": {
        "operationId": "putApiHuddlesByIdState",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "Your state in the call: muted, and the published track (microphone), video and screen, or null when they stop.",
        "description": "Your state in the call: `muted`, and the published `track` (microphone), `video` and `screen`, or null when they stop. After reconnecting, send the new `connId`.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"muted\": true }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/huddles/{id}/recording": {
      "post": {
        "operationId": "postApiHuddlesByIdRecording",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "Start recording the huddle, in video/webm, audio/webm, video/mp4 or audio/mp4.",
        "description": "Start recording the huddle, in `video/webm`, `audio/webm`, `video/mp4` or `audio/mp4`. Everyone in the call is told. 403 when an admin turned recordings off, or when the workspace's `recordingControl` is `hosts` and you aren't the huddle's host (whoever started it), a co-host or an admin. Guests can't. A `transcriptOnly` start in a workspace with `autoTranscribe` skips that rule. With an `audioMime`, `audio` in the answer says whether to also upload an audio-only track for the transcript. With `transcriptOnly`, nothing is recorded: `mime` is an audio type, the chunks are the transcript's audio, and only the transcript and notes are kept (the notes are posted in the channel). That needs transcripts on, not recordings; 403 when they're off or the plan's transcripts for the month are used, 503 when the server can't transcribe.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.\n\nExample request:\n\n```json\n{ \"mime\": \"video/webm\", \"audioMime\": \"audio/webm;codecs=opus\" }\n```\n\nExample answer:\n\n```json\n{ \"recording\": { \"id\": \"01JBF4…\", … }, \"audio\": true }\n```",
        "x-freesbe-access": "app",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/recordings/{id}/chunks/{seq}": {
      "put": {
        "operationId": "putApiRecordingsByIdChunksBySeq",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "The recorder's app uploads chunk 0, 1, 2… as the body, up to 32 MB each.",
        "description": "The recorder's app uploads chunk 0, 1, 2… as the body, up to 32 MB each.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "seq",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/recordings/{id}/audio/{seq}": {
      "put": {
        "operationId": "putApiRecordingsByIdAudioBySeq",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "The audio-only track for the transcript, chunk by chunk like the video, when the start answered audio: true.",
        "description": "The audio-only track for the transcript, chunk by chunk like the video, when the start answered `audio: true`.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "seq",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/recordings/{id}/stop": {
      "post": {
        "operationId": "postApiRecordingsByIdStop",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "Stops the recording; the recorder's app then finishes it.",
        "description": "Stops the recording; the recorder's app then finishes it. Who can depends on the workspace's `recordingControl`: `everyone` (anyone from the workspace in the call), `starter` (the default: the recorder, the call's hosts and co-hosts, and owners and admins) or `hosts` (the same, for starting too). A meeting's hosts are its organizer and invited members; a huddle's is whoever started it. The recorder can always stop their own. 403 otherwise. Answers 204.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/huddles/{id}/cohosts": {
      "put": {
        "operationId": "putApiHuddlesByIdCohosts",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "A host of the huddle (whoever started it, a co-host, or an owner or admin) makes someone in it a co-host, or stops them ",
        "description": "A host of the huddle (whoever started it, a co-host, or an owner or admin) makes someone in it a co-host, or stops them being one. Co-hosts start and stop recordings like a host, and name more co-hosts, until the huddle ends. Guests can't be co-hosts. The huddle's `cohosts` lists them.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"userId\": \"01JBF2…\", \"cohost\": true }\n```\n\nExample answer:\n\n```json\n{ \"huddle\": { \"id\": \"01JBF4…\", \"cohosts\": [\"01JBF2…\"], … } }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/huddles/{id}/drawing": {
      "put": {
        "operationId": "putApiHuddlesByIdDrawing",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "A host of the huddle (whoever started it, a co-host, or an owner or admin) turns drawing on shared screens off for every",
        "description": "A host of the huddle (whoever started it, a co-host, or an owner or admin) turns drawing on shared screens off for everyone, or back on. Drawing is on when a huddle starts. While it's off, the huddle's `drawingOffBy` is the host who turned it off and lines people draw aren't passed on. Each participant's `drawSlot` is their pen colour for the whole huddle. The lines themselves go over the realtime socket (`draw` frames out, `huddle.draw` events in) and are never stored.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"on\": false }\n```\n\nExample answer:\n\n```json\n{ \"huddle\": { \"id\": \"01JBF4…\", \"drawingOffBy\": \"01JBF2…\", … } }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/recordings/{id}/finish": {
      "post": {
        "operationId": "postApiRecordingsByIdFinish",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "The recorder uploaded every chunk (durationMs).",
        "description": "The recorder uploaded every chunk (`durationMs`). `speakers` is who spoke when, to name the voices in the transcript: `[{ id, name, member, spans: [[startMs, endMs], …] }]`. The recording is saved shortly after: a huddle's is posted in the channel as a file, a meeting's is kept with the meeting. Then the transcript and notes are written.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/recordings": {
      "get": {
        "operationId": "getApiWorkspacesByWRecordings",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "Recordings of huddles and meetings you can see, newest first, up to 100.",
        "description": "Recordings of huddles and meetings you can see, newest first, up to 100. A meeting's recording has the meeting's `attendees`. `state` is `saving` from when a recording stops until its file is ready, then `saved`, or `failed` when nothing usable arrived (`file` is null until it's saved). `transcript` is `queued`, `working`, `ready`, `failed`, `skipped` (with a `skipped` reason: `not_set_up`, `off`, `allowance`, `cap` or `empty`) or null for recordings made before transcripts.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"recordings\": [ { \"id\": \"01JBF4…\", \"kind\": \"meeting\", \"title\": \"Weekly sync\",\n  \"state\": \"saved\", \"startedAt\": 1729303200000, \"durationMs\": 1601000, \"file\": { \"url\": \"…\" },\n  \"transcript\": \"ready\", \"skipped\": null, … } ] }\n```",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "recordings:read",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/recordings/{id}": {
      "get": {
        "operationId": "getApiRecordingsById",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "A recording with its notes (summary, decisions and action items with their owner) and its transcript as segments: who sp",
        "description": "A recording with its `notes` (summary, decisions and action items with their owner) and its transcript as `segments`: who spoke, their user id when they're a member, start and end in ms, and the text.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"recording\": { \"id\": \"01JBF4…\", \"transcript\": \"ready\",\n  \"notes\": { \"summary\": \"…\", \"decisions\": [\"…\"],\n             \"actionItems\": [ { \"text\": \"Send Acme the new price list by Friday\", \"owner\": \"James Okafor\" } ] },\n  \"segments\": [ { \"speaker\": \"Maya Chen\", \"userId\": \"01JBC1…\", \"start\": 4000, \"end\": 12000, \"text\": \"…\" } ],\n  \"language\": \"en\", … } }\n```",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "recordings:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/recordings/{id}/transcribe": {
      "post": {
        "operationId": "postApiRecordingsByIdTranscribe",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "Try a transcript again after it failed, or after the workspace had used its plan's transcripts.",
        "description": "Try a transcript again after it failed, or after the workspace had used its plan's transcripts. Answers the recording.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/recordings/{id}/guest-links": {
      "get": {
        "operationId": "getApiRecordingsByIdGuestLinks",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "A meeting recording's links to its notes and transcript for people outside the workspace: the ones its guests were email",
        "description": "A meeting recording's links to its notes and transcript for people outside the workspace: the ones its guests were emailed, and the ones made with Share (`createdBy`; `email` is null for a link for anyone who has it). Who, until when, when and how often it was opened (`opens`), whether it plays the recording, and whether the email went out. `canRevoke` is true for the meeting's organizer, whoever recorded it and admins, and only they get `url`, the link itself, for links made with Share.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"links\": [ { \"id\": \"01JBH2…\", \"email\": \"gina.lopez@acme.example\", \"name\": \"Gina Lopez\",\n  \"createdAt\": 1729609800000, \"expiresAt\": 1730214600000, \"openedAt\": 1729611720000,\n  \"revokedAt\": null, \"video\": true, \"failed\": false, \"createdBy\": null, \"opens\": 2,\n  \"lastOpenedAt\": 1729672320000, \"url\": null } ], \"canRevoke\": true }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/recordings/{id}/guest-links/{link}": {
      "delete": {
        "operationId": "deleteApiRecordingsByIdGuestLinksByLink",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "Revoke one outside link right away (the meeting's organizer and whoever recorded it can too).",
        "description": "Revoke one outside link right away (the meeting's organizer and whoever recorded it can too). Without `/{link}`, revokes every outside link for the recording. Answers the list.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "link",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/recordings/{id}/sharing": {
      "get": {
        "operationId": "getApiRecordingsByIdSharing",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "Who the recording is shared with in the workspace (shares: a userId or a channelId, who shared it and when), its outside",
        "description": "Who the recording is shared with in the workspace (`shares`: a `userId` or a `channelId`, who shared it and when), its outside links when you can manage them, and what you can do: `canShare` (members, not guests), `outsideBlock` (null when you can make outside links, otherwise `off`, `not_allowed`, `no_transcript`, `huddle` or `guest`), `maxDays` and `videoAllowed`.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"sharing\": { \"shares\": [ { \"id\": \"01JBH5…\", \"userId\": \"01JBC4…\", \"channelId\": null,\n  \"sharedBy\": \"01JBC1…\", \"createdAt\": 1729611000000 } ], \"links\": [ … ], \"canShare\": true,\n  \"outsideBlock\": null, \"canRevoke\": true, \"maxDays\": 7, \"videoAllowed\": true } }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/recordings/{id}/shares": {
      "post": {
        "operationId": "postApiRecordingsByIdShares",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "Share a recording you can see with up to 20 people (userIds, posted in your DM with each) and channels or group DMs (cha",
        "description": "Share a recording you can see with up to 20 people (`userIds`, posted in your DM with each) and channels or group DMs (`channelIds`, which you must be able to post in), with an optional `comment`. Each message carries an attachment with the recording's title, a link to its page, the start of its summary, and `recording`: its `id`, `kind`, `startedAt`, `durationMs` and whether it has a `video`. The people it's shared with, and everyone in a shared channel, can then see the recording. Answers the sharing, 201.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"userIds\": [\"01JBC4…\"], \"channelIds\": [\"01JBC9…\"], \"comment\": \"Notes from the Acme call\" }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/recordings/{id}/shares/{share}": {
      "delete": {
        "operationId": "deleteApiRecordingsByIdSharesByShare",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "Take a share back: whoever made it, the meeting's organizer, whoever recorded it and admins.",
        "description": "Take a share back: whoever made it, the meeting's organizer, whoever recorded it and admins. The message stays. Answers the sharing.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "share",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/recordings/{id}/links": {
      "post": {
        "operationId": "postApiRecordingsByIdLinks",
        "tags": [
          "Huddles and recordings"
        ],
        "summary": "Make a link to a meeting's notes and transcript for people outside the workspace: the meeting's organizer, whoever recor",
        "description": "Make a link to a meeting's notes and transcript for people outside the workspace: the meeting's organizer, whoever recorded it and admins, when the workspace has outside sharing on (`guestTranscripts`) and the transcript is ready. `days` is 1, 3, 7, 14 or 30, up to the workspace's `guestTranscriptDays`; `video` plays the recording too, when `guestTranscriptVideo` allows it. With an `email` (not a member of the workspace), the link is emailed there. Answers the link, with its `url`, and the sharing, 201.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"days\": 7, \"video\": false, \"email\": \"pat@contoso.example\" }\n```\n\nExample answer:\n\n```json\n{ \"link\": { \"id\": \"01JBH6…\", \"email\": \"pat@contoso.example\", \"url\": \"https://app.freesbe.net/notes/…\", … },\n  \"sharing\": { … } }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/ai": {
      "get": {
        "operationId": "getApiWorkspacesByWAi",
        "tags": [
          "AI summaries, translations and writing help"
        ],
        "summary": "Whether AI features are on for the workspace (enabled) and set up on the server (available), and this usage period's req",
        "description": "Whether AI features are on for the workspace (`enabled`) and set up on the server (`available`), and this usage period's requests against the allowance (`limit`, null for no limit), which starts again on `resets` (the workspace's billing day, UTC).\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"enabled\": true, \"available\": true, \"used\": 412, \"limit\": 800, \"resets\": \"2026-12-14\" }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/summary": {
      "post": {
        "operationId": "postApiChannelsByCSummary",
        "tags": [
          "AI summaries, translations and writing help"
        ],
        "summary": "Summarize a thread (threadRootId) or the channel over a span: unread (since you last read, the default), day or week, up",
        "description": "Summarize a thread (`threadRootId`) or the channel over a `span`: `unread` (since you last read, the default), `day` or `week`, up to the newest 400 messages. `language` is an app language code; it defaults to yours. Each point links to its message (`messageId`, and `threadRootId` for a reply). Messages repeated by the same author (alerts, bots) are read once. Summaries are kept: asking again with nothing new answers at once and isn't counted as a request, and new messages are read into the kept summary. Send `Accept: text/event-stream` to get it as server-sent events while it's written: `{\"type\":\"stage\",\"stage\":\"reading\",\"count\":240,\"folded\":180}`, then `{\"type\":\"text\",\"text\":\"…\"}` pieces, then `{\"type\":\"done\",\"summary\":{…},\"cached\":false}` (or `{\"type\":\"error\",\"message\":\"…\"}`). Guests get 403.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"span\": \"day\", \"language\": \"en\" }\n```\n\nExample answer:\n\n```json\n{ \"summary\": { \"overview\": \"The launch is on track for April 14.\",\n  \"points\": [ { \"text\": \"Priya confirmed the date.\", \"messageId\": \"01JBD2…\", \"threadRootId\": null } ],\n  \"messageCount\": 9, \"from\": 1729303200000, \"to\": 1729316400000 } }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/messages/{m}/translate": {
      "post": {
        "operationId": "postApiMessagesByMTranslate",
        "tags": [
          "AI summaries, translations and writing help"
        ],
        "summary": "Translate a message into language (an app language code; yours by default).",
        "description": "Translate a message into `language` (an app language code; yours by default). `same` is true when it already is in that language. Guests get 403.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"language\": \"de\" }\n```\n\nExample answer:\n\n```json\n{ \"text\": \"Neue Bestellung von Contoso …\", \"same\": false }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/ai/rewrite": {
      "post": {
        "operationId": "postApiWorkspacesByWAiRewrite",
        "tags": [
          "AI summaries, translations and writing help"
        ],
        "summary": "Writing help: a better version of a draft (text, up to 4,000 characters) in a style: fix (spelling and grammar), clearer",
        "description": "Writing help: a better version of a draft (`text`, up to 4,000 characters) in a `style`: `fix` (spelling and grammar), `clearer`, `shorter`, `friendlier` or `formal`. It only rewrites the draft, in the draft's language, keeping mentions, links and code. Nothing is sent. Send `Accept: text/event-stream` to get it as server-sent events while it's written: `{\"type\":\"text\",\"text\":\"…\"}` pieces, then `{\"type\":\"done\",\"text\":\"…\"}` (or `{\"type\":\"error\",\"message\":\"…\"}`). Gives up after 30 seconds (502).\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"text\": \"hey contoso, thx for the order!! we can deliver by nov 6\", \"style\": \"formal\" }\n```\n\nExample answer:\n\n```json\n{ \"text\": \"Hi Contoso team, thank you for your order. We can deliver by November 6.\" }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/ai/photo-touchup": {
      "get": {
        "operationId": "getApiWorkspacesByWAiPhotoTouchup",
        "tags": [
          "AI summaries, translations and writing help"
        ],
        "summary": "How many profile photo touch-ups you have left today (3 a day, across your workspaces).",
        "description": "How many profile photo touch-ups you have left today (3 a day, across your workspaces).\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"left\": 2, \"limit\": 3 }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWAiPhotoTouchup",
        "tags": [
          "AI summaries, translations and writing help"
        ],
        "summary": "Improve with AI for a profile photo: send image as base64 JPEG (up to 1,024 px on its longest side and 1 MB).",
        "description": "Improve with AI for a profile photo: send `image` as base64 JPEG (up to 1,024 px on its longest side and 1 MB). The model checks it's a photo of a person with their face showing and answers where the face is (fractions of the picture) and gentle light and colour fixes, which the app applies itself. Anything else answers `ok: false`. 3 a day per person and 20 a day per workspace on Free (200 on paid plans); past that, 429. Counts as an AI request.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"image\": \"/9j/4AAQSkZJRgABAQ…\" }\n```\n\nExample answer:\n\n```json\n{ \"ok\": true, \"face\": { \"x\": 0.41, \"y\": 0.11, \"width\": 0.21, \"height\": 0.5 },\n  \"adjust\": { \"brightness\": 1.1, \"contrast\": 1.08, \"saturation\": 1.04, \"warmth\": 0.06 },\n  \"softenBackground\": true, \"left\": 2 }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/meetings": {
      "get": {
        "operationId": "getApiWorkspacesByWMeetings",
        "tags": [
          "Meetings"
        ],
        "summary": "Upcoming meetings, and the last week's, that you organize, are invited to or joined.",
        "description": "Upcoming meetings, and the last week's, that you organize, are invited to or joined. `attendees` lists who joined the call, in the order they came in: `{ userId, name }`, with `userId` null for a guest. While a call can be going, `live` lists who's in it and who's waiting in the lobby. Once everyone has left a call that took place, `live.callEndedAt` says when, and `live.rejoinUntil` how long the link still lets them back in. `lastCallAt` is when its last call ended: the link works until 30 days after, and `calls` lists its calls that are over, oldest first (`startedAt`, `endedAt`, `attendees`). Last week's means scheduled or called in the last 7 days. `chatMessages` counts the messages in its chat. `email` says whether invites are emailed.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"meetings\": [ { \"id\": \"01JBE7…\", \"title\": \"Quarterly review with Acme Corp\",\n  \"live\": { \"inCall\": [ { \"id\": \"…\", \"name\": \"Dana Whitfield\", \"guest\": false } ],\n            \"waiting\": [ { \"id\": \"01JBE9…\", \"name\": \"Jordan Lee\", … } ] }, … } ],\n  \"email\": true }\n```",
        "x-freesbe-access": "members",
        "x-freesbe-app-scope": "meetings:read",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWMeetings",
        "tags": [
          "Meetings"
        ],
        "summary": "Schedule one: title, startsAt, durationMin (15, 30, 45, 60, 90, 120, 180 or 240), and optionally description, timeZone, ",
        "description": "Schedule one: `title`, `startsAt`, `durationMin` (15, 30, 45, 60, 90, 120, 180 or 240), and optionally `description`, `timeZone`, members by `userIds` (those also in `optionalUserIds` are invited as optional) and anyone else by `emails` (up to 50 people), and `waitingRoom` (default true). Invites are emailed unless `notify` is false; `unsent` lists addresses that couldn't be. Answers 201.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{\n  \"title\": \"Quarterly review with Acme Corp\",\n  \"startsAt\": 1761310800000,\n  \"durationMin\": 45,\n  \"timeZone\": \"Europe/London\",\n  \"userIds\": [\"01JB8R…\"],\n  \"emails\": [\"jordan@acme.example\"],\n  \"waitingRoom\": true\n}\n```\n\nExample answer:\n\n```json\n{\n  \"meeting\": {\n    \"id\": \"01JBE7…\",\n    \"workspaceId\": \"01JB8Q…\",\n    \"code\": \"kdq-rmvt-zpa\",\n    \"url\": \"https://meet.freesbe.net/kdq-rmvt-zpa\",\n    \"title\": \"Quarterly review with Acme Corp\",\n    \"description\": \"\",\n    \"startsAt\": 1761310800000,\n    \"durationMin\": 45,\n    \"timeZone\": \"Europe/London\",\n    \"organizerId\": \"01JB8Q…\",\n    \"invitees\": [\n      { \"email\": \"priya@northwind.example\", \"name\": \"Priya Raman\", \"userId\": \"01JB8R…\" },\n      { \"email\": \"jordan@acme.example\", \"name\": null, \"userId\": null, \"response\": \"accepted\" }\n    ],\n    \"waitingRoom\": true,\n    \"createdAt\": 1761200000000,\n    \"canceledAt\": null,\n    \"endedAt\": null\n  },\n  \"unsent\": []\n}\n```",
        "x-freesbe-access": "full-members",
        "x-freesbe-app-scope": "meetings:write",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/support-sessions": {
      "post": {
        "operationId": "postApiWorkspacesByWSupportSessions",
        "tags": [
          "Meetings"
        ],
        "summary": "Start a support session: a one-hour meeting starting now, with a waiting room, whose link and code you give a customer.",
        "description": "Start a support session: a one-hour meeting starting now, with a waiting room, whose link and `code` you give a customer. Members in it can ask to control the screen the customer shares from the desktop app. Needs remote control turned on for the workspace, or answers 403. Answers 201 with the meeting, like scheduling one.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{\n  \"meeting\": {\n    \"id\": \"01JBE7…\",\n    \"workspaceId\": \"01JB8Q…\",\n    \"code\": \"kdq-rmvt-zpa\",\n    \"url\": \"https://meet.freesbe.net/kdq-rmvt-zpa\",\n    \"title\": \"Quarterly review with Acme Corp\",\n    \"description\": \"\",\n    \"startsAt\": 1761310800000,\n    \"durationMin\": 45,\n    \"timeZone\": \"Europe/London\",\n    \"organizerId\": \"01JB8Q…\",\n    \"invitees\": [\n      { \"email\": \"priya@northwind.example\", \"name\": \"Priya Raman\", \"userId\": \"01JB8R…\" },\n      { \"email\": \"jordan@acme.example\", \"name\": null, \"userId\": null, \"response\": \"accepted\" }\n    ],\n    \"waitingRoom\": true,\n    \"createdAt\": 1761200000000,\n    \"canceledAt\": null,\n    \"endedAt\": null\n  },\n  \"unsent\": []\n}\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/meetings/{id}": {
      "patch": {
        "operationId": "patchApiMeetingsById",
        "tags": [
          "Meetings"
        ],
        "summary": "Change a meeting.",
        "description": "Change a meeting. Send the whole meeting, as when scheduling it. Everyone still invited gets an updated invite, new people an invite, removed people a cancellation.\n\nWho can call it: Organizer or admins. The person who scheduled the meeting, or a workspace owner or admin.",
        "x-freesbe-access": "organizer",
        "x-freesbe-app-scope": "meetings:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiMeetingsById",
        "tags": [
          "Meetings"
        ],
        "summary": "Cancel it and email the cancellation.",
        "description": "Cancel it and email the cancellation. Anyone in the call is disconnected. Answers 204.\n\nWho can call it: Organizer or admins. The person who scheduled the meeting, or a workspace owner or admin.",
        "x-freesbe-access": "organizer",
        "x-freesbe-app-scope": "meetings:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/meetings/{id}/end": {
      "post": {
        "operationId": "postApiMeetingsByIdEnd",
        "tags": [
          "Meetings"
        ],
        "summary": "End the call for everyone; the link stops working.",
        "description": "End the call for everyone; the link stops working. Answers 204.\n\nWho can call it: Organizer or admins. The person who scheduled the meeting, or a workspace owner or admin.",
        "x-freesbe-access": "organizer",
        "x-freesbe-app-scope": "meetings:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/meetings/{id}/admit": {
      "post": {
        "operationId": "postApiMeetingsByIdAdmit",
        "tags": [
          "Meetings"
        ],
        "summary": "Let someone in from the lobby (admit: true) or turn them away.",
        "description": "Let someone in from the lobby (`admit: true`) or turn them away. `peerId` is from `live.waiting`. The organizer, invited members and admins can. Answers 204.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"peerId\": \"01JBE9…\", \"admit\": true }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/meetings/{id}/new-link": {
      "post": {
        "operationId": "postApiMeetingsByIdNewLink",
        "tags": [
          "Meetings"
        ],
        "summary": "Replace the link; the old one stops working and invitees get the new one.",
        "description": "Replace the link; the old one stops working and invitees get the new one.\n\nWho can call it: Organizer or admins. The person who scheduled the meeting, or a workspace owner or admin.\n\nExample answer:\n\n```json\n{\n  \"meeting\": {\n    \"id\": \"01JBE7…\",\n    \"workspaceId\": \"01JB8Q…\",\n    \"code\": \"kdq-rmvt-zpa\",\n    \"url\": \"https://meet.freesbe.net/kdq-rmvt-zpa\",\n    \"title\": \"Quarterly review with Acme Corp\",\n    \"description\": \"\",\n    \"startsAt\": 1761310800000,\n    \"durationMin\": 45,\n    \"timeZone\": \"Europe/London\",\n    \"organizerId\": \"01JB8Q…\",\n    \"invitees\": [\n      { \"email\": \"priya@northwind.example\", \"name\": \"Priya Raman\", \"userId\": \"01JB8R…\" },\n      { \"email\": \"jordan@acme.example\", \"name\": null, \"userId\": null, \"response\": \"accepted\" }\n    ],\n    \"waitingRoom\": true,\n    \"createdAt\": 1761200000000,\n    \"canceledAt\": null,\n    \"endedAt\": null\n  },\n  \"unsent\": []\n}\n```",
        "x-freesbe-access": "organizer",
        "x-freesbe-app-scope": "meetings:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/meet/{code}": {
      "get": {
        "operationId": "getApiMeetByCode",
        "tags": [
          "Meetings"
        ],
        "summary": "What a meeting link shows before joining: title, time, organizer, workspace, whether it's early, open, closed or cancele",
        "description": "What a meeting link shows before joining: title, time, organizer, workspace, whether it's `early`, `open`, `closed` or `canceled`, and whether guests wait in a lobby.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/meet/{code}/join": {
      "post": {
        "operationId": "postApiMeetByCodeJoin",
        "tags": [
          "Meetings"
        ],
        "summary": "Knock or join, as a member or a guest with a name (or the personal invite token from their email).",
        "description": "Knock or join, as a member or a guest with a `name` (or the personal `invite` token from their email). Answers a `token` for the call's socket and media, and whether you're `admitted` or waiting.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/meet/{code}/quality": {
      "post": {
        "operationId": "postApiMeetByCodeQuality",
        "tags": [
          "Meetings"
        ],
        "summary": "How the call sounded for you, sent as you leave, with the token from joining: the same report as a huddle's.",
        "description": "How the call sounded for you, sent as you leave, with the `token` from joining: the same `report` as a huddle's. Answers 204.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/meet/{code}/chat/{token}": {
      "get": {
        "operationId": "getApiMeetByCodeChatByToken",
        "tags": [
          "Meetings"
        ],
        "summary": "The call's chat so far, oldest first, for anyone let into the call (members and guests, with the token from joining).",
        "description": "The call's chat so far, oldest first, for anyone let into the call (members and guests, with the `token` from joining). New messages also arrive on the socket as `{ t: \"chat\", message }`. In the call, open a message's file at `/api/meet/{code}/chat/{token}/files/{id}`.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.\n\nExample answer:\n\n```json\n{ \"messages\": [ { \"id\": \"01JBG2…\", \"peerId\": \"01JBE9…\", \"userId\": null, \"name\": \"Jordan Lee\",\n  \"guest\": true, \"body\": \"Here are our numbers\", \"file\": { \"id\": \"01JBG3…\", \"name\": \"forecast.xlsx\",\n  \"mime\": \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\", \"size\": 48200,\n  \"url\": \"/api/files/01JBG3…\" }, \"createdAt\": 1761310920000 } ] }\n```",
        "x-freesbe-access": "app",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiMeetByCodeChatByToken",
        "tags": [
          "Meetings"
        ],
        "summary": "Send a message (body, up to 4,000 characters) to everyone in the call.",
        "description": "Send a message (`body`, up to 4,000 characters) to everyone in the call. Answers 201 with `message`.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.\n\nExample request:\n\n```json\n{ \"body\": \"The price list is at https://northwind.example/wholesale\" }\n```",
        "x-freesbe-access": "app",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/meet/{code}/chat/{token}/files": {
      "post": {
        "operationId": "postApiMeetByCodeChatByTokenFiles",
        "tags": [
          "Meetings"
        ],
        "summary": "Send a file to the call's chat: the file is the body, with Content-Type and Content-Length, and width/height for picture",
        "description": "Send a file to the call's chat: the file is the body, with `Content-Type` and `Content-Length`, and `width`/`height` for pictures, `text` for a caption. Guests from outside follow the workspace's file rules for guests (403 `file_blocked`). Answers 201 with `message`.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/meetings/{id}/chat": {
      "get": {
        "operationId": "getApiMeetingsByIdChat",
        "tags": [
          "Meetings"
        ],
        "summary": "The chat kept with a meeting, after the call: for its organizer, invited members, members who were in the call, people w",
        "description": "The chat kept with a meeting, after the call: for its organizer, invited members, members who were in the call, people who can see its recording, and owners and admins. Files open at their `url`. 404 for anyone else.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/meetings/code/{code}/recording": {
      "post": {
        "operationId": "postApiMeetingsCodeByCodeRecording",
        "tags": [
          "Meetings"
        ],
        "summary": "Start recording the meeting you're in, by its code.",
        "description": "Start recording the meeting you're in, by its code. Workspace members can; guests can't. Everyone in the call sees who is recording. Upload and finish it like a huddle recording; it's kept with the meeting and listed under `/api/workspaces/{w}/recordings`. 409 when it's already being recorded.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.\n\nExample request:\n\n```json\n{ \"mime\": \"video/webm\", \"audioMime\": \"audio/webm;codecs=opus\" }\n```\n\nExample answer:\n\n```json\n{ \"recording\": { \"id\": \"01JBF4…\", … }, \"audio\": true }\n```",
        "x-freesbe-access": "app",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/calendar": {
      "get": {
        "operationId": "getApiMeCalendar",
        "tags": [
          "Calendar"
        ],
        "summary": "Your connected calendar, if any, and the providers this server can connect to: google, microsoft and zoho.",
        "description": "Your connected calendar, if any, and the providers this server can connect to: `google`, `microsoft` and `zoho`. `needsReconnect` means the provider stopped accepting Freesbe's access.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"connection\": { \"provider\": \"google\", \"email\": \"dana@northwind.example\", \"autoStatus\": true,\n  \"connectedAt\": 1761200000000, \"needsReconnect\": false, \"events\": true,\n  \"app\": { \"workspaceId\": \"01JB8Q…\", \"agenda\": true, \"agendaMinute\": 480, \"weekends\": false,\n    \"reminderMinutes\": 10, \"invites\": true } },\n  \"providers\": [\"google\", \"microsoft\", \"zoho\"] }\n```",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiMeCalendar",
        "tags": [
          "Calendar"
        ],
        "summary": "Turn the automatic \"In a meeting\" status on or off, and change the Calendar app: app.workspaceId turns it on (messages g",
        "description": "Turn the automatic \"In a meeting\" status on or off, and change the Calendar app: `app.workspaceId` turns it on (messages go to your DM with yourself there) or off with `null`; `agendaMinute` is minutes after midnight in your time zone; `reminderMinutes` is 1, 5, 10, 15, 30 or `null`. Setting your status by hand takes it back from the calendar.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample request:\n\n```json\n{ \"autoStatus\": false, \"app\": { \"agendaMinute\": 450, \"reminderMinutes\": 5 } }\n```",
        "x-freesbe-access": "signed-in",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiMeCalendar",
        "tags": [
          "Calendar"
        ],
        "summary": "Disconnect the calendar and clear a status it set.",
        "description": "Disconnect the calendar and clear a status it set. Answers 204.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/integrations/zoho/calendar/start": {
      "get": {
        "operationId": "getApiIntegrationsZohoCalendarStart",
        "tags": [
          "Calendar"
        ],
        "summary": "Open in the browser to connect Zoho Calendar, in any Zoho data center.",
        "description": "Open in the browser to connect Zoho Calendar, in any Zoho data center. Takes the same `next`, `events=1` and `workspace={w}` as the Google and Microsoft one and comes back the same way, through Zoho's shared callback. Zoho Calendar events have `canAnswer: false`: Freesbe can't answer them, so `rsvp` answers 400.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.",
        "x-freesbe-access": "app",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/calendar/agenda": {
      "get": {
        "operationId": "getApiMeCalendarAgenda",
        "tags": [
          "Calendar"
        ],
        "summary": "Calendar app: your events on a day (today when left out) in your time zone, without declined or canceled ones.",
        "description": "Calendar app: your events on a day (today when left out) in your time zone, without declined or canceled ones. `response` is `organizer`, `pending`, `accepted`, `tentative` or `declined`; `joinUrl` is a video call link when the event has one.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"day\": \"2026-10-23\", \"timezone\": \"Asia/Singapore\", \"events\": [\n  { \"id\": \"7k2…\", \"title\": \"Sales standup\", \"start\": 1761183000000, \"end\": 1761183900000,\n    \"allDay\": false, \"location\": null, \"joinUrl\": \"https://meet.google.com/abc-defg-hij\",\n    \"link\": \"https://calendar.google.com/…\", \"organizer\": \"Priya Raman\",\n    \"response\": \"accepted\", \"cancelled\": false } ] }\n```",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "day",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/calendar/agenda/send": {
      "post": {
        "operationId": "postApiMeCalendarAgendaSend",
        "tags": [
          "Calendar"
        ],
        "summary": "Calendar app: send today's agenda to your DM with yourself now.",
        "description": "Calendar app: send today's agenda to your DM with yourself now. Answers 204.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/calendar/events/{id}/rsvp": {
      "post": {
        "operationId": "postApiMeCalendarEventsByIdRsvp",
        "tags": [
          "Calendar"
        ],
        "summary": "Calendar app: answer an invitation in your calendar; the organizer hears about it.",
        "description": "Calendar app: answer an invitation in your calendar; the organizer hears about it. With `messageId`, the Calendar message it came from shows the answer.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample request:\n\n```json\n{ \"answer\": \"accepted\", \"messageId\": \"01JBF7…\" }\n```\n\nExample answer:\n\n```json\n{ \"event\": { \"id\": \"7k2…\", \"response\": \"accepted\", … } }\n```",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/calendar-app": {
      "get": {
        "operationId": "getApiWorkspacesByWCalendarApp",
        "tags": [
          "Calendar"
        ],
        "summary": "Whether people can use the Calendar app in the workspace, and how many get its messages there; whether they can schedule",
        "description": "Whether people can use the Calendar app in the workspace, and how many get its messages there; whether they can schedule Freesbe meetings from Outlook and Google Calendar (`addins`), how many connected an add-in, the Outlook add-in's manifest address for the Microsoft 365 admin center, and the Google Calendar add-on's Apps Script files.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"enabled\": true, \"people\": 12, \"addins\": true, \"addinPeople\": 4,\n  \"outlookManifestUrl\": \"https://app.freesbe.net/addins/outlook/manifest.xml\",\n  \"googleAddon\": { \"code\": \"https://app.freesbe.net/addins/google/Code.gs\",\n    \"manifest\": \"https://app.freesbe.net/addins/google/appsscript.json\" } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWCalendarApp",
        "tags": [
          "Calendar"
        ],
        "summary": "Turn the Calendar app (enabled) or the calendar add-ins for Outlook and Google Calendar (addins) on or off for the works",
        "description": "Turn the Calendar app (`enabled`) or the calendar add-ins for Outlook and Google Calendar (`addins`) on or off for the workspace; send either or both. Calendar app off stops everyone's Calendar messages there; add-ins off stop everyone's add-ins from scheduling meetings in it.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"enabled\": false, \"addins\": true }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/calendar-addins": {
      "get": {
        "operationId": "getApiMeCalendarAddins",
        "tags": [
          "Calendar"
        ],
        "summary": "The calendar add-ins (Outlook, Google Calendar) you connected, one per workspace and calendar, with how many meetings ea",
        "description": "The calendar add-ins (Outlook, Google Calendar) you connected, one per workspace and calendar, with how many meetings each scheduled, and the add-in's manifest address.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"connections\": [ { \"id\": \"01JBP4…\", \"client\": \"outlook\", \"workspaceId\": \"01JB8Q…\",\n  \"workspaceName\": \"Northwind Traders\", \"createdAt\": 1761800000000,\n  \"lastUsedAt\": 1761886400000, \"meetings\": 7 } ],\n  \"outlookManifestUrl\": \"https://app.freesbe.net/addins/outlook/manifest.xml\" }\n```",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiMeCalendarAddins",
        "tags": [
          "Calendar"
        ],
        "summary": "What the add-in's sign-in window calls: connects the Outlook add-in (client: outlook) or the Google Calendar add-on (goo",
        "description": "What the add-in's sign-in window calls: connects the Outlook add-in (`client`: `outlook`) or the Google Calendar add-on (`google`) to a workspace. Outlook's gets its token (`fsb-cal-…`), which can only schedule your meetings there; Google's gets a one-time code, good for ten minutes, that the add-on trades for its token with `POST /addins/google/token` (body: `code`). Connecting again replaces the old token. Answers 403 when the workspace's admins turned the add-ins off, and to guests.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.\n\nExample request:\n\n```json\n{ \"client\": \"outlook\", \"workspaceId\": \"01JB8Q…\" }\n```",
        "x-freesbe-access": "app",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/calendar-addins/{id}": {
      "delete": {
        "operationId": "deleteApiMeCalendarAddinsById",
        "tags": [
          "Calendar"
        ],
        "summary": "Disconnect an add-in; its token stops working at once.",
        "description": "Disconnect an add-in; its token stops working at once. Meetings it scheduled stay. Answers 204.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/calendar-addins/meetings": {
      "post": {
        "operationId": "postApiCalendarAddinsMeetings",
        "tags": [
          "Calendar"
        ],
        "summary": "The add-in's own call, with its token as Authorization: Bearer fsb-cal-…: the Freesbe meeting for the Outlook or Google ",
        "description": "The add-in's own call, with its token as `Authorization: Bearer fsb-cal-…`: the Freesbe meeting for the Outlook or Google Calendar event it's in. The same event (by `eventId`, or the `code` of the link already in the invitation) keeps its meeting, brought up to date; otherwise a new one. Freesbe sends no emails for it, since the calendar sends the invitation. Returns the meeting, the link to put in the invitation, and the text for it in the calendar's `locale`.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.\n\nExample request:\n\n```json\n{ \"title\": \"Quarterly review\", \"startsAt\": 1761912000000, \"endsAt\": 1761915600000,\n  \"timeZone\": \"America/New_York\",\n  \"attendees\": [ { \"email\": \"jordan@acme.example\", \"name\": \"Jordan Lee\" } ],\n  \"locale\": \"en-US\" }\n```\n\nExample answer:\n\n```json\n{ \"meeting\": { \"id\": \"01JBP9…\", \"code\": \"abc-defg-hij\", \"source\": \"outlook\", … },\n  \"joinUrl\": \"https://meet.freesbe.net/abc-defg-hij\", \"workspaceName\": \"Northwind Traders\",\n  \"reused\": false, \"inviteHtml\": \"<div id=\"freesbe-meeting\">…</div>\", \"inviteText\": \"…\" }\n```",
        "x-freesbe-access": "app",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/calendar-addins/me": {
      "get": {
        "operationId": "getApiCalendarAddinsMe",
        "tags": [
          "Calendar"
        ],
        "summary": "With the add-in's token: who it belongs to and in which workspace.",
        "description": "With the add-in's token: who it belongs to and in which workspace.\n\nWho can call it: App only. Needs the Freesbe app or a browser (a passkey prompt, a sign-in redirect, a call). Listed so you know it exists; scripts can't use it.\n\nExample answer:\n\n```json\n{ \"name\": \"Maya Patel\", \"email\": \"maya@northwind.example\", \"workspaceName\": \"Northwind Traders\" }\n```",
        "x-freesbe-access": "app",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/availability": {
      "post": {
        "operationId": "postApiWorkspacesByWAvailability",
        "tags": [
          "Calendar"
        ],
        "summary": "What it takes to find a time for up to 20 userIds between from and to, at most 8 days apart.",
        "description": "What it takes to find a time for up to 20 `userIds` between `from` and `to`, at most 8 days apart. `busy` comes from each person's connected calendar (`calendar` is `connected`, `none` or `error`); `meetings` are their Freesbe meetings in any workspace, leaving out `exceptMeetingId` when you're moving one. `workingHours` (Sunday first, minutes after midnight) are in their `timezone`, and `dndUntil` is when their paused notifications resume.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"userIds\": [\"01JB8R…\", \"01JB8T…\"], \"from\": 1761292800000, \"to\": 1761379200000 }\n```\n\nExample answer:\n\n```json\n{ \"people\": [\n  { \"userId\": \"01JB8R…\", \"calendar\": \"connected\",\n    \"busy\": [ { \"start\": 1761300000000, \"end\": 1761303600000 } ],\n    \"meetings\": [ { \"start\": 1761307200000, \"end\": 1761309000000 } ],\n    \"timezone\": \"Europe/London\",\n    \"workingHours\": [[], [[540, 1020]], [[540, 1020]], [[540, 1020]], [[540, 1020]], [[540, 1020]], []],\n    \"dndUntil\": null },\n  { \"userId\": \"01JB8T…\", \"calendar\": \"none\", \"busy\": [], \"meetings\": [], … }\n] }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/booking-links": {
      "get": {
        "operationId": "getApiWorkspacesByWBookingLinks",
        "tags": [
          "Bookings"
        ],
        "summary": "Your booking pages in the workspace, the baseUrl they start with (the workspace's customDomain when it has one), whether",
        "description": "Your booking pages in the workspace, the `baseUrl` they start with (the workspace's `customDomain` when it has one), whether your calendar is checked, and whether bookings are emailed.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWBookingLinks",
        "tags": [
          "Bookings"
        ],
        "summary": "Make a link: slug (3 to 40 lowercase letters, digits and dashes), title, durations, weekly hours (Sunday first, as minut",
        "description": "Make a link: `slug` (3 to 40 lowercase letters, digits and dashes), `title`, `durations`, weekly `hours` (Sunday first, as minutes after midnight) and `timeZone`, and optionally `description`, `minNoticeMin`, `maxDaysAhead`, `bufferMin`, `showPhoto`, `verifyEmail` (bookers type a code we email them; on unless set), `onePerPerson` (one upcoming booking per address; on unless set), `enabled` and `questions`. `questions` (up to 6) are asked on the page after name and email: each has an `id` you pick (letters, digits, `-` and `_`), a `kind` (`company`, `team_size`, `phone`, or `text` with your own `label`) and `required`. Company, team size and phone can each be asked once. Answers 201, or 409 when the name is taken.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{\n  \"slug\": \"dana-intro\",\n  \"title\": \"Intro call with Dana\",\n  \"durations\": [15, 30],\n  \"hours\": [[], [[540, 1020]], [[540, 1020]], [[540, 1020]], [[540, 1020]], [[540, 720]], []],\n  \"timeZone\": \"Europe/London\",\n  \"minNoticeMin\": 240,\n  \"bufferMin\": 10,\n  \"questions\": [\n    { \"id\": \"company\", \"kind\": \"company\", \"required\": true },\n    { \"id\": \"size\", \"kind\": \"team_size\", \"required\": false },\n    { \"id\": \"goal\", \"kind\": \"text\", \"label\": \"What would you like to see?\", \"required\": false }\n  ]\n}\n```\n\nExample answer:\n\n```json\n{ \"link\": { \"id\": \"01JBJ2…\", \"slug\": \"dana-intro\", \"url\": \"https://app.freesbe.net/b/dana-intro\",\n  \"title\": \"Intro call with Dana\", \"durations\": [15, 30], \"maxDaysAhead\": 60, \"enabled\": true, … } }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/booking-links/{id}": {
      "patch": {
        "operationId": "patchApiBookingLinksById",
        "tags": [
          "Bookings"
        ],
        "summary": "Change one of your links.",
        "description": "Change one of your links. Send the whole link, as when making it; `enabled: false` pauses it. Leave out `questions` to keep the link's questions as they are.\n\nWho can call it: Its owner. Only the person it belongs to, such as the maker of a booking page.",
        "x-freesbe-access": "owner",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiBookingLinksById",
        "tags": [
          "Bookings"
        ],
        "summary": "Delete one of your links.",
        "description": "Delete one of your links. Meetings already booked stay. Answers 204.\n\nWho can call it: Its owner. Only the person it belongs to, such as the maker of a booking page.",
        "x-freesbe-access": "owner",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/booking-slugs/{slug}": {
      "get": {
        "operationId": "getApiBookingSlugsBySlug",
        "tags": [
          "Bookings"
        ],
        "summary": "Whether a link name is free.",
        "description": "Whether a link name is free.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"slug\": \"dana-intro\", \"available\": true }\n```",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/book/{slug}": {
      "get": {
        "operationId": "getApiBookBySlug",
        "tags": [
          "Bookings"
        ],
        "summary": "What the booking page shows: title, description, owner, workspace, the lengths offered, the owner's time zone and the li",
        "description": "What the booking page shows: title, description, owner, workspace, the lengths offered, the owner's time zone and the link's `questions`.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      },
      "post": {
        "operationId": "postApiBookBySlug",
        "tags": [
          "Bookings"
        ],
        "summary": "Book a time: durationMin, startsAt, name, email, and optionally a note, the booker's timeZone and answers to the link's ",
        "description": "Book a time: `durationMin`, `startsAt`, `name`, `email`, and optionally a `note`, the booker's `timeZone` and `answers` to the link's questions, by question id. Required questions need an answer; `team_size` is one of `1-10`, `11-50`, `51-200`, `201-1000` or `1000+`. The answers go into the meeting's description, the `booking.created` event and workflow variables. Answers 201 with `status: \"booked\"`, the booker's own meeting link, whether an invite was emailed, and `manageUrl`, the booker's page to move or cancel it. When the page verifies bookers' email, it answers 202 with `status: \"verify\"` and a `holdId` instead: a 6-digit code went to the address and the time is held for 10 minutes. When the address already has an upcoming booking on a page that takes one per person, it answers `status: \"already_booked\"` and emails the address its booking's link.\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample request:\n\n```json\n{ \"durationMin\": 30, \"startsAt\": 1761301800000, \"name\": \"Jordan Lee\",\n  \"email\": \"jordan@acme.example\", \"note\": \"Pricing for 40 seats\", \"timeZone\": \"America/Chicago\",\n  \"answers\": { \"company\": \"Acme Corp\", \"size\": \"11-50\" } }\n```\n\nExample answer:\n\n```json\n{ \"title\": \"Intro call with Dana\", \"startsAt\": 1761301800000, \"durationMin\": 30,\n  \"ownerName\": \"Dana Whitfield\", \"meetingUrl\": \"https://meet.freesbe.net/…\", \"emailed\": true,\n  \"manageUrl\": \"https://app.freesbe.net/b/dana?manage=…\" }\n```",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/book/{slug}/slots": {
      "get": {
        "operationId": "getApiBookBySlugSlots",
        "tags": [
          "Bookings"
        ],
        "summary": "The free start times for one length, between from and to (at most 42 days apart).",
        "description": "The free start times for one length, between `from` and `to` (at most 42 days apart).\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample answer:\n\n```json\n{ \"durationMin\": 30, \"slots\": [1761300000000, 1761301800000, 1761303600000] }\n```",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "duration",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/book/{slug}/verify": {
      "post": {
        "operationId": "postApiBookBySlugVerify",
        "tags": [
          "Bookings"
        ],
        "summary": "Confirm a held time with the code from the email: holdId and code.",
        "description": "Confirm a held time with the code from the email: `holdId` and `code`. Answers like booking does, or `status: \"already_booked\"` with the existing booking's `manageUrl`. A wrong code answers 400 (five tries); a code that ran out answers 409.\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample request:\n\n```json\n{ \"holdId\": \"01JBK7…\", \"code\": \"482913\" }\n```",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/book/{slug}/resend": {
      "post": {
        "operationId": "postApiBookBySlugResend",
        "tags": [
          "Bookings"
        ],
        "summary": "Email a new code for a held time: holdId.",
        "description": "Email a new code for a held time: `holdId`. Up to two more codes per hold; the hold runs 10 minutes from the new code.\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample request:\n\n```json\n{ \"holdId\": \"01JBK7…\" }\n```",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/book/manage/{meetingId}": {
      "get": {
        "operationId": "getApiBookManageByMeetingId",
        "tags": [
          "Bookings"
        ],
        "summary": "The booker's own booking, by the secret t from their manageUrl (the part after the dot in manage=<meetingId>.<secret>): ",
        "description": "The booker's own booking, by the secret `t` from their `manageUrl` (the part after the dot in `manage=<meetingId>.<secret>`): its time, who it's with, their meeting link, whether it's canceled, the booking page it came from, and whether it can still be moved (`canReschedule`) or canceled (`canCancel`), and `changesLeft`, how many more times the booker can move it.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "meetingId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "t",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/book/manage/{meetingId}/slots": {
      "get": {
        "operationId": "getApiBookManageByMeetingIdSlots",
        "tags": [
          "Bookings"
        ],
        "summary": "The free times the booking can move to, at its own length.",
        "description": "The free times the booking can move to, at its own length. Its current time counts as free.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "meetingId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "t",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/book/manage/{meetingId}/reschedule": {
      "post": {
        "operationId": "postApiBookManageByMeetingIdReschedule",
        "tags": [
          "Bookings"
        ],
        "summary": "Move the booking to a free time: token (the secret) and startsAt, and optionally the booker's timeZone.",
        "description": "Move the booking to a free time: `token` (the secret) and `startsAt`, and optionally the booker's `timeZone`. Both sides get an updated invite. Answers like booking does.\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample request:\n\n```json\n{ \"token\": \"…\", \"startsAt\": 1761309000000, \"timeZone\": \"America/Chicago\" }\n```",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "meetingId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/book/manage/{meetingId}/cancel": {
      "post": {
        "operationId": "postApiBookManageByMeetingIdCancel",
        "tags": [
          "Bookings"
        ],
        "summary": "Cancel the booking: token, and optionally a reason for the host.",
        "description": "Cancel the booking: `token`, and optionally a `reason` for the host. Both sides get a cancellation. Answers 204.\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample request:\n\n```json\n{ \"token\": \"…\", \"reason\": \"Our budget review moved to November\" }\n```",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "meetingId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/book/{slug}/photo": {
      "get": {
        "operationId": "getApiBookBySlugPhoto",
        "tags": [
          "Bookings"
        ],
        "summary": "The owner's photo, when the link shows it.",
        "description": "The owner's photo, when the link shows it. On a team page, `?h=` is the person's place in the page's `team.hosts`.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/team-booking-pages": {
      "get": {
        "operationId": "getApiWorkspacesByWTeamBookingPages",
        "tags": [
          "Team booking pages"
        ],
        "summary": "The workspace's team booking pages, with their people in order (and who paused themselves), the baseUrl links start with",
        "description": "The workspace's team booking pages, with their people in order (and who paused themselves), the `baseUrl` links start with, and whether the plan `included` them.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWTeamBookingPages",
        "tags": [
          "Team booking pages"
        ],
        "summary": "Make a team page: everything a booking page takes (see Bookings), plus mode (round_robin or together), order (fewest or ",
        "description": "Make a team page: everything a booking page takes (see Bookings), plus `mode` (`round_robin` or `together`), `order` (`fewest` or `priority`, for round robin) and `hostIds`, up to 20 members in order. Guests can't take bookings. Answers 201, 403 when the plan doesn't include team pages, or 409 when the name is taken.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{\n  \"slug\": \"northwind-demo\",\n  \"title\": \"Product demo\",\n  \"durations\": [30],\n  \"hours\": [[], [[540, 1020]], [[540, 1020]], [[540, 1020]], [[540, 1020]], [[540, 1020]], []],\n  \"timeZone\": \"America/New_York\",\n  \"mode\": \"round_robin\",\n  \"order\": \"fewest\",\n  \"hostIds\": [\"01JBJ2…\", \"01JBJ3…\", \"01JBJ4…\"]\n}\n```\n\nExample answer:\n\n```json\n{ \"id\": \"01JBK1…\", \"slug\": \"northwind-demo\", \"url\": \"https://app.freesbe.net/b/northwind-demo\",\n  \"mode\": \"round_robin\", \"order\": \"fewest\",\n  \"hosts\": [{ \"userId\": \"01JBJ2…\", \"name\": \"Maya Chen\", \"paused\": false }, …], … }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/team-booking-pages/{id}": {
      "patch": {
        "operationId": "patchApiTeamBookingPagesById",
        "tags": [
          "Team booking pages"
        ],
        "summary": "Change a team page.",
        "description": "Change a team page. Send the whole page, as when making it; `enabled: false` pauses it for everyone. People who paused themselves stay paused.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiTeamBookingPagesById",
        "tags": [
          "Team booking pages"
        ],
        "summary": "Delete a team page.",
        "description": "Delete a team page. Meetings already booked stay. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/team-booking-pages/mine": {
      "get": {
        "operationId": "getApiWorkspacesByWTeamBookingPagesMine",
        "tags": [
          "Team booking pages"
        ],
        "summary": "The team pages you take bookings on, and whether you paused yourself on each.",
        "description": "The team pages you take bookings on, and whether you paused yourself on each.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"pages\": [{ \"id\": \"01JBK1…\", \"title\": \"Product demo\", \"url\": \"https://app.freesbe.net/b/northwind-demo\",\n  \"mode\": \"round_robin\", \"enabled\": true, \"paused\": false, \"hostNames\": [\"Maya Chen\", \"Sam Ortiz\"] }] }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/team-booking-pages/{id}/me": {
      "put": {
        "operationId": "putApiTeamBookingPagesByIdMe",
        "tags": [
          "Team booking pages"
        ],
        "summary": "Pause or resume yourself on a team page: paused.",
        "description": "Pause or resume yourself on a team page: `paused`. While paused, your times aren't offered and no bookings go to you.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"paused\": true }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/custom-domain": {
      "get": {
        "operationId": "getApiWorkspacesByWCustomDomain",
        "tags": [
          "Custom domain"
        ],
        "summary": "The workspace's domain, if any, with its status (pending, active or failed), what it's still waiting for, and the DNS re",
        "description": "The workspace's domain, if any, with its `status` (`pending`, `active` or `failed`), what it's still waiting for, and the DNS records to add. Also the workspace's `plan` and whether it `included` a custom domain.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"domain\": { \"hostname\": \"meetme.northwind.example\", \"status\": \"pending\",\n  \"problem\": \"Waiting for the CNAME record\",\n  \"cname\": { \"name\": \"meetme.northwind.example\", \"target\": \"…\" }, \"txt\": null, \"createdAt\": 1761200000000, … },\n  \"plan\": \"corporate\", \"included\": true, \"configured\": true }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWCustomDomain",
        "tags": [
          "Custom domain"
        ],
        "summary": "Connect a subdomain you own (hostname; a bare domain like northwind.example can't be used).",
        "description": "Connect a subdomain you own (`hostname`; a bare domain like `northwind.example` can't be used). 403 when the plan doesn't include it, 409 when the workspace already has one or another workspace uses it.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"hostname\": \"meetme.northwind.example\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWCustomDomain",
        "tags": [
          "Custom domain"
        ],
        "summary": "Disconnect the domain.",
        "description": "Disconnect the domain. Links go back to the Freesbe address. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/custom-domain/check": {
      "post": {
        "operationId": "postApiWorkspacesByWCustomDomainCheck",
        "tags": [
          "Custom domain"
        ],
        "summary": "Check again whether the DNS record and certificate are ready.",
        "description": "Check again whether the DNS record and certificate are ready.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/time/clock": {
      "get": {
        "operationId": "getApiWorkspacesByWTimeClock",
        "tags": [
          "Punch clock"
        ],
        "summary": "Your clock: the settings, whether the clock covers you, and whether you're working, on a break or off.",
        "description": "Your clock: the settings, whether the clock covers you, and whether you're `working`, on a `break` or `off`.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{\n  \"settings\": { \"enabled\": true, \"trackEveryone\": false, \"weekStart\": 1, \"timezone\": null,\n                \"dailyOvertimeMinutes\": 480, \"weeklyOvertimeMinutes\": 2400,\n                \"maxShiftMinutes\": 720, \"paidBreaks\": false },\n  \"tracked\": true,\n  \"clock\": { \"userId\": \"01JB8R…\", \"state\": \"working\", \"since\": 1761202800000,\n             \"shiftStartedAt\": 1761202800000 }\n}\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWTimeClock",
        "tags": [
          "Punch clock"
        ],
        "summary": "action: in, break, resume or out, with an optional note and your current timezone.",
        "description": "`action`: `in`, `break`, `resume` or `out`, with an optional `note` and your current `timezone`.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"action\": \"in\", \"note\": \"Opening the Acme Corp warehouse\" }\n```\n\nExample answer:\n\n```json\n{\n  \"settings\": { \"enabled\": true, \"trackEveryone\": false, \"weekStart\": 1, \"timezone\": null,\n                \"dailyOvertimeMinutes\": 480, \"weeklyOvertimeMinutes\": 2400,\n                \"maxShiftMinutes\": 720, \"paidBreaks\": false },\n  \"tracked\": true,\n  \"clock\": { \"userId\": \"01JB8R…\", \"state\": \"working\", \"since\": 1761202800000,\n             \"shiftStartedAt\": 1761202800000 }\n}\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/time/entries": {
      "get": {
        "operationId": "getApiWorkspacesByWTimeEntries",
        "tags": [
          "Punch clock"
        ],
        "summary": "Entries between from and to (milliseconds, at most 93 days): your own, or for admins everyone's, or one person's with us",
        "description": "Entries between `from` and `to` (milliseconds, at most 93 days): your own, or for admins everyone's, or one person's with `userId`.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWTimeEntries",
        "tags": [
          "Punch clock"
        ],
        "summary": "Add time after the fact: kind (work or break), startedAt, endedAt, note and a reason.",
        "description": "Add time after the fact: `kind` (`work` or `break`), `startedAt`, `endedAt`, `note` and a `reason`. Admins can add it for someone with `userId`.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"kind\": \"work\", \"startedAt\": 1761116400000, \"endedAt\": 1761145200000,\n  \"note\": \"Stocktake at the Acme Corp warehouse\", \"reason\": \"Forgot to clock in\" }\n```\n\nExample answer:\n\n```json\n{\n  \"entry\": {\n    \"id\": \"01JBH5…\",\n    \"userId\": \"01JB8R…\",\n    \"kind\": \"work\",\n    \"startedAt\": 1761116400000,\n    \"endedAt\": 1761145200000,\n    \"timezone\": \"Asia/Singapore\",\n    \"source\": \"manual\",\n    \"note\": \"Stocktake at the Acme Corp warehouse\",\n    \"edited\": false\n  }\n}\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/time/entries/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWTimeEntriesById",
        "tags": [
          "Punch clock"
        ],
        "summary": "Change an entry: your own, or anyone's for admins.",
        "description": "Change an entry: your own, or anyone's for admins. Needs a `reason`.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"endedAt\": 1761148800000, \"reason\": \"Stayed for the delivery\" }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWTimeEntriesById",
        "tags": [
          "Punch clock"
        ],
        "summary": "Delete an entry, with a reason in the body.",
        "description": "Delete an entry, with a `reason` in the body. Answers 204.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/time/entries/{id}/history": {
      "get": {
        "operationId": "getApiWorkspacesByWTimeEntriesByIdHistory",
        "tags": [
          "Punch clock"
        ],
        "summary": "Every change to an entry, oldest first: who, when, before, after and why.",
        "description": "Every change to an entry, oldest first: who, when, before, after and why.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/time/board": {
      "get": {
        "operationId": "getApiWorkspacesByWTimeBoard",
        "tags": [
          "Punch clock"
        ],
        "summary": "Who is on the clock right now.",
        "description": "Who is on the clock right now.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/time/export": {
      "get": {
        "operationId": "getApiWorkspacesByWTimeExport",
        "tags": [
          "Punch clock"
        ],
        "summary": "Timesheets as CSV: from and to dates (YYYY-MM-DD), format shifts or daily, optionally one userId.",
        "description": "Timesheets as CSV: `from` and `to` dates (`YYYY-MM-DD`), `format` `shifts` or `daily`, optionally one `userId`. Days are cut in each person's time zone.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/time/settings": {
      "get": {
        "operationId": "getApiWorkspacesByWTimeSettings",
        "tags": [
          "Punch clock"
        ],
        "summary": "The punch clock settings and who it covers (trackedUserIds).",
        "description": "The punch clock settings and who it covers (`trackedUserIds`).\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiWorkspacesByWTimeSettings",
        "tags": [
          "Punch clock"
        ],
        "summary": "Turn it on (enabled), cover everyone (trackEveryone) or some people (trackedUserIds), and set weekStart, timezone, daily",
        "description": "Turn it on (`enabled`), cover everyone (`trackEveryone`) or some people (`trackedUserIds`), and set `weekStart`, `timezone`, daily and weekly overtime, the longest shift and `paidBreaks`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"enabled\": true, \"trackEveryone\": false, \"trackedUserIds\": [\"01JB8R…\"], \"weeklyOvertimeMinutes\": 2400 }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/apps": {
      "get": {
        "operationId": "getApiWorkspacesByWApps",
        "tags": [
          "Apps"
        ],
        "summary": "The workspace's apps, by name.",
        "description": "The workspace's apps, by name. Tokens aren't included, only their last four characters (`tokenHint`).\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWApps",
        "tags": [
          "Apps"
        ],
        "summary": "Make an app from manifest (parse YAML to JSON first).",
        "description": "Make an app from `manifest` (parse YAML to JSON first). It gets a bot user, in no channels yet, a bot token and a `signingSecret`; the token is only in this answer. Slack scope and event names are mapped; ones Freesbe doesn't have are listed in `unsupportedScopes` and `unsupportedEvents`, and events whose scope is missing in `eventsMissingScope`. With `settings.event_subscriptions.request_url`, the URL must answer [the challenge](#app-events) first, or this answers 400. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"manifest\": {\n  \"display_information\": { \"name\": \"Order desk\", \"description\": \"Posts new wholesale orders to #orders\" },\n  \"features\": { \"bot_user\": { \"display_name\": \"Order desk\" } },\n  \"oauth_config\": { \"scopes\": { \"bot\": [\"channels:read\", \"channels:join\", \"chat:write\"] } } } }\n```\n\nExample answer:\n\n```json\n{\n  \"app\": {\n    \"id\": \"01JC2A…\",\n    \"name\": \"Order desk\",\n    \"description\": \"Posts new wholesale orders to #orders\",\n    \"color\": \"#2D6A4F\",\n    \"botUserId\": \"01JC2B…\",\n    \"botName\": \"Order desk\",\n    \"iconUrl\": \"/api/avatars/01JC2B…?v=01JF…\",\n    \"scopes\": [\"channels:read\", \"channels:join\", \"chat:write\"],\n    \"manifest\": { \"display_information\": { \"name\": \"Order desk\", … }, … },\n    \"eventsUrl\": null,\n    \"events\": [],\n    \"tokenHint\": \"x9Qa\",\n    \"tokenCreatedAt\": 1761200000000,\n    \"lastUsedAt\": null,\n    \"createdBy\": \"01JB8Q…\",\n    \"createdAt\": 1761200000000,\n    \"disabledAt\": null\n  },\n  \"token\": \"fsb-bot-…\",\n  \"signingSecret\": \"8f14e45fceea167a5a36dedd4bea2543\"\n}\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/apps/{id}": {
      "get": {
        "operationId": "getApiWorkspacesByWAppsById",
        "tags": [
          "Apps"
        ],
        "summary": "One app.",
        "description": "One app.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiWorkspacesByWAppsById",
        "tags": [
          "Apps"
        ],
        "summary": "Replace the manifest (the name, colour, scopes, events and bot name follow it; a new request URL must answer the challen",
        "description": "Replace the `manifest` (the name, colour, scopes, events and bot name follow it; a new request URL must answer the challenge), or turn the app off and on with `disabled`. A turned-off app's token answers 401 and it gets no events.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"disabled\": true }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWAppsById",
        "tags": [
          "Apps"
        ],
        "summary": "Delete the app and its token.",
        "description": "Delete the app and its token. Its bot stays as a deactivated member, so its messages keep its name. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/apps/{id}/icon": {
      "put": {
        "operationId": "putApiWorkspacesByWAppsByIdIcon",
        "tags": [
          "Apps"
        ],
        "summary": "Give the app an icon, which is also its bot's picture in messages and member lists: the raw PNG, JPEG, GIF or WebP bytes",
        "description": "Give the app an icon, which is also its bot's picture in messages and member lists: the raw PNG, JPEG, GIF or WebP bytes with their `Content-Type`, up to 2 MB. A square picture works best. Answers with the app, its `iconUrl` set.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\ncurl -X PUT $API/api/workspaces/$W/apps/$APP/icon \\\n  -H \"Authorization: Bearer $FREESBE_TOKEN\" \\\n  -H 'Content-Type: image/png' --data-binary @order-desk.png\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWAppsByIdIcon",
        "tags": [
          "Apps"
        ],
        "summary": "Remove the app's icon, so its first letter shows again (or, for a Zapier, Make, n8n or Zoho Flow app, that tool's logo).",
        "description": "Remove the app's icon, so its first letter shows again (or, for a Zapier, Make, n8n or Zoho Flow app, that tool's logo). Answers with the app.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/apps/{id}/token": {
      "post": {
        "operationId": "postApiWorkspacesByWAppsByIdToken",
        "tags": [
          "Apps"
        ],
        "summary": "A new bot token, only in this answer.",
        "description": "A new bot token, only in this answer. The old one stops working at once.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/apps/{id}/secret": {
      "get": {
        "operationId": "getApiWorkspacesByWAppsByIdSecret",
        "tags": [
          "Apps"
        ],
        "summary": "The signing secret the app's event deliveries are signed with.",
        "description": "The signing secret the app's event deliveries are signed with.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"signingSecret\": \"8f14e45fceea167a5a36dedd4bea2543\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/apps/{id}/deliveries": {
      "get": {
        "operationId": "getApiWorkspacesByWAppsByIdDeliveries",
        "tags": [
          "Apps"
        ],
        "summary": "The last 50 event deliveries to the app's request URL, newest first, kept for 14 days.",
        "description": "The last 50 event deliveries to the app's request URL, newest first, kept for 14 days. Same shape as a webhook's deliveries.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/apps/me": {
      "get": {
        "operationId": "getApiAppsMe",
        "tags": [
          "Apps"
        ],
        "summary": "Which app, bot user and workspace the token belongs to, and its scopes, like Slack's auth.test.",
        "description": "Which app, bot user and workspace the token belongs to, and its scopes, like Slack's `auth.test`. Needs no scope.\n\nWho can call it: App token. Only an app's bot token (see Apps). People's tokens get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"appId\": \"01JC2A…\", \"appName\": \"Order desk\", \"botUserId\": \"01JC2B…\",\n  \"workspaceId\": \"01JB8Q…\", \"workspaceName\": \"Northwind Traders\",\n  \"scopes\": [\"channels:read\", \"channels:join\", \"chat:write\"] }\n```",
        "x-freesbe-access": "bot",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/apps/me/icon": {
      "put": {
        "operationId": "putApiAppsMeIcon",
        "tags": [
          "Apps"
        ],
        "summary": "Set the app's own icon, its bot's picture, like Slack's users.setPhoto: the raw PNG, JPEG, GIF or WebP bytes with their ",
        "description": "Set the app's own icon, its bot's picture, like Slack's `users.setPhoto`: the raw PNG, JPEG, GIF or WebP bytes with their `Content-Type`, up to 2 MB. Needs no scope. Answers with the app.\n\nWho can call it: App token. Only an app's bot token (see Apps). People's tokens get 403 forbidden.\n\nExample request:\n\n```json\ncurl -X PUT $API/api/apps/me/icon \\\n  -H \"Authorization: Bearer $BOT_TOKEN\" \\\n  -H 'Content-Type: image/png' --data-binary @icon.png\n```",
        "x-freesbe-access": "bot",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiAppsMeIcon",
        "tags": [
          "Apps"
        ],
        "summary": "Remove the app's icon, so its first letter shows again.",
        "description": "Remove the app's icon, so its first letter shows again. Needs no scope. Answers with the app.\n\nWho can call it: App token. Only an app's bot token (see Apps). People's tokens get 403 forbidden.",
        "x-freesbe-access": "bot",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/app-commands": {
      "get": {
        "operationId": "getApiWorkspacesByWAppCommands",
        "tags": [
          "Apps"
        ],
        "summary": "The slash commands and message actions the workspace's apps add, for the message box and message menus.",
        "description": "The slash commands and message actions the workspace's apps add, for the message box and message menus. Turned-off apps are left out.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"commands\": [ { \"appId\": \"01JC2A…\", \"appName\": \"Order desk\", \"color\": \"#2D6A4F\",\n    \"command\": \"/order\", \"description\": \"Look up an order\", \"usageHint\": \"[order number]\" } ],\n  \"messageActions\": [ { \"appId\": \"01JC2A…\", \"appName\": \"Order desk\", \"color\": \"#2D6A4F\",\n    \"callbackId\": \"create_order\", \"name\": \"Create order\", \"description\": \"\" } ] }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/commands": {
      "post": {
        "operationId": "postApiChannelsByCCommands",
        "tags": [
          "Apps"
        ],
        "summary": "Run a slash command in the channel (or the thread in threadRootId): Freesbe sends it to the app that has it.",
        "description": "Run a slash command in the channel (or the thread in `threadRootId`): Freesbe sends it to the app that has it. `reply` is the app's answer when only you see it, or null. 404 when no app has the command; 502 when the app can't be reached, answers with an error or takes longer than 3 seconds.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"command\": \"/order\", \"text\": \"4512\" }\n```\n\nExample answer:\n\n```json\n{ \"reply\": { \"id\": \"01JD…\", \"appId\": \"01JC2A…\", \"appName\": \"Order desk\", \"color\": \"#2D6A4F\",\n  \"channelId\": \"01JB9…\", \"threadRootId\": null, \"body\": \"Order 4512 is packed and ships today.\",\n  \"blocks\": [], \"createdAt\": 1761200000000 } }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/messages/{m}/app-actions": {
      "post": {
        "operationId": "postApiMessagesByMAppActions",
        "tags": [
          "Apps"
        ],
        "summary": "Send the message to one of an app's message actions, as Slack's message_action.",
        "description": "Send the message to one of an app's message actions, as Slack's `message_action`. Answers 204; the app answers later through its `response_url`, if at all.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"appId\": \"01JC2A…\", \"callbackId\": \"create_order\" }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/messages/{m}/app-buttons": {
      "post": {
        "operationId": "postApiMessagesByMAppButtons",
        "tags": [
          "Apps"
        ],
        "summary": "Press a button on an app's message: Freesbe sends the app Slack's block_actions.",
        "description": "Press a button on an app's message: Freesbe sends the app Slack's `block_actions`. `clientTrigger` is any random string; a dialog the app opens in answer comes over the socket with it. Answers 204; 404 when the button or app is gone.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"actionId\": \"pack_order\", \"blockId\": \"order_4471\", \"clientTrigger\": \"k3v9q2\" }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "m",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/channels/{c}/app-buttons": {
      "post": {
        "operationId": "postApiChannelsByCAppButtons",
        "tags": [
          "Apps"
        ],
        "summary": "Press a button on an app's answer only you see.",
        "description": "Press a button on an app's answer only you see. Those aren't kept, so send the button's `text` and `value` with it. Answers 204.\n\nWho can call it: Channel members. People who can see the channel: anyone in the workspace for a public channel, members for a private channel or DM.\n\nExample request:\n\n```json\n{ \"appId\": \"01JC2A…\", \"ephemeralId\": \"01JD…\", \"actionId\": \"restock\", \"text\": \"Restock\",\n  \"value\": \"assam\" }\n```",
        "x-freesbe-access": "channel",
        "parameters": [
          {
            "name": "c",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/app-views/{id}/submit": {
      "post": {
        "operationId": "postApiAppViewsByIdSubmit",
        "tags": [
          "Apps"
        ],
        "summary": "Send an app's dialog.",
        "description": "Send an app's dialog. `values` holds each input's answer by its block id: a string, or a list for checkboxes. The app hears it as `view_submission`; `action` is what it answered: `close`, `clear` (close every dialog), `errors` (by block id), or `update` and `push` with the next `view`.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"values\": { \"qty\": \"24\", \"warehouse\": \"singapore\" } }\n```\n\nExample answer:\n\n```json\n{ \"action\": \"errors\", \"errors\": { \"qty\": \"Only 12 cases left\" } }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/app-views/{id}/buttons": {
      "post": {
        "operationId": "postApiAppViewsByIdButtons",
        "tags": [
          "Apps"
        ],
        "summary": "Press a button in an app's dialog, with what's filled in so far.",
        "description": "Press a button in an app's dialog, with what's filled in so far. Answers 204.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"actionId\": \"add_item\", \"values\": { \"qty\": \"24\" } }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/app-views/{id}/close": {
      "post": {
        "operationId": "postApiAppViewsByIdClose",
        "tags": [
          "Apps"
        ],
        "summary": "Close an app's dialog, or every dialog of its stack with cleared.",
        "description": "Close an app's dialog, or every dialog of its stack with `cleared`. An app that set `notify_on_close` hears `view_closed`. Answers 204.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"cleared\": true }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/apps/views": {
      "post": {
        "operationId": "postApiAppsViews",
        "tags": [
          "Apps"
        ],
        "summary": "Open a dialog, like Slack's views.open: triggerId is the trigger_id of a command, action or button press (it works for 3",
        "description": "Open a dialog, like Slack's `views.open`: `triggerId` is the `trigger_id` of a command, action or button press (it works for 30 seconds), and `view` is a Block Kit modal. Needs no scope.\n\nWho can call it: App token. Only an app's bot token (see Apps). People's tokens get 403 forbidden.\n\nExample request:\n\n```json\n{ \"triggerId\": \"eyJh…\", \"view\": { \"type\": \"modal\", \"callback_id\": \"new_order\",\n  \"title\": { \"type\": \"plain_text\", \"text\": \"New order\" },\n  \"submit\": { \"type\": \"plain_text\", \"text\": \"Create\" },\n  \"blocks\": [ { \"type\": \"input\", \"block_id\": \"qty\", \"label\": { \"type\": \"plain_text\", \"text\": \"Cases\" },\n    \"element\": { \"type\": \"number_input\", \"action_id\": \"qty\", \"is_decimal_allowed\": false } } ] } }\n```\n\nExample answer:\n\n```json\n{ \"view\": { \"id\": \"01JD…\", \"rootId\": \"01JD…\", \"parentId\": null, \"hash\": \"a1b2c3d4e5f6\" } }\n```",
        "x-freesbe-access": "bot",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/apps/views/push": {
      "post": {
        "operationId": "postApiAppsViewsPush",
        "tags": [
          "Apps"
        ],
        "summary": "Add a dialog on top of an open one (views.push), with a trigger_id from inside it.",
        "description": "Add a dialog on top of an open one (`views.push`), with a `trigger_id` from inside it. Dialogs stack three deep.\n\nWho can call it: App token. Only an app's bot token (see Apps). People's tokens get 403 forbidden.\n\nExample request:\n\n```json\n{ \"triggerId\": \"eyJh…\", \"view\": { \"type\": \"modal\", \"title\": { \"type\": \"plain_text\", \"text\": \"Pick a tea\" }, \"blocks\": [] } }\n```",
        "x-freesbe-access": "bot",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/apps/views/{id}": {
      "put": {
        "operationId": "putApiAppsViewsById",
        "tags": [
          "Apps"
        ],
        "summary": "Change an open dialog (views.update).",
        "description": "Change an open dialog (`views.update`). With `hash`, 409 when it changed since.\n\nWho can call it: App token. Only an app's bot token (see Apps). People's tokens get 403 forbidden.\n\nExample request:\n\n```json\n{ \"view\": { \"type\": \"modal\", \"title\": { \"type\": \"plain_text\", \"text\": \"Order created\" }, \"blocks\": [] },\n  \"hash\": \"a1b2c3d4e5f6\" }\n```",
        "x-freesbe-access": "bot",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/app-hooks": {
      "get": {
        "operationId": "getApiWorkspacesByWAppHooks",
        "tags": [
          "Apps"
        ],
        "summary": "Every app's REST hooks, newest first, with the app's name and the channel's: what **Workspace settings → Integrations & ",
        "description": "Every app's REST hooks, newest first, with the app's name and the channel's: what **Workspace settings → Integrations & apps → Integrations → Automation** lists.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/app-hooks/{id}": {
      "delete": {
        "operationId": "deleteApiWorkspacesByWAppHooksById",
        "tags": [
          "Apps"
        ],
        "summary": "Stop an app's REST hook.",
        "description": "Stop an app's REST hook. The flow it belongs to stops hearing about the event.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/apps/hooks": {
      "get": {
        "operationId": "getApiAppsHooks",
        "tags": [
          "Apps"
        ],
        "summary": "The app's REST hooks: the events it asked to be sent to a URL, as Zapier, Make, n8n and Zoho Flow do.",
        "description": "The app's REST hooks: the events it asked to be sent to a URL, as Zapier, Make, n8n and Zoho Flow do. Needs no scope.\n\nWho can call it: App token. Only an app's bot token (see Apps). People's tokens get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"hooks\": [ { \"id\": \"01JE…\", \"event\": \"message.created\",\n  \"url\": \"https://hooks.zapier.com/hooks/standard/…\", \"channelId\": \"01JB8R…\",\n  \"source\": \"zapier\", \"createdAt\": 1767000000000 } ] }\n```",
        "x-freesbe-access": "bot",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiAppsHooks",
        "tags": [
          "Apps"
        ],
        "summary": "Send one [event](#app-events) to a URL from now on (a REST hook).",
        "description": "Send one [event](#app-events) to a URL from now on (a REST hook). The app needs the event's scope. With `channelId`, only that channel's events; for messages, reactions and files the bot has to be in the channel, and it joins a public one by itself when the app has `channels:join`. Each delivery has the event's `type` and `data` as an outgoing webhook's do, plus `user`: who did it (`id`, `name`, `isBot`, and `email` when the app has `users:read`). It's signed with the app's signing secret. Answer `410` and the hook is deleted. 100 hooks per app.\n\nWho can call it: App token. Only an app's bot token (see Apps). People's tokens get 403 forbidden.\n\nExample request:\n\n```json\n{ \"event\": \"message.created\", \"url\": \"https://hooks.zapier.com/hooks/standard/…\",\n  \"channelId\": \"01JB8R…\", \"source\": \"zapier\" }\n```\n\nExample answer:\n\n```json\n{ \"hook\": { \"id\": \"01JE…\", \"event\": \"message.created\", \"channelId\": \"01JB8R…\", … } }\n```",
        "x-freesbe-access": "bot",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/apps/hooks/{id}": {
      "delete": {
        "operationId": "deleteApiAppsHooksById",
        "tags": [
          "Apps"
        ],
        "summary": "Stop a REST hook.",
        "description": "Stop a REST hook. Answers 204.\n\nWho can call it: App token. Only an app's bot token (see Apps). People's tokens get 403 forbidden.",
        "x-freesbe-access": "bot",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/hooks/commands/{token}": {
      "post": {
        "operationId": "postHooksCommandsByToken",
        "tags": [
          "Apps"
        ],
        "summary": "An app's response_url: answer a slash command, message action or button press later, up to 30 minutes after.",
        "description": "An app's `response_url`: answer a slash command, message action or button press later, up to 30 minutes after. The body is a message like an incoming webhook's (`text`, `blocks`, `attachments`), with `\"response_type\": \"in_channel\"` to post it in the channel; otherwise only the person sees it. After a button press, `\"replace_original\": true` changes the message or answer the button was on, and `\"delete_original\": true` removes it. Answers `{ \"ok\": true }`.\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample request:\n\n```json\n{ \"replace_original\": true, \"text\": \"Order 4512 packed by Marcus\" }\n```",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/sign-in-apps": {
      "get": {
        "operationId": "getApiWorkspacesByWSignInApps",
        "tags": [
          "Sign in with Freesbe"
        ],
        "summary": "Every app people can sign in to with Freesbe, by name: the app, its Sign in with Freesbe settings, and when someone last",
        "description": "Every app people can sign in to with Freesbe, by name: the app, its Sign in with Freesbe settings, and when someone last signed in to it (`lastUsedAt`, null if nobody has).\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"issuer\": \"https://id.freesbe.net\", \"apps\": [{ \"app\": { \"id\": \"01JC2A…\",\n  \"name\": \"Northwind Dashboard\", \"color\": \"#1D4ED8\", … }, \"client\": { \"clientId\": \"01JC2A…\",\n  \"redirectUris\": [\"https://dashboard.northwind.example/auth/callback\"], \"who\": \"members\",\n  \"requireMfa\": true, … }, \"lastUsedAt\": 1792760520000 }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/apps/{id}/sign-in": {
      "get": {
        "operationId": "getApiWorkspacesByWAppsByIdSignIn",
        "tags": [
          "Sign in with Freesbe"
        ],
        "summary": "The app's Sign in with Freesbe settings, or client: null while it's off.",
        "description": "The app's Sign in with Freesbe settings, or `client: null` while it's off. The client id is the app's id; the secret shows only its last four characters.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"issuer\": \"https://id.freesbe.net\", \"client\": { \"clientId\": \"01JC2A…\",\n  \"redirectUris\": [\"https://dashboard.northwind.example/auth/callback\"], \"public\": false,\n  \"who\": \"members\", \"requireMfa\": false, \"preapproved\": false, \"secretHint\": \"x9Qa\", \"people\": 12,\n  \"notifyChannelId\": null } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWAppsByIdSignIn",
        "tags": [
          "Sign in with Freesbe"
        ],
        "summary": "Turns it on or changes it.",
        "description": "Turns it on or changes it. Return addresses must use https (http only for localhost); `public` apps may also use their own reverse-domain scheme and must use PKCE. `notifyChannelId` (a public or private channel, or null) is where the app's bot posts each sign-in. `requireMfa` (on unless you send false) makes people confirm it's them at every sign-in: a passkey, a phone approval or an authenticator app code from the last 5 minutes, or an emailed code for people with none of those; until they do, the sign-in page's request answers 403 `strong_mfa_required` (or `mfa_required`). The first time, the answer includes the client `secret`, shown once. `DELETE` turns it off.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"redirectUris\": [\"https://dashboard.northwind.example/auth/callback\"], \"who\": \"members\",\n  \"requireMfa\": true, \"preapproved\": false, \"public\": false, \"notifyChannelId\": \"01JC2C…\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/apps/{id}/sign-in/secret": {
      "post": {
        "operationId": "postApiWorkspacesByWAppsByIdSignInSecret",
        "tags": [
          "Sign in with Freesbe"
        ],
        "summary": "A new client secret, in secret; the old one stops working at once.",
        "description": "A new client secret, in `secret`; the old one stops working at once.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/connected-apps": {
      "get": {
        "operationId": "getApiMeConnectedApps",
        "tags": [
          "Sign in with Freesbe"
        ],
        "summary": "Apps you've allowed to sign you in, most recently used first.",
        "description": "Apps you've allowed to sign you in, most recently used first. `DELETE /api/me/connected-apps/{appId}` takes it back; the app asks again next time.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"apps\": [{ \"appId\": \"01JC2A…\", \"name\": \"Northwind Dashboard\", \"color\": \"#1D4ED8\",\n  \"workspaceName\": \"Northwind Traders\", \"scopes\": [\"openid\", \"profile\", \"email\"],\n  \"createdAt\": 1792540320000, \"lastUsedAt\": 1792760520000 }] }\n```",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/agent-connect/{id}": {
      "get": {
        "operationId": "getApiAgentConnectById",
        "tags": [
          "AI agents"
        ],
        "summary": "The connect page: the agent asking, the permissions it wants, and the person's workspaces with whether each one lets it ",
        "description": "The connect page: the agent asking, the permissions it wants, and the person's workspaces with whether each one lets it in (`allowed`, `approval` when an admin has to approve it first, `requested` while they do, `off`, or `blocked`) and which permissions it wouldn't get there (`withheld`). The id comes from the browser's redirect to `/connect/{id}`.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"id\": \"01JC7A…\", \"agent\": { \"name\": \"Claude\", \"host\": \"claude.ai\", \"logoUrl\": \"https://claude.ai/logo.png\" },\n  \"redirectHost\": \"claude.ai\", \"scopes\": [\"channels:read\", \"channels:history\", \"chat:write\"],\n  \"workspaces\": [{ \"id\": \"01JC2W…\", \"name\": \"Northwind Traders\", \"access\": \"allowed\", \"withheld\": [] }] }\n```",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiAgentConnectById",
        "tags": [
          "AI agents"
        ],
        "summary": "Allows the agent in a workspace, or not.",
        "description": "Allows the agent in a workspace, or not. The answer's `redirect` sends the browser back to the agent with a one-time code (`outcome: \"connected\"`), or with an error once admins have been asked to approve it (`\"requested\"`) or when the person said no (`\"denied\"`). Guests can't connect agents.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample request:\n\n```json\n{ \"workspaceId\": \"01JC2W…\", \"allow\": true, \"note\": \"For drafting release notes\" }\n```\n\nExample answer:\n\n```json\n{ \"outcome\": \"connected\", \"redirect\": \"https://claude.ai/api/mcp/auth_callback?code=…&state=…\" }\n```",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/me/agents": {
      "get": {
        "operationId": "getApiMeAgents",
        "tags": [
          "AI agents"
        ],
        "summary": "The agents you connected, most recently used first.",
        "description": "The agents you connected, most recently used first. `status` is `active`, `waiting` for an admin's approval, or `approved` once they gave it (connect again from the agent). `DELETE /api/me/agents/{grantId}` disconnects one at once.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.\n\nExample answer:\n\n```json\n{ \"agents\": [{ \"grantId\": \"01JC7G…\", \"agent\": { \"name\": \"Claude\", \"host\": \"claude.ai\", \"logoUrl\": null },\n  \"workspaceId\": \"01JC2W…\", \"workspaceName\": \"Northwind Traders\", \"scopes\": [\"channels:read\", \"chat:write\"],\n  \"status\": \"active\", \"createdAt\": 1792540320000, \"lastUsedAt\": 1792760520000 }] }\n```",
        "x-freesbe-access": "signed-in",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/agents": {
      "get": {
        "operationId": "getApiWorkspacesByWAgents",
        "tags": [
          "AI agents"
        ],
        "summary": "The workspace's agent settings, every agent anyone connected (with how many people, who is waiting for approval and thei",
        "description": "The workspace's agent settings, every agent anyone connected (with how many people, who is waiting for approval and their notes, and the permission ceiling), and the MCP server address to give people.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"settings\": { \"policy\": \"open\", \"allowPrivate\": false, \"postAsPerson\": false }, \"mcpUrl\": \"https://api.freesbe.net/mcp\",\n  \"agents\": [{ \"id\": \"01JC7B…\", \"agent\": { \"name\": \"Claude\", \"host\": \"claude.ai\", \"logoUrl\": null },\n    \"botUserId\": \"01JC7C…\", \"status\": \"allowed\", \"scopeCeiling\": null, \"people\": 4,\n    \"waiting\": [], \"createdAt\": 1792540320000, \"lastUsedAt\": 1792760520000 }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWAgents",
        "tags": [
          "AI agents"
        ],
        "summary": "Changes who can connect agents (off, approved or open), whether they may read private channels and direct messages, and ",
        "description": "Changes who can connect agents (`off`, `approved` or `open`), whether they may read private channels and direct messages, and whether they post as the person who connected them, with a \"via\" line (`postAsPerson`, kept as it is when left out). Answers like `GET`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"policy\": \"approved\", \"allowPrivate\": false, \"postAsPerson\": true }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/agents/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWAgentsById",
        "tags": [
          "AI agents"
        ],
        "summary": "Approves, allows or blocks an agent (status), or sets the most it may do here (scopeCeiling, a list of permissions, or n",
        "description": "Approves, allows or blocks an agent (`status`), or sets the most it may do here (`scopeCeiling`, a list of permissions, or `null` for any). Both apply to existing connections at once. `DELETE` removes the agent and all its connections from the workspace.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"status\": \"allowed\", \"scopeCeiling\": [\"channels:read\", \"channels:history\", \"chat:write\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/agents/activity": {
      "get": {
        "operationId": "getApiWorkspacesByWAgentsActivity",
        "tags": [
          "AI agents"
        ],
        "summary": "What agents did here, newest first, 50 at a time: connections, approvals, blocks, removals and every tool call.",
        "description": "What agents did here, newest first, 50 at a time: connections, approvals, blocks, removals and every tool call. Pass `next` back as `?before=` for older entries.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"activity\": [{ \"id\": \"01JC7D…\", \"agentName\": \"Claude\", \"userId\": \"01JC2U…\", \"userName\": \"Maya Chen\",\n  \"action\": \"tool\", \"tool\": \"get_connection\", \"ok\": true, \"detail\": null, \"at\": 1792760520000 }], \"next\": null }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/agent-questions/{id}/answer": {
      "post": {
        "operationId": "postApiAgentQuestionsByIdAnswer",
        "tags": [
          "AI agents"
        ],
        "summary": "Answers a question an agent asked you (the agent_question block on its message).",
        "description": "Answers a question an agent asked you (the `agent_question` block on its message). `value` fits the question's `answer.type`: text, a day (`\"2026-11-06\"`), an ETA (`{ \"date\", \"time\" }`, time optional), the choice or list of choices, `true` or `false`, or a number. Only the person it's with can answer, once; `409` when it's no longer waiting.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"value\": { \"date\": \"2026-11-06\", \"time\": \"15:00\" }, \"note\": \"Waiting on the carrier pickup\" }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/agent-questions/{id}/pass": {
      "post": {
        "operationId": "postApiAgentQuestionsByIdPass",
        "tags": [
          "AI agents"
        ],
        "summary": "Says the question isn't yours to answer.",
        "description": "Says the question isn't yours to answer. It goes to `suggestUserId` if given, or the next person the agent named, or back to the agent as declined.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample request:\n\n```json\n{ \"suggestUserId\": \"01JC2U…\" }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/agent-questions/{id}/later": {
      "post": {
        "operationId": "postApiAgentQuestionsByIdLater",
        "tags": [
          "AI agents"
        ],
        "summary": "Can't say yet: you're asked again at 9:00 on your next working day.",
        "description": "Can't say yet: you're asked again at 9:00 on your next working day.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/webhooks": {
      "get": {
        "operationId": "getApiWorkspacesByWWebhooks",
        "tags": [
          "Webhooks"
        ],
        "summary": "Every webhook you can see, newest first.",
        "description": "Every webhook you can see, newest first.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWWebhooks",
        "tags": [
          "Webhooks"
        ],
        "summary": "Create an incoming webhook (kind, name, channelId) or an outgoing one (kind, name, url, events, and channelId for one ch",
        "description": "Create an incoming webhook (`kind`, `name`, `channelId`) or an outgoing one (`kind`, `name`, `url`, `events`, and `channelId` for one channel). The incoming `hookUrl` or outgoing `secret` is only in this answer. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"kind\": \"outgoing\", \"name\": \"Support bot\", \"url\": \"https://bot.northwind.example/freesbe\",\n  \"events\": [\"message.created\", \"reaction.added\"] }\n```\n\nExample answer:\n\n```json\n{\n  \"webhook\": {\n    \"id\": \"01JBG3…\",\n    \"kind\": \"outgoing\",\n    \"name\": \"Support bot\",\n    \"channelId\": null,\n    \"url\": \"https://bot.northwind.example/freesbe\",\n    \"events\": [\"message.created\", \"reaction.added\"],\n    \"createdBy\": \"01JB8Q…\",\n    \"createdAt\": 1761200000000,\n    \"disabledAt\": null\n  },\n  \"secret\": \"…\"\n}\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/webhooks/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWWebhooksById",
        "tags": [
          "Webhooks"
        ],
        "summary": "Change name, url, events, channelId, or turn it off and on with disabled.",
        "description": "Change `name`, `url`, `events`, `channelId`, or turn it off and on with `disabled`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"disabled\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWWebhooksById",
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete it.",
        "description": "Delete it. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/webhooks/{id}/rotate": {
      "post": {
        "operationId": "postApiWorkspacesByWWebhooksByIdRotate",
        "tags": [
          "Webhooks"
        ],
        "summary": "A new URL (incoming) or signing secret (outgoing).",
        "description": "A new URL (incoming) or signing secret (outgoing). The old one stops working at once.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/webhooks/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWWebhooksByIdTest",
        "tags": [
          "Webhooks"
        ],
        "summary": "Send a webhook.test event (outgoing).",
        "description": "Send a `webhook.test` event (outgoing). Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/webhooks/{id}/deliveries": {
      "get": {
        "operationId": "getApiWorkspacesByWWebhooksByIdDeliveries",
        "tags": [
          "Webhooks"
        ],
        "summary": "The last 14 days of deliveries, newest first (outgoing): event, status, attempts, last HTTP code and error.",
        "description": "The last 14 days of deliveries, newest first (outgoing): event, status, attempts, last HTTP code and error.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/hooks/custom/{id}/{token}": {
      "post": {
        "operationId": "postHooksCustomByIdByToken",
        "tags": [
          "Webhooks"
        ],
        "summary": "Post to an incoming webhook.",
        "description": "Post to an incoming webhook. `{id}` is the webhook's ID; the token is the secret. Older `/hooks/{token}` URLs keep working. Answers `ok` as plain text.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/payment-alerts": {
      "get": {
        "operationId": "getApiWorkspacesByWPaymentAlerts",
        "tags": [
          "Payment alerts"
        ],
        "summary": "Every payment alert you can see, newest first: provider, channelId, kinds, minAmount, whether it's ready (its signing se",
        "description": "Every payment alert you can see, newest first: `provider`, `channelId`, `kinds`, `minAmount`, whether it's `ready` (its signing secret is saved) and `lastEventAt`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWPaymentAlerts",
        "tags": [
          "Payment alerts"
        ],
        "summary": "Connect an account: provider (mercury, stripe or airwallex), channelId, kinds (money_in, money_out, balance, other) and ",
        "description": "Connect an account: `provider` (`mercury`, `stripe` or `airwallex`), `channelId`, `kinds` (`money_in`, `money_out`, `balance`, `other`) and an optional `minAmount`. Mercury also takes `apiToken`, used once to register the webhook and not kept. Stripe and Airwallex answer with the `hookUrl` to paste into their dashboard, only in this answer. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"provider\": \"stripe\", \"channelId\": \"01J…\", \"kinds\": [\"money_in\", \"other\"], \"minAmount\": 100 }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/payment-alerts/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWPaymentAlertsById",
        "tags": [
          "Payment alerts"
        ],
        "summary": "Change channelId, kinds or minAmount, save the provider's signing secret (Stripe and Airwallex), or turn it off and on w",
        "description": "Change `channelId`, `kinds` or `minAmount`, save the provider's signing `secret` (Stripe and Airwallex), or turn it off and on with `disabled`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"secret\": \"whsec_…\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWPaymentAlertsById",
        "tags": [
          "Payment alerts"
        ],
        "summary": "Disconnect it.",
        "description": "Disconnect it. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/payment-alerts/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWPaymentAlertsByIdTest",
        "tags": [
          "Payment alerts"
        ],
        "summary": "Post a sample alert into its channel.",
        "description": "Post a sample alert into its channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/hooks/finance/{provider}/{token}": {
      "post": {
        "operationId": "postHooksFinanceByProviderByToken",
        "tags": [
          "Payment alerts"
        ],
        "summary": "Where the provider (mercury, stripe or airwallex) delivers events, signed with Mercury-Signature, Stripe-Signature, or A",
        "description": "Where the provider (`mercury`, `stripe` or `airwallex`) delivers events, signed with `Mercury-Signature`, `Stripe-Signature`, or Airwallex's `x-timestamp` and `x-signature`. Answers 200 to signed events, posted or filtered out, 401 to a bad or old signature and 404 when the alert is off or gone.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/commerce": {
      "get": {
        "operationId": "getApiWorkspacesByWCommerce",
        "tags": [
          "Commerce: Shopify and Amazon"
        ],
        "summary": "Every store you can see, newest first: provider, channelId, kinds, minAmount, whether it's ready, the store (the myshopi",
        "description": "Every store you can see, newest first: `provider`, `channelId`, `kinds`, `minAmount`, whether it's `ready`, the `store` (the myshopify.com domain or Amazon's seller id), Amazon's `region`, `brokenAt` and `lastEventAt`, plus `amazonAvailable`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWCommerce",
        "tags": [
          "Commerce: Shopify and Amazon"
        ],
        "summary": "Connect a store: provider (shopify or amazon), channelId, kinds (order, fulfilled, cancelled, refund, payout; Shopify le",
        "description": "Connect a store: `provider` (`shopify` or `amazon`), `channelId`, `kinds` (`order`, `fulfilled`, `cancelled`, `refund`, `payout`; Shopify leaves out `payout`, Amazon `refund`), an optional `minAmount`, and for Amazon a `region` (`na`, `eu` or `fe`). Shopify answers with the `hookUrl` to paste into the store's webhook settings, only in this answer; Amazon with the `authorizeUrl` where the admin approves Freesbe in Seller Central. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"provider\": \"shopify\", \"channelId\": \"01J…\", \"kinds\": [\"order\", \"refund\"], \"minAmount\": 50 }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/commerce/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWCommerceById",
        "tags": [
          "Commerce: Shopify and Amazon"
        ],
        "summary": "Change channelId, kinds or minAmount, save the key Shopify signs the store's webhooks with (secret), or turn it off and ",
        "description": "Change `channelId`, `kinds` or `minAmount`, save the key Shopify signs the store's webhooks with (`secret`), or turn it off and on with `disabled`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"secret\": \"…\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWCommerceById",
        "tags": [
          "Commerce: Shopify and Amazon"
        ],
        "summary": "Disconnect it: Freesbe forgets the signing key or Amazon's token.",
        "description": "Disconnect it: Freesbe forgets the signing key or Amazon's token. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/commerce/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWCommerceByIdTest",
        "tags": [
          "Commerce: Shopify and Amazon"
        ],
        "summary": "Post a sample alert into its channel.",
        "description": "Post a sample alert into its channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/commerce/{id}/connect": {
      "post": {
        "operationId": "postApiWorkspacesByWCommerceByIdConnect",
        "tags": [
          "Commerce: Shopify and Amazon"
        ],
        "summary": "Amazon only: a fresh url to approve Freesbe in Seller Central again, after Amazon stopped accepting it.",
        "description": "Amazon only: a fresh `url` to approve Freesbe in Seller Central again, after Amazon stopped accepting it.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/hooks/commerce/shopify/{token}": {
      "post": {
        "operationId": "postHooksCommerceShopifyByToken",
        "tags": [
          "Commerce: Shopify and Amazon"
        ],
        "summary": "Where a Shopify store delivers its order and refund webhooks, signed with X-Shopify-Hmac-Sha256.",
        "description": "Where a Shopify store delivers its order and refund webhooks, signed with `X-Shopify-Hmac-Sha256`. Answers 200 to signed deliveries, posted or filtered out, 401 to a bad signature and 404 when the store is off or gone.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/kraken": {
      "get": {
        "operationId": "getApiWorkspacesByWKraken",
        "tags": [
          "Kraken alerts"
        ],
        "summary": "Every Kraken account you can see, newest first: channelId, kinds, minUsd, keyHint (the key's last four characters), bala",
        "description": "Every Kraken account you can see, newest first: `channelId`, `kinds`, `minUsd`, `keyHint` (the key's last four characters), `balanceRules`, `summaryHour` and `summaryTimeZone`, `checkedAt`, `lastEventAt`, and `error` when Kraken refused the key.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWKraken",
        "tags": [
          "Kraken alerts"
        ],
        "summary": "Connect an account: apiKey and privateKey (a key with Query Funds and Query Ledger Entries), channelId, kinds (deposits,",
        "description": "Connect an account: `apiKey` and `privateKey` (a key with Query Funds and Query Ledger Entries), `channelId`, `kinds` (`deposits`, `withdrawals`, `trades`, `other`), and optionally `minUsd`, up to 10 `balanceRules` (`asset`, `op` `below` or `above`, `amount`), `summaryHour` (0 to 23) and `summaryTimeZone`. Freesbe checks the key reads the account first and answers 400 when Kraken refuses it, or when the key is already connected. The private key is never sent back. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"apiKey\": \"…\", \"privateKey\": \"…\", \"channelId\": \"01J…\", \"kinds\": [\"deposits\", \"trades\"], \"minUsd\": 100, \"balanceRules\": [{ \"asset\": \"BTC\", \"op\": \"below\", \"amount\": 0.5 }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/kraken/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWKrakenById",
        "tags": [
          "Kraken alerts"
        ],
        "summary": "Change any of the above, replace the key (apiKey and privateKey together), or turn it off and on with disabled.",
        "description": "Change any of the above, replace the key (`apiKey` and `privateKey` together), or turn it off and on with `disabled`. Turned back on, it carries on from then.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"summaryHour\": 9, \"summaryTimeZone\": \"America/New_York\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWKrakenById",
        "tags": [
          "Kraken alerts"
        ],
        "summary": "Disconnect it and forget the key.",
        "description": "Disconnect it and forget the key. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/kraken/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWKrakenByIdTest",
        "tags": [
          "Kraken alerts"
        ],
        "summary": "Post a sample alert into its channel.",
        "description": "Post a sample alert into its channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/crypto-wallets": {
      "get": {
        "operationId": "getApiWorkspacesByWCryptoWallets",
        "tags": [
          "Crypto wallets"
        ],
        "summary": "Every wallet you can see, newest first: network, address, name, channelId, directions, minUsd, balanceRules, checkedAt, ",
        "description": "Every wallet you can see, newest first: `network`, `address`, `name`, `channelId`, `directions`, `minUsd`, `balanceRules`, `checkedAt`, `lastEventAt`, and `error` when the network's data couldn't be read. Also `networks`, the ones this server can watch, and the workspace's daily `summary` (`channelId`, `hour`, `timeZone`) or null.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWCryptoWallets",
        "tags": [
          "Crypto wallets"
        ],
        "summary": "Watch a wallet: network (bitcoin, ethereum, base, arbitrum, optimism, polygon, bnb, avalanche, solana, tron), its public",
        "description": "Watch a wallet: `network` (`bitcoin`, `ethereum`, `base`, `arbitrum`, `optimism`, `polygon`, `bnb`, `avalanche`, `solana`, `tron`), its public `address`, a `name`, `channelId`, and optionally `directions` (`in`, `out`), `minUsd` and up to 5 `balanceRules` (`asset`: the network's coin, `USDC` or `USDT`; `op` `below` or `above`; `amount`). Answers 400 when the address isn't one for the network or is already watched. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"network\": \"tron\", \"address\": \"T…\", \"name\": \"Customer payments\", \"channelId\": \"01J…\", \"minUsd\": 50, \"balanceRules\": [{ \"asset\": \"USDT\", \"op\": \"below\", \"amount\": 10000 }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/crypto-wallets/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWCryptoWalletsById",
        "tags": [
          "Crypto wallets"
        ],
        "summary": "Change the name, channelId, directions, minUsd or balanceRules, or turn it off and on with disabled.",
        "description": "Change the `name`, `channelId`, `directions`, `minUsd` or `balanceRules`, or turn it off and on with `disabled`. Turned back on, it carries on from then. The network and address stay as they are.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"directions\": [\"in\"], \"minUsd\": 100 }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWCryptoWalletsById",
        "tags": [
          "Crypto wallets"
        ],
        "summary": "Stop watching the wallet.",
        "description": "Stop watching the wallet. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/crypto-wallets/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWCryptoWalletsByIdTest",
        "tags": [
          "Crypto wallets"
        ],
        "summary": "Post a sample alert into its channel.",
        "description": "Post a sample alert into its channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/crypto-wallets/summary": {
      "put": {
        "operationId": "putApiWorkspacesByWCryptoWalletsSummary",
        "tags": [
          "Crypto wallets"
        ],
        "summary": "Set the daily card with every wallet's balances: summary with channelId, hour (0 to 23) and timeZone, or null to turn it",
        "description": "Set the daily card with every wallet's balances: `summary` with `channelId`, `hour` (0 to 23) and `timeZone`, or null to turn it off. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"summary\": { \"channelId\": \"01J…\", \"hour\": 9, \"timeZone\": \"America/New_York\" } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/hubspot": {
      "get": {
        "operationId": "getApiWorkspacesByWHubspot",
        "tags": [
          "HubSpot"
        ],
        "summary": "Whether the server can connect HubSpot (available), the connection (portalId, hubDomain, botUserId, unfurls, brokenAt wh",
        "description": "Whether the server can connect HubSpot (`available`), the `connection` (`portalId`, `hubDomain`, `botUserId`, `unfurls`, `brokenAt` when HubSpot stopped accepting it) or null, and the `alerts`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiWorkspacesByWHubspot",
        "tags": [
          "HubSpot"
        ],
        "summary": "Turn link previews on or off with unfurls.",
        "description": "Turn link previews on or off with `unfurls`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"unfurls\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWHubspot",
        "tags": [
          "HubSpot"
        ],
        "summary": "Disconnect: Freesbe forgets HubSpot's access and the app's command and action go away.",
        "description": "Disconnect: Freesbe forgets HubSpot's access and the app's command and action go away. Alerts are kept for a reconnect. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/hubspot/connect": {
      "post": {
        "operationId": "postApiWorkspacesByWHubspotConnect",
        "tags": [
          "HubSpot"
        ],
        "summary": "The url of HubSpot's page that asks to allow Freesbe.",
        "description": "The `url` of HubSpot's page that asks to allow Freesbe. Send the browser there; HubSpot sends it back to Freesbe, which finishes connecting and opens the app with `?hubspot=connected`. Only the admin who started it can finish it, within 15 minutes.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/hubspot/alerts": {
      "post": {
        "operationId": "postApiWorkspacesByWHubspotAlerts",
        "tags": [
          "HubSpot"
        ],
        "summary": "Add an alert: channelId, kinds (deal_created, deal_stage, deal_won, deal_lost, contact_created) and an optional minAmoun",
        "description": "Add an alert: `channelId`, `kinds` (`deal_created`, `deal_stage`, `deal_won`, `deal_lost`, `contact_created`) and an optional `minAmount` for deals. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"channelId\": \"01J…\", \"kinds\": [\"deal_created\", \"deal_won\"], \"minAmount\": 5000 }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/hubspot/alerts/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWHubspotAlertsById",
        "tags": [
          "HubSpot"
        ],
        "summary": "Change channelId, kinds or minAmount, or turn it off and on with disabled.",
        "description": "Change `channelId`, `kinds` or `minAmount`, or turn it off and on with `disabled`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"disabled\": true }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWHubspotAlertsById",
        "tags": [
          "HubSpot"
        ],
        "summary": "Delete it.",
        "description": "Delete it. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/hubspot/alerts/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWHubspotAlertsByIdTest",
        "tags": [
          "HubSpot"
        ],
        "summary": "Post a sample alert into its channel.",
        "description": "Post a sample alert into its channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/hooks/crm/hubspot": {
      "post": {
        "operationId": "postHooksCrmHubspot",
        "tags": [
          "HubSpot"
        ],
        "summary": "Where HubSpot delivers webhook events for every connected account, signed with X-HubSpot-Signature-v3 and X-HubSpot-Requ",
        "description": "Where HubSpot delivers webhook events for every connected account, signed with `X-HubSpot-Signature-v3` and `X-HubSpot-Request-Timestamp`. Answers 200 to signed events and posts them afterwards, and 401 to a bad or old signature.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/github": {
      "get": {
        "operationId": "getApiWorkspacesByWGithub",
        "tags": [
          "GitHub"
        ],
        "summary": "Whether the server can install GitHub (available), the connection (installationId, account, accountType, repositorySelec",
        "description": "Whether the server can install GitHub (`available`), the `connection` (`installationId`, `account`, `accountType`, `repositorySelection`, `botUserId`, `unfurls`, `brokenAt` when the app was removed or suspended in GitHub) or null, and the `subscriptions`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiWorkspacesByWGithub",
        "tags": [
          "GitHub"
        ],
        "summary": "Turn link previews on or off with unfurls.",
        "description": "Turn link previews on or off with `unfurls`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"unfurls\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWGithub",
        "tags": [
          "GitHub"
        ],
        "summary": "Disconnect: Freesbe forgets the installation and its subscriptions, and the app's command and action go away.",
        "description": "Disconnect: Freesbe forgets the installation and its subscriptions, and the app's command and action go away. The app stays installed in GitHub until someone removes it there. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/github/connect": {
      "post": {
        "operationId": "postApiWorkspacesByWGithubConnect",
        "tags": [
          "GitHub"
        ],
        "summary": "The url of GitHub's page that installs the app.",
        "description": "The `url` of GitHub's page that installs the app. Send the browser there; GitHub sends it back to Freesbe, which checks the installation is one this person can reach and opens the app with `?github=connected`. Only the admin who started it can finish it, within 30 minutes.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/github/repos": {
      "get": {
        "operationId": "getApiWorkspacesByWGithubRepos",
        "tags": [
          "GitHub"
        ],
        "summary": "The repos the installation can see (fullName, private), up to 300.",
        "description": "The `repos` the installation can see (`fullName`, `private`), up to 300.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/github/subscriptions": {
      "post": {
        "operationId": "postApiWorkspacesByWGithubSubscriptions",
        "tags": [
          "GitHub"
        ],
        "summary": "Subscribe a channel to a repository: channelId, repo (owner/repo), and optional features (pulls, reviews, issues, commen",
        "description": "Subscribe a channel to a repository: `channelId`, `repo` (`owner/repo`), and optional `features` (`pulls`, `reviews`, `issues`, `comments`, `commits`, `releases`, `deployments`, `workflows`; pull requests, issues, releases and deployments when left out), `labels` and `branch`. A channel already subscribed to the repository gets the features added. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"channelId\": \"01J…\", \"repo\": \"northwind-traders/storefront\", \"features\": [\"pulls\", \"releases\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/github/subscriptions/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWGithubSubscriptionsById",
        "tags": [
          "GitHub"
        ],
        "summary": "Change channelId, features, labels or branch, or turn it off and on with disabled.",
        "description": "Change `channelId`, `features`, `labels` or `branch`, or turn it off and on with `disabled`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"labels\": [\"bug\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWGithubSubscriptionsById",
        "tags": [
          "GitHub"
        ],
        "summary": "Delete it.",
        "description": "Delete it. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/github/subscriptions/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWGithubSubscriptionsByIdTest",
        "tags": [
          "GitHub"
        ],
        "summary": "Post a sample pull request card into its channel.",
        "description": "Post a sample pull request card into its channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/hooks/dev-tools/github": {
      "post": {
        "operationId": "postHooksDevToolsGithub",
        "tags": [
          "GitHub"
        ],
        "summary": "Where GitHub delivers webhook events for every installation, signed with X-Hub-Signature-256.",
        "description": "Where GitHub delivers webhook events for every installation, signed with `X-Hub-Signature-256`. Answers 200 to signed deliveries and posts them afterwards (each `X-GitHub-Delivery` once), and 401 to a bad signature.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/jira": {
      "get": {
        "operationId": "getApiWorkspacesByWJira",
        "tags": [
          "Jira"
        ],
        "summary": "Whether the server can connect Jira (available), the connection (siteUrl, siteName, jiraUser who Freesbe acts as, botUse",
        "description": "Whether the server can connect Jira (`available`), the `connection` (`siteUrl`, `siteName`, `jiraUser` who Freesbe acts as, `botUserId`, `unfurls`, `brokenAt` when Atlassian stopped accepting its access) or null, and the `subscriptions`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiWorkspacesByWJira",
        "tags": [
          "Jira"
        ],
        "summary": "Turn link previews on or off with unfurls.",
        "description": "Turn link previews on or off with `unfurls`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"unfurls\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWJira",
        "tags": [
          "Jira"
        ],
        "summary": "Disconnect: Freesbe removes its webhook from the site and forgets the connection and its subscriptions, and the app's co",
        "description": "Disconnect: Freesbe removes its webhook from the site and forgets the connection and its subscriptions, and the app's command and action go away. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/jira/connect": {
      "post": {
        "operationId": "postApiWorkspacesByWJiraConnect",
        "tags": [
          "Jira"
        ],
        "summary": "The url of Atlassian's page that asks to allow Freesbe.",
        "description": "The `url` of Atlassian's page that asks to allow Freesbe. Send the browser there; Atlassian sends it back to Freesbe, which finishes connecting and opens the app with `?jira=connected`. Only the admin who started it can finish it, within 30 minutes.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/jira/projects": {
      "get": {
        "operationId": "getApiWorkspacesByWJiraProjects",
        "tags": [
          "Jira"
        ],
        "summary": "The projects the connected account can browse (key, name), up to 300.",
        "description": "The `projects` the connected account can browse (`key`, `name`), up to 300.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/jira/subscriptions": {
      "post": {
        "operationId": "postApiWorkspacesByWJiraSubscriptions",
        "tags": [
          "Jira"
        ],
        "summary": "Subscribe a channel to a project: channelId, project (its key), and optional features (created, status, assigned, commen",
        "description": "Subscribe a channel to a project: `channelId`, `project` (its key), and optional `features` (`created`, `status`, `assigned`, `comments`; all but comments when left out) and `labels`. A channel already subscribed to the project gets the features added. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"channelId\": \"01J…\", \"project\": \"OPS\", \"features\": [\"created\", \"comments\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/jira/subscriptions/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWJiraSubscriptionsById",
        "tags": [
          "Jira"
        ],
        "summary": "Change channelId, features or labels, or turn it off and on with disabled.",
        "description": "Change `channelId`, `features` or `labels`, or turn it off and on with `disabled`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"labels\": [\"customer\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWJiraSubscriptionsById",
        "tags": [
          "Jira"
        ],
        "summary": "Delete it.",
        "description": "Delete it. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/jira/subscriptions/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWJiraSubscriptionsByIdTest",
        "tags": [
          "Jira"
        ],
        "summary": "Post a sample issue card into its channel.",
        "description": "Post a sample issue card into its channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/hooks/dev-tools/jira/{token}": {
      "post": {
        "operationId": "postHooksDevToolsJiraByToken",
        "tags": [
          "Jira"
        ],
        "summary": "Where the site's webhook delivers issue and comment events, to the connection's own secret address, which Freesbe regist",
        "description": "Where the site's webhook delivers issue and comment events, to the connection's own secret address, which Freesbe registers with Jira itself. Answers 200 and posts afterwards (each `X-Atlassian-Webhook-Identifier` once), 404 to an unknown address, and 401 to a bad signature.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/gitlab": {
      "get": {
        "operationId": "getApiWorkspacesByWGitlab",
        "tags": [
          "GitLab"
        ],
        "summary": "Whether the server can connect GitLab.com (available), the connection (instanceUrl, selfManaged, gitlabUser who Freesbe ",
        "description": "Whether the server can connect GitLab.com (`available`), the `connection` (`instanceUrl`, `selfManaged`, `gitlabUser` who Freesbe acts as, `botUserId`, `unfurls`, `brokenAt` when GitLab stopped accepting its access) or null, the `subscriptions`, the `callbackUrl` a self-managed server's application needs as its redirect URI, and for a `private` server the `webhook` (`url`, `secret`) its admin adds to each project.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiWorkspacesByWGitlab",
        "tags": [
          "GitLab"
        ],
        "summary": "Turn link previews on or off with unfurls.",
        "description": "Turn link previews on or off with `unfurls`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"unfurls\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWGitlab",
        "tags": [
          "GitLab"
        ],
        "summary": "Disconnect: Freesbe takes its webhooks off the projects and forgets the connection and its subscriptions, and the app's ",
        "description": "Disconnect: Freesbe takes its webhooks off the projects and forgets the connection and its subscriptions, and the app's command and action go away. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/gitlab/connect": {
      "post": {
        "operationId": "postApiWorkspacesByWGitlabConnect",
        "tags": [
          "GitLab"
        ],
        "summary": "The url of GitLab's page that asks to allow Freesbe.",
        "description": "The `url` of GitLab's page that asks to allow Freesbe. Leave the body empty for GitLab.com; for a self-managed server send its https `instanceUrl` and the `clientId` and `clientSecret` of the application made on it. For a private server Freesbe can't reach, send `instanceUrl` and `private: true`: it connects straight away and `url` is null. Otherwise send the browser there; GitLab sends it back to Freesbe, which finishes connecting and opens the app with `?gitlab=connected`. Only the admin who started it can finish it, within 30 minutes.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"instanceUrl\": \"https://gitlab.northwind.example\", \"clientId\": \"…\", \"clientSecret\": \"…\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/gitlab/projects": {
      "get": {
        "operationId": "getApiWorkspacesByWGitlabProjects",
        "tags": [
          "GitLab"
        ],
        "summary": "The projects the connected account is a member of (path, name, private), most active first, up to 300.",
        "description": "The `projects` the connected account is a member of (`path`, `name`, `private`), most active first, up to 300.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/gitlab/subscriptions": {
      "post": {
        "operationId": "postApiWorkspacesByWGitlabSubscriptions",
        "tags": [
          "GitLab"
        ],
        "summary": "Subscribe a channel to a project: channelId, project (its path), and optional features (merge_requests, issues, comments",
        "description": "Subscribe a channel to a project: `channelId`, `project` (its path), and optional `features` (`merge_requests`, `issues`, `comments`, `pushes`, `tags`, `releases`, `deployments`, `pipelines`; merge requests, issues, releases and deployments when left out), `labels` and `branch`. Freesbe adds its webhook to the project; `hookError` says why when GitLab refused (usually a missing Maintainer role). A channel already subscribed to the project gets the features added. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"channelId\": \"01J…\", \"project\": \"northwind/storefront\", \"features\": [\"merge_requests\", \"pipelines\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/gitlab/subscriptions/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWGitlabSubscriptionsById",
        "tags": [
          "GitLab"
        ],
        "summary": "Change channelId, features, labels or branch, or turn it off and on with disabled.",
        "description": "Change `channelId`, `features`, `labels` or `branch`, or turn it off and on with `disabled`. Turning it on tries the project's webhook again.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"labels\": [\"bug\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWGitlabSubscriptionsById",
        "tags": [
          "GitLab"
        ],
        "summary": "Delete it.",
        "description": "Delete it. The project's webhook goes when no channel follows the project any more. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/gitlab/subscriptions/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWGitlabSubscriptionsByIdTest",
        "tags": [
          "GitLab"
        ],
        "summary": "Post a sample merge request card into its channel.",
        "description": "Post a sample merge request card into its channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/hooks/dev-tools/gitlab/{token}": {
      "post": {
        "operationId": "postHooksDevToolsGitlabByToken",
        "tags": [
          "GitLab"
        ],
        "summary": "Where the projects' webhooks deliver, to the connection's own secret address, with its secret in X-Gitlab-Token.",
        "description": "Where the projects' webhooks deliver, to the connection's own secret address, with its secret in `X-Gitlab-Token`. Answers 200 and posts afterwards (each `X-Gitlab-Event-UUID` once), 404 to an unknown address, and 401 to a wrong token.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/monday": {
      "get": {
        "operationId": "getApiWorkspacesByWMonday",
        "tags": [
          "monday.com"
        ],
        "summary": "Whether the server can connect monday.com (available), the connection (accountUrl, accountName, mondayUser who Freesbe a",
        "description": "Whether the server can connect monday.com (`available`), the `connection` (`accountUrl`, `accountName`, `mondayUser` who Freesbe acts as, `botUserId`, `unfurls`, `brokenAt` when monday.com stopped accepting its access) or null, and the `subscriptions`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiWorkspacesByWMonday",
        "tags": [
          "monday.com"
        ],
        "summary": "Turn link previews on or off with unfurls.",
        "description": "Turn link previews on or off with `unfurls`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"unfurls\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWMonday",
        "tags": [
          "monday.com"
        ],
        "summary": "Disconnect: Freesbe takes its webhooks off the boards and forgets the connection and its subscriptions, and the app's co",
        "description": "Disconnect: Freesbe takes its webhooks off the boards and forgets the connection and its subscriptions, and the app's command and action go away. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/monday/connect": {
      "post": {
        "operationId": "postApiWorkspacesByWMondayConnect",
        "tags": [
          "monday.com"
        ],
        "summary": "The url of monday.com's page that asks to allow Freesbe.",
        "description": "The `url` of monday.com's page that asks to allow Freesbe. Send the browser there; monday.com sends it back to Freesbe, which finishes connecting and opens the app with `?monday=connected`. Only the admin who started it can finish it, within 30 minutes.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/monday/boards": {
      "get": {
        "operationId": "getApiWorkspacesByWMondayBoards",
        "tags": [
          "monday.com"
        ],
        "summary": "The boards the connected account can open (id, name), by name, up to 500.",
        "description": "The `boards` the connected account can open (`id`, `name`), by name, up to 500. Subitem boards and docs are left out.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/monday/subscriptions": {
      "post": {
        "operationId": "postApiWorkspacesByWMondaySubscriptions",
        "tags": [
          "monday.com"
        ],
        "summary": "Subscribe a channel to a board: channelId, boardId, and optional features (created, status, assigned, updates; the first",
        "description": "Subscribe a channel to a board: `channelId`, `boardId`, and optional `features` (`created`, `status`, `assigned`, `updates`; the first three when left out) and `statuses` (only status changes to these post). Freesbe adds its webhooks to the board. A channel already subscribed to the board gets the features added. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"channelId\": \"01J…\", \"boardId\": \"1001\", \"features\": [\"created\", \"status\"], \"statuses\": [\"Stuck\", \"Done\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/monday/subscriptions/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWMondaySubscriptionsById",
        "tags": [
          "monday.com"
        ],
        "summary": "Change channelId, features or statuses, or turn it off and on with disabled.",
        "description": "Change `channelId`, `features` or `statuses`, or turn it off and on with `disabled`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"statuses\": [] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWMondaySubscriptionsById",
        "tags": [
          "monday.com"
        ],
        "summary": "Delete it.",
        "description": "Delete it. The board's webhooks go when no channel follows the board any more. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/monday/subscriptions/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWMondaySubscriptionsByIdTest",
        "tags": [
          "monday.com"
        ],
        "summary": "Post a sample item card into its channel.",
        "description": "Post a sample item card into its channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/hooks/projects/monday/{token}": {
      "post": {
        "operationId": "postHooksProjectsMondayByToken",
        "tags": [
          "monday.com"
        ],
        "summary": "Where the boards' webhooks deliver new items, column changes and updates, to the connection's own secret address, which ",
        "description": "Where the boards' webhooks deliver new items, column changes and updates, to the connection's own secret address, which Freesbe gives monday.com itself. Answers monday.com's `challenge` when a webhook is made, otherwise 200 and posts afterwards (each trigger once), 404 to an unknown address, and 401 to a bad signature.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/salesforce": {
      "get": {
        "operationId": "getApiWorkspacesByWSalesforce",
        "tags": [
          "Salesforce"
        ],
        "summary": "Whether the server can connect Salesforce (available), whether the workspace's plan includes it (included), the connecti",
        "description": "Whether the server can connect Salesforce (`available`), whether the workspace's `plan` includes it (`included`), the `connection` (`orgId`, `orgName`, `instanceUrl`, `sandbox`, `botUserId`, `unfurls`, `brokenAt` when Salesforce stopped accepting it) or null, and the `alerts`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiWorkspacesByWSalesforce",
        "tags": [
          "Salesforce"
        ],
        "summary": "Turn link previews on or off with unfurls.",
        "description": "Turn link previews on or off with `unfurls`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"unfurls\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWSalesforce",
        "tags": [
          "Salesforce"
        ],
        "summary": "Disconnect: Freesbe forgets Salesforce's access and the app's command and action go away.",
        "description": "Disconnect: Freesbe forgets Salesforce's access and the app's command and action go away. Alerts are kept for a reconnect. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/salesforce/connect": {
      "post": {
        "operationId": "postApiWorkspacesByWSalesforceConnect",
        "tags": [
          "Salesforce"
        ],
        "summary": "The url of Salesforce's page that asks to allow Freesbe, at test.salesforce.com with sandbox: true.",
        "description": "The `url` of Salesforce's page that asks to allow Freesbe, at test.salesforce.com with `sandbox: true`. Send the browser there; Salesforce sends it back to Freesbe, which finishes connecting and opens the app with `?salesforce=connected`. Only the admin who started it can finish it, within 15 minutes. 403 when the plan doesn't include Salesforce.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"sandbox\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/salesforce/alerts": {
      "post": {
        "operationId": "postApiWorkspacesByWSalesforceAlerts",
        "tags": [
          "Salesforce"
        ],
        "summary": "Add an alert: channelId, kinds (opportunity_created, opportunity_stage, opportunity_won, opportunity_lost, lead_created,",
        "description": "Add an alert: `channelId`, `kinds` (`opportunity_created`, `opportunity_stage`, `opportunity_won`, `opportunity_lost`, `lead_created`, `case_created`) and an optional `minAmount` for opportunities. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"channelId\": \"01J…\", \"kinds\": [\"opportunity_created\", \"opportunity_won\"], \"minAmount\": 10000 }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/salesforce/alerts/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWSalesforceAlertsById",
        "tags": [
          "Salesforce"
        ],
        "summary": "Change channelId, kinds or minAmount, or turn it off and on with disabled.",
        "description": "Change `channelId`, `kinds` or `minAmount`, or turn it off and on with `disabled`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"disabled\": true }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWSalesforceAlertsById",
        "tags": [
          "Salesforce"
        ],
        "summary": "Delete it.",
        "description": "Delete it. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/salesforce/alerts/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWSalesforceAlertsByIdTest",
        "tags": [
          "Salesforce"
        ],
        "summary": "Post a sample alert into its channel.",
        "description": "Post a sample alert into its channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/order-lookup": {
      "get": {
        "operationId": "getApiWorkspacesByWOrderLookup",
        "tags": [
          "Customer orders"
        ],
        "summary": "The store customers are looked up in, or lookup: null: store, storeUrl and the store's lastError, if it refused the last",
        "description": "The store customers are looked up in, or `lookup: null`: `store`, `storeUrl` and the store's `lastError`, if it refused the last lookup. The API key never comes back.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWOrderLookup",
        "tags": [
          "Customer orders"
        ],
        "summary": "Set up the store, or replace its key: store (woocommerce), storeUrl (https), and a REST API key with Read permission as ",
        "description": "Set up the store, or replace its key: `store` (`woocommerce`), `storeUrl` (https), and a REST API key with Read permission as `consumerKey` and `consumerSecret`. Freesbe checks the key with the store first and answers 400 with the store's reason when it doesn't work.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"store\": \"woocommerce\", \"storeUrl\": \"https://shop.example\", \"consumerKey\": \"ck_…\", \"consumerSecret\": \"cs_…\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWOrderLookup",
        "tags": [
          "Customer orders"
        ],
        "summary": "Stop looking customers up and forget the key.",
        "description": "Stop looking customers up and forget the key. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/order-lookup/test": {
      "post": {
        "operationId": "postApiWorkspacesByWOrderLookupTest",
        "tags": [
          "Customer orders"
        ],
        "summary": "Look someone up by email or phone, to see what the team would see.",
        "description": "Look someone up by `email` or `phone`, to see what the team would see.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"email\": \"customer@example.com\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/inbox/conversations/{id}/orders": {
      "get": {
        "operationId": "getApiInboxConversationsByIdOrders",
        "tags": [
          "Customer orders"
        ],
        "summary": "The customer's orders, found by the email or phone number of the conversation's customer: store, customer (orderCount, t",
        "description": "The customer's orders, found by the email or phone number of the conversation's customer: `store`, `customer` (`orderCount`, `totalSpent`, `currency`, `since`) and up to five `orders`, newest first, each with `name`, `status`, `total`, `items`, `tracking` and `url`. For people who can see the conversation's channel. Answers 502 when the store doesn't answer.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/caller-orders": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneCallerOrders",
        "tags": [
          "Customer orders"
        ],
        "summary": "The same, for a caller, found by their phone number.",
        "description": "The same, for a caller, found by their phone number.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "number",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/sources": {
      "get": {
        "operationId": "getApiWorkspacesByWInboxSources",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Where customers write in from: each source's id, kind (webchat, email, sms, whatsapp or telegram), name, channelId, enab",
        "description": "Where customers write in from: each source's `id`, `kind` (`webchat`, `email`, `sms`, `whatsapp` or `telegram`), `name`, `channelId`, `enabled`, `testMode`, for a web chat its `webchat` settings with the public `key`, the `snippet` to paste on the site and a `pageUrl` with the chat on its own, for an email inbox its `email` settings with the `address` to forward to, for SMS its `sms.number`, and for WhatsApp its `whatsapp` settings: the `number`, whether it's `connected` to a WhatsApp Business account, and that account's `verifiedName`, and for Telegram its `telegram` settings: the `name` and `username` customers see, the `link` (https://t.me/…) to message it, and whether customer `chats` come in. `available` lists the kinds this server can add now, and `live` the kinds that can leave test mode (`sms` once texting customers is on, `whatsapp` once WhatsApp is set up on the server). `whatsappIncluded` and `telegramIncluded` say whether the workspace's plan includes WhatsApp and Telegram (Business and up), and `chatBrandingIncluded` whether a web chat can hide “Chat by Freesbe” (Corporate and up).\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWInboxSources",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Add a web chat, an email inbox, an SMS inbox or a WhatsApp inbox: a kind, a name, the channelId new conversations go to ",
        "description": "Add a web chat, an email inbox, an SMS inbox or a WhatsApp inbox: a `kind`, a `name`, the `channelId` new conversations go to (not a DM), and optional settings. A web chat takes `webchat`: `title`, `greeting`, `color` (#rrggbb), `askEmail`, `questions` (up to 6, asked before the chat: each `{ id, kind, label, required, choices }`, `kind` one of `text`, `long_text`, `phone` or `choice`, and a `choice` needs at least two `choices`), `logo` (`workspace`, `custom` or `none`), `hours` (`{ mode, own }`: `mode` is `always`, `workspace` for the phone system's business hours, or `own` for the chat's `own` week `{ timezone, days: [{ day, open, close }] }`, `day` 0 for Sunday and times `HH:MM`), `showAvailable` (show who's online, and be away when nobody is), `busyReply` and `noAgentReply` (automatic replies `{ enabled, afterMin, text }`, the second after the first, 1 to 120 minutes after the customer's first unanswered message), `awayMessage`, `hideBranding` (leave out “Chat by Freesbe”, on plans that include it: 403 `forbidden` otherwise), `popup` (open by itself once a visit: `{ enabled, afterPages, afterSeconds }`, 1 to 20 pages and 0 to 300 seconds), `chime` (`none`, `pop`, `ding`, `bell` or `bubble`, played when it opens by itself and for replies while it's closed), `rememberDays` (how long a returning visitor sees their conversation, counted from their last message: `0` for this visit only, `1`, `7`, `30` (the default) or `90`; after that their token answers 401), `animation` (`none`, `bounce`, `wiggle` or `pulse`: the button moves twice a few seconds in), `teaser` (`{ enabled, text, afterSeconds }`, a line beside the button once a visit, up to 120 characters and 0 to 300 seconds; left out while `popup` is on), `launcher` (`{ side, bottom, style, label, hideOnPhones, hideOn }`: `side` `left` or `right`, `bottom` 0 to 200 pixels, `style` `icon` or `label` with `label` as its words, and `hideOn` up to 20 pieces of addresses where the chat stays off), `language` (`auto` for the visitor's browser, or one of the app's languages, like `he`: the chat's own words), `callLinkId` (one of the workspace's Call us links, opened by a phone in the chat's header while it takes calls, or null; 400 `invalid` for another workspace's link), `collectDetails` (visitor details for the team, on by default; off keeps only the visitor's country), and `sites`, the websites that may show it (any when empty). An email inbox takes `email`: `replyTo`, the team's own address replies ask customers to answer, and `fromName`, the name replies come from. An SMS inbox takes `sms`: the `number` customers text, with its country code; it starts in test mode. A WhatsApp inbox takes `whatsapp`: the WhatsApp Business `number`, with its country code; it starts in test mode too, and needs a plan that includes WhatsApp (403 `forbidden` otherwise). Telegram takes `telegram.token`, the key Telegram gave the business's bot: Freesbe checks it with Telegram and starts taking the bot's messages, or answers 400 and keeps nothing. One Telegram per workspace, on a plan that includes it. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"kind\": \"webchat\", \"name\": \"Main website\", \"channelId\": \"01J…\", \"webchat\": { \"color\": \"#e8590c\", \"sites\": [\"www.northwind.example\"] } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/sources/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWInboxSourcesById",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Change its name, channelId, webchat, email, sms or whatsapp settings, or turn it off and on with enabled.",
        "description": "Change its `name`, `channelId`, `webchat`, `email`, `sms` or `whatsapp` settings, or turn it off and on with `enabled`. A web chat that's off disappears from the site; an email inbox that's off bounces mail. For SMS, `testMode: false` takes it live, texting customers for real (only when `live` lists `sms`, and only on one of the workspace's own phone numbers); `testMode: true` takes it back. For WhatsApp, `testMode: false` needs the inbox connected first ([connect WhatsApp](#ref-inbox)), and a connected inbox keeps its number. For Telegram, `telegram.chats: false` stops customers' messages coming in (shared channels keep posting). `telegram.callLinkId` picks the [Call us link](/docs/phone/#call-us-links) customers get when they send /call (null for none). Deleting a Telegram inbox disconnects the bot. Messenger and Instagram inboxes aren't added here: [connect them with Facebook](#ref-inbox); deleting one disconnects it, and Freesbe stops listening to the Page once neither is left.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"enabled\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWInboxSourcesById",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Delete it, with its conversations.",
        "description": "Delete it, with its conversations. Their threads stay in the channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/sources/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWInboxSourcesByIdTest",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Only for an inbox in test mode: a made-up customer's text, from the number in from (a made-up one when left out), with u",
        "description": "Only for an inbox in test mode: a made-up customer's `text`, from the number in `from` (a made-up one when left out), with up to 10 of your uploaded `fileIds` as photos or files they sent. It lands like a real one, and replies to it are kept with `test: true` instead of being sent. Answers the conversation and its deliveries.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"text\": \"Are you open on Saturday?\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/sources/{id}/telegram/shares": {
      "get": {
        "operationId": "getApiWorkspacesByWInboxSourcesByIdTelegramShares",
        "tags": [
          "Customer inbox"
        ],
        "summary": "A Telegram inbox's shared channels and where they can go: shares, each with its id, the Freesbe channelId, the Telegram ",
        "description": "A Telegram inbox's shared channels and where they can go: `shares`, each with its `id`, the Freesbe `channelId`, the Telegram `chat` it posts to, `twoWay` (a group's messages come back into the channel) and `enabled`; and `chats`, the Telegram channels and groups the bot was added to, each with its `id`, `title`, `kind` (`channel` or `group`), `members` and `canPost` (an admin who can post, for a channel).\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"shares\": [ { \"id\": \"01J…\", \"channelId\": \"01J…\", \"chat\": { \"id\": \"-1001…\", \"title\": \"Northwind Traders News\", \"kind\": \"channel\", \"members\": 4210, \"canPost\": true }, \"twoWay\": false, \"enabled\": true, … } ], \"chats\": [ … ] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWInboxSourcesByIdTelegramShares",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Shares a channel on Telegram: the channelId and the chatId of one of chats the bot can post in.",
        "description": "Shares a channel on Telegram: the `channelId` and the `chatId` of one of `chats` the bot can post in. Posts by people in the channel then go out from the bot, and edits and deletes follow. `twoWay` (groups only) brings what people write in the group into the channel, and thread replies go both ways. Up to 50 per workspace. Answers 201 with the share.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"channelId\": \"01J…\", \"chatId\": \"-1001…\", \"twoWay\": true }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/sources/{id}/telegram/shares/{share}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWInboxSourcesByIdTelegramSharesByShare",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Pauses or resumes a share with enabled, or changes twoWay.",
        "description": "Pauses or resumes a share with `enabled`, or changes `twoWay`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"enabled\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "share",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWInboxSourcesByIdTelegramSharesByShare",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Stops sharing the channel.",
        "description": "Stops sharing the channel. What's already on Telegram stays. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "share",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/sources/{id}/whatsapp/connect": {
      "post": {
        "operationId": "postApiWorkspacesByWInboxSourcesByIdWhatsappConnect",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Starts connecting a WhatsApp inbox to the business's WhatsApp Business account: answers the url of Meta's sign-up to sen",
        "description": "Starts connecting a WhatsApp inbox to the business's WhatsApp Business account: answers the `url` of Meta's sign-up to send the admin to. Meta sends them back to Freesbe, which finds the inbox's number in the account they picked and takes the inbox live. Only when `live` lists `whatsapp`; the link works for 15 minutes, for the admin who started it.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/meta/connect": {
      "post": {
        "operationId": "postApiWorkspacesByWInboxMetaConnect",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Starts connecting the business's Facebook Page for Messenger, Instagram or both: the channelId new conversations go to (",
        "description": "Starts connecting the business's Facebook Page for Messenger, Instagram or both: the `channelId` new conversations go to (not a DM) and `kinds`, `messenger`, `instagram` or both. Answers the `url` of Facebook's window to send the admin to. Facebook sends them back to Freesbe, which makes a Messenger inbox for the Page and an Instagram inbox for the Instagram professional account linked to it (or connects the workspace's existing ones again), and they take messages straight away. When the admin manages more than one Page, they come back with `meta=pick&meta-pick=<id>` in the address: [pick the Page](#ref-inbox) with it. Only when `available` lists `messenger`, on a plan that includes Messenger and Instagram (403 `forbidden` otherwise). The link works for an hour, for the admin who started it. One Page feeds one workspace.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"channelId\": \"01J…\", \"kinds\": [\"messenger\", \"instagram\"] }\n```\n\nExample answer:\n\n```json\n{ \"url\": \"https://www.facebook.com/v21.0/dialog/oauth?…\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/meta/picks/{id}": {
      "get": {
        "operationId": "getApiWorkspacesByWInboxMetaPicksById",
        "tags": [
          "Customer inbox"
        ],
        "summary": "The Facebook Pages the admin can connect after Facebook's window, for an hour and only for that admin: each Page's id, n",
        "description": "The Facebook Pages the admin can connect after Facebook's window, for an hour and only for that admin: each Page's `id`, `name` and linked `instagram` account (its `username`, or null), and the `kinds` they asked for.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"pages\": [ { \"id\": \"1029…\", \"name\": \"Northwind Traders\", \"instagram\": { \"username\": \"northwindtraders\" } } ], \"kinds\": [\"messenger\", \"instagram\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWInboxMetaPicksById",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Connects the Page with pageId, one of the pick's pages.",
        "description": "Connects the Page with `pageId`, one of the pick's `pages`. 400 when it has no Instagram account and Instagram was asked for, or when it's already connected to another workspace. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"pageId\": \"1029…\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/sources/{id}/whatsapp/templates": {
      "get": {
        "operationId": "getApiWorkspacesByWInboxSourcesByIdWhatsappTemplates",
        "tags": [
          "Customer inbox"
        ],
        "summary": "A WhatsApp inbox's message templates, from its WhatsApp Business account, approved ones first: each one's id, name, lang",
        "description": "A WhatsApp inbox's message templates, from its WhatsApp Business account, approved ones first: each one's `id`, `name`, `language`, `category` (`UTILITY`, `MARKETING` or `AUTHENTICATION`), `status` (`approved`, `pending`, `rejected`, `paused` or `disabled`), `header`, `body` with blanks `{{1}}`, `{{2}}`…, `footer`, how many `params` it takes, whether Freesbe can fill it (`supported`: not with a picture header, header blanks or a link button that changes) and Meta's `rejectedReason`. Until the inbox is connected, `sample` is true and three made-up templates stand in. `manageUrl` opens the account's templates in WhatsApp Manager.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"templates\": [ { \"id\": \"1234…\", \"name\": \"order_update\", \"language\": \"en_US\", \"category\": \"UTILITY\", \"status\": \"approved\", \"body\": \"Hi {{1}}, your order {{2}} is on its way.\", \"params\": 2, \"supported\": true, … } ], \"sample\": false, \"manageUrl\": \"https://business.facebook.com/wa/manage/message-templates/?waba_id=…\" }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWInboxSourcesByIdWhatsappTemplates",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Sends a new template to Meta for review: a lowercase name with underscores, a language code like en_US, a category (UTIL",
        "description": "Sends a new template to Meta for review: a lowercase `name` with underscores, a `language` code like `en_US`, a `category` (`UTILITY` or `MARKETING`), the `body` with blanks `{{1}}`, `{{2}}`… numbered in order, an example for each blank in `examples`, and an optional `footer`. The inbox has to be connected. Answers 201 with the template, `pending` until Meta approves it.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"name\": \"restock_alert\", \"language\": \"en_US\", \"category\": \"UTILITY\", \"body\": \"Hi {{1}}, {{2}} is back in stock. Reply to order.\", \"examples\": [\"Dana\", \"Darjeeling First Flush\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/sources/{id}/whatsapp/start": {
      "post": {
        "operationId": "postApiWorkspacesByWInboxSourcesByIdWhatsappStart",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Write to a customer first, with an approved template (name, language and the params that fill its blanks), to their What",
        "description": "Write to a customer first, with an approved `template` (`name`, `language` and the `params` that fill its blanks), to their WhatsApp number `to` with its country code, and an optional `name`. It goes into their open conversation from this inbox, or starts a thread in the inbox's channel, and shows there as your message. You have to be able to post in that channel. Answers 201 with the conversation and its deliveries; in test mode it's kept with `test: true`.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"to\": \"+44 7700 900123\", \"name\": \"Oliver Grant\", \"template\": { \"name\": \"order_update\", \"language\": \"en_US\", \"params\": [\"Oliver\", \"NW-48240\"] } }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/sources/{id}/logo": {
      "put": {
        "operationId": "putApiWorkspacesByWInboxSourcesByIdLogo",
        "tags": [
          "Customer inbox"
        ],
        "summary": "A web chat's own logo: the picture is the body (PNG, JPEG, GIF or WebP, with its Content-Type).",
        "description": "A web chat's own logo: the picture is the body (PNG, JPEG, GIF or WebP, with its `Content-Type`). Sets `webchat.logo` to `custom` and returns the `source`, with the picture at `webchat.customLogoUrl`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWInboxSourcesByIdLogo",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Remove a web chat's own logo.",
        "description": "Remove a web chat's own logo. A chat that showed it goes back to the workspace logo. Returns the `source`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox": {
      "get": {
        "operationId": "getApiWorkspacesByWInbox",
        "tags": [
          "Customer inbox"
        ],
        "summary": "The sources you can see, a page of conversations (newest change first) and the counts of open ones: all, yours and nobod",
        "description": "The `sources` you can see, a page of `conversations` (newest change first) and the `counts` of open ones: all, yours and nobody's. Pick a list with `?view=open|mine|unassigned|closed`, one source with `?source=`, one person's with `?assignee=<userId>`, and page with `?before=<updatedAt>`. `?sort=newest|oldest|waiting` orders by when conversations were opened, or puts the customers who have waited longest for a reply first; those pages with `?offset=` instead of `before`. When the person on an open conversation leaves the workspace or its channel, it goes back to nobody and `previousAssigneeId` says who had it, until someone takes it.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"sources\": [ … ], \"conversations\": [ { \"id\": \"01J…\", \"status\": \"open\", \"assigneeId\": null, \"contact\": { \"name\": \"Jordan Fields\", \"email\": \"jordan@contoso.example\" }, \"rootMessageId\": \"01J…\", … } ], \"hasMore\": false, \"counts\": { \"open\": 3, \"mine\": 1, \"unassigned\": 2 } }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/inbox/conversations/{id}": {
      "get": {
        "operationId": "getApiInboxConversationsById",
        "tags": [
          "Customer inbox"
        ],
        "summary": "One conversation, and the deliveries of the replies that went to the customer (messageId, status, error).",
        "description": "One conversation, and the `deliveries` of the replies that went to the customer (`messageId`, `status`, `error`). Thread replies without one were notes. For a web chat, `visitor` has the visitor details: `country` (two letters, null when unknown), `city`, `region`, `timeZone`, the `page` they're on and this visit's `pages` (`{ url, title, at }`, the last 20, addresses without query strings), `referrer`, `campaign` tags (`source`, `medium`, `campaign`, `term`, `content`), `earlierChats`, `browser`, `os`, `device` (`computer`, `phone` or `tablet`), `language`, `screen`, `ip`, and `limited` when the chat keeps only the country. Null for other channels. A web chat conversation's `visitor` in lists and on its card has `country`, `city`, `timeZone` and `page`.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiInboxConversationsById",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Close or reopen it with status, or give it to someone in its channel with assigneeId (null: nobody).",
        "description": "Close or reopen it with `status`, or give it to someone in its channel with `assigneeId` (null: nobody). The inbox bot says so in the thread and mentions the new owner.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"assigneeId\": \"01JB8R…\" }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/inbox/conversations/{id}/suggest": {
      "post": {
        "operationId": "postApiInboxConversationsByIdSuggest",
        "tags": [
          "Customer inbox"
        ],
        "summary": "An answer to the customer the AI drafts from the conversation, its notes and the saved replies, as text.",
        "description": "An answer to the customer the AI drafts from the conversation, its notes and the saved replies, as `text`. Nothing is sent. Counts toward the workspace's AI allowance.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/inbox/conversations/{id}/agent": {
      "post": {
        "operationId": "postApiInboxConversationsByIdAgent",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Where the [AI agent](/docs/customer-inbox/#ai-agent) answers in the conversation's inbox: action: \"pause\" stops it answe",
        "description": "Where the [AI agent](/docs/customer-inbox/#ai-agent) answers in the conversation's inbox: `action: \"pause\"` stops it answering there, and `action: \"resume\"` lets it answer again (it answers the customer's last message if nobody has). A conversation's `ai` says how it stands: `state` (`answering`, `handed_off` or `paused`) and the agent's `name`; null where the agent doesn't answer. Answers the conversation and its deliveries.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"action\": \"resume\" }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/inbox/conversations/{id}/block": {
      "post": {
        "operationId": "postApiInboxConversationsByIdBlock",
        "tags": [
          "Customer inbox"
        ],
        "summary": "[Blocks](/docs/customer-inbox/#block-a-visitor) a web chat conversation's visitor from all the workspace's web chats, an",
        "description": "[Blocks](/docs/customer-inbox/#block-a-visitor) a web chat conversation's visitor from all the workspace's web chats, and with `ip: true` their IP address too for `days` (1, 7 or 30; null until someone unblocks it). Closes the conversation and notes it in the thread. 400 for other kinds of conversation. Answers the conversation and its deliveries.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"ip\": true, \"days\": 30 }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/blocks": {
      "get": {
        "operationId": "getApiWorkspacesByWInboxBlocks",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Who's blocked from the workspace's web chats: visitors (id, contactId, name, email, conversationId, ip as { shown, expir",
        "description": "Who's blocked from the workspace's web chats: `visitors` (`id`, `contactId`, `name`, `email`, `conversationId`, `ip` as `{ shown, expiresAt }` or null when only the visitor is blocked, `blockedBy` and `createdAt`), the IP addresses and `ranges` admins blocked (`id`, `cidr`, `blockedBy`, `createdAt`, `expiresAt`), and the blocked `countries` (two-letter codes, `XX` for an unknown location such as a VPN or Tor).\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"visitors\": [{ \"id\": \"01J…\", \"contactId\": \"01J…\", \"name\": \"Rex\", \"email\": \"rex@spam.example\", \"conversationId\": \"01J…\", \"ip\": { \"shown\": \"192.0.2.61\", \"expiresAt\": 1795000000000 }, \"blockedBy\": \"Sam Chen\", \"createdAt\": 1792400000000 }], \"ranges\": [{ \"id\": \"01J…\", \"cidr\": \"198.51.100.0/24\", \"blockedBy\": \"Maya Patel\", \"createdAt\": 1792100000000, \"expiresAt\": null }], \"countries\": [\"XX\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWInboxBlocks",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Blocks an IP address or range (cidr, IPv4 or IPv6, no wider than a /8 or an IPv6 /16) from the web chats until it's unbl",
        "description": "Blocks an IP address or range (`cidr`, IPv4 or IPv6, no wider than a /8 or an IPv6 /16) from the web chats until it's unblocked. 400 when it isn't one. Answers the list, 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"cidr\": \"203.0.113.0/24\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/blocks/{id}": {
      "delete": {
        "operationId": "deleteApiWorkspacesByWInboxBlocksById",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Unblocks a visitor (and their IP address) or an address or range.",
        "description": "Unblocks a visitor (and their IP address) or an address or range. Answers the list.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/block-countries": {
      "put": {
        "operationId": "putApiWorkspacesByWInboxBlockCountries",
        "tags": [
          "Customer inbox"
        ],
        "summary": "The countries where the web chats don't open, replacing the list: two-letter codes, and XX for an unknown location.",
        "description": "The countries where the web chats don't open, replacing the list: two-letter codes, and `XX` for an unknown location. Answers the list.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"countries\": [\"XX\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/agent": {
      "get": {
        "operationId": "getApiWorkspacesByWInboxAgent",
        "tags": [
          "Customer inbox"
        ],
        "summary": "The [AI agent](/docs/customer-inbox/#ai-agent)'s settings (enabled, name, instructions, model (a model id, or auto), str",
        "description": "The [AI agent](/docs/customer-inbox/#ai-agent)'s `settings` (`enabled`, `name`, `instructions`, `model` (a model `id`, or `auto`), `strongModel`, `when` (`always`, `outside_hours` or `after_wait`), `waitMinutes`, `sourceIds`, `handoffTopics`, `maxAnswers` and `guardrails`: `maskPii`, `safety`, `stayOnTopic`, `neverPromise`), its `knowledge` (web pages, notes, files and canvases: `id`, `kind` (`url`, `text`, `file` or `canvas`), `title`, `url`, `chars`, `status`, `error`, and `cabinetItemId` for a file from Files or `channelId` for a canvas), the `models` to pick from (`id`, `name`, `maker`, `runsIn`, `weight`, `tier`, `available`), the inbox `sources`, whether the workspace has the add-on (`included`), this month's conversations `used` of `limit`, and the latest `events`: hand-offs and what the guardrails stopped (never the customer's words).\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWInboxAgent",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Change any of the settings above.",
        "description": "Change any of the settings above. Turning it on needs the AI agent add-on (400 `invalid` otherwise), and a model whose provider isn't set up on the server can't be picked. Answers like GET.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"enabled\": true, \"sourceIds\": [\"01J…\"], \"when\": \"outside_hours\", \"handoffTopics\": [\"Refunds\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/agent/knowledge": {
      "post": {
        "operationId": "postApiWorkspacesByWInboxAgentKnowledge",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Something for the AI agent to answer from: a page of the website (kind: \"url\" and its public url, which Freesbe reads no",
        "description": "Something for the AI agent to answer from: a page of the website (`kind: \"url\"` and its public `url`, which Freesbe reads now), a note (`kind: \"text\"`, a `title` and the `text`, up to 20,000 characters), a file in Files (`kind: \"cabinet\"` and its `itemId`; it reads the newest version) or a canvas (`kind: \"canvas\"` and its `canvasId`; it reads it again when it's edited, at most every 10 minutes). Only a file or canvas the admin can open. Up to 50 in all. Answers 201 with the agent, like GET.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"kind\": \"url\", \"url\": \"https://northwind.example/shipping\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/agent/knowledge/file": {
      "post": {
        "operationId": "postApiWorkspacesByWInboxAgentKnowledgeFile",
        "tags": [
          "Customer inbox"
        ],
        "summary": "A file for the AI agent to learn from, as the request's body, named by ?name=: PDF, Word (.docx), text, Markdown, HTML o",
        "description": "A file for the AI agent to learn from, as the request's body, named by `?name=`: PDF, Word (.docx), text, Markdown, HTML or CSV, up to 10 MB. It keeps the file's words, not its pictures. Kept in the workspace's region and deleted when it's removed from the agent. Answers 201 with the agent, like GET; a file it couldn't read is listed with its `error`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/agent/canvases": {
      "get": {
        "operationId": "getApiWorkspacesByWInboxAgentCanvases",
        "tags": [
          "Customer inbox"
        ],
        "summary": "The canvases the admin can pick for the AI agent: those of public channels and private channels they're in (id, channelI",
        "description": "The canvases the admin can pick for the AI agent: those of public channels and private channels they're in (`id`, `channelId`, `name`, `isPrivate`, `updatedAt`).\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/agent/knowledge/{id}/refresh": {
      "post": {
        "operationId": "postApiWorkspacesByWInboxAgentKnowledgeByIdRefresh",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Reads a web page, file or canvas in the agent's knowledge again.",
        "description": "Reads a web page, file or canvas in the agent's knowledge again. Answers the agent, like GET.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/agent/knowledge/{id}": {
      "delete": {
        "operationId": "deleteApiWorkspacesByWInboxAgentKnowledgeById",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Removes something from the agent's knowledge.",
        "description": "Removes something from the agent's knowledge. An uploaded file is deleted with it; a file in Files stays there. Answers the agent, like GET.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/agent/try": {
      "post": {
        "operationId": "postApiWorkspacesByWInboxAgentTry",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Ask the AI agent a question as a customer would, with its saved settings.",
        "description": "Ask the AI agent a `question` as a customer would, with its saved settings. Nothing is sent to anyone. Answers its `answer` (null when it would hand off), `handoff`, the `reason`, the `model` that answered, the scoring step's `difficulty` (1 to 3, in automatic mode) and the titles of the `sources` it used.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"question\": \"Do you ship to Canada?\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/inbox/conversations/{id}/whatsapp/template": {
      "post": {
        "operationId": "postApiInboxConversationsByIdWhatsappTemplate",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Sends an approved WhatsApp template into the conversation (its name, language and the params that fill its blanks): how ",
        "description": "Sends an approved WhatsApp template into the conversation (its `name`, `language` and the `params` that fill its blanks): how to reach a customer more than 24 hours after their last message, when WhatsApp doesn't take a free-form reply. It shows in the thread as your message. Answers the conversation and its deliveries.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"name\": \"follow_up\", \"language\": \"en_US\", \"params\": [\"Dana\", \"your order NW-48231\"] }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/replies": {
      "get": {
        "operationId": "getApiWorkspacesByWInboxReplies",
        "tags": [
          "Customer inbox"
        ],
        "summary": "The team's saved replies: id, title, body.",
        "description": "The team's saved replies: `id`, `title`, `body`.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWInboxReplies",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Save a reply with a title and a body.",
        "description": "Save a reply with a `title` and a `body`. Answers 201.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"title\": \"Shipping times\", \"body\": \"We ship across the EU in 3 to 5 days.\" }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/replies/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWInboxRepliesById",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Change its title and body.",
        "description": "Change its `title` and `body`.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWInboxRepliesById",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Delete it: admins, and whoever saved it.",
        "description": "Delete it: admins, and whoever saved it. Answers 204.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/inbox/message-log": {
      "get": {
        "operationId": "getApiWorkspacesByWInboxMessageLog",
        "tags": [
          "Customer inbox"
        ],
        "summary": "Every message to and from customers on the workspace's inboxes for a range of dates (counted in tz, a year at most), new",
        "description": "Every message to and from customers on the workspace's inboxes for a range of dates (counted in `tz`, a year at most), newest first, with how it went. `kind` is `webchat`, `email`, `sms` or `whatsapp`; `direction` is `in` or `out`; `status` is `received`, `sent`, `delivered`, `read` or `failed`; `q` matches the customer's number, address or name. `preview` is the start of the message, or `null` when it's in a private channel the admin isn't in. `limit` is up to 500 a page; `more` says another `page` has older messages.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"messages\": [{ \"id\": \"01J…\", \"at\": 1793536200000, \"kind\": \"sms\", \"sourceName\": \"Support line\", \"direction\": \"out\", \"contact\": { \"name\": \"Dana Ruiz\", \"address\": \"+14155550142\" }, \"authorId\": \"01J…\", \"status\": \"failed\", \"error\": \"Number can't receive texts\", \"test\": false, \"preview\": \"Your order ships tomorrow.\", \"conversationId\": \"01J…\", \"channelId\": \"01J…\", \"messageId\": \"01J…\", \"rootMessageId\": \"01J…\" }], \"more\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tz",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/chat/{key}": {
      "get": {
        "operationId": "getApiChatByKey",
        "tags": [
          "Customer inbox"
        ],
        "summary": "The web chat's title, greeting, color, whether it asks for an email (askEmail), the questions it asks before the chat, a",
        "description": "The web chat's `title`, `greeting`, `color`, whether it asks for an email (`askEmail`), the `questions` it asks before the chat, and the header's `logoUrl` (null for none). Also whether it's `open` now (inside its hours, and with someone online when it shows who is), when it `opensAt` next (null when it doesn't say) in which `timezone`, the first names of who's `available` (null when it doesn't show them), the `awayMessage` shown while it isn't open, and whether it hides “Chat by Freesbe” (`hideBranding`). `blocked` is true when the workspace blocked this visitor's IP address or country, and `checkKey` is the bot check's site key when starting a chat needs one (null when it doesn't). 404 when it's off or gone.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/chat/{key}/start": {
      "post": {
        "operationId": "postApiChatByKeyStart",
        "tags": [
          "Customer inbox"
        ],
        "summary": "A visitor's first message (text, with name and email when the chat asks, and answers to its questions as [{ questionId, ",
        "description": "A visitor's first message (`text`, with `name` and `email` when the chat asks, and `answers` to its questions as `[{ questionId, answer }]`; 400 when a required one is missing or a `choice` answer isn't one of its choices): starts a conversation and returns the visitor's secret as `visitorToken`, to send as `Authorization: Bearer` from then on, and their `messages`. Optional `visit` tells the team about the visit, when the chat collects visitor details: `pages` (`[{ url, title, at }]`, oldest first), `referrer`, `campaign` (`{ source, medium, campaign, term, content }`), `timeZone`, `language` and `screen` (like `1440×900`). Addresses that aren't http(s) are dropped, and query strings are cut. When the chat gave a `checkKey`, `check` is the token from the bot check; 403 `check_failed` when it doesn't pass. 403 `blocked` for a blocked visitor (every visitor call answers that once they're blocked), and 429 past 5 new chats from one IP address in 10 minutes or 100 new chats an hour for the chat. Answers 201.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/chat/{key}/messages": {
      "get": {
        "operationId": "getApiChatByKeyMessages",
        "tags": [
          "Customer inbox"
        ],
        "summary": "With the visitor's token: their side of the latest conversation (from is visitor or team; notes never show) after ?after",
        "description": "With the visitor's token: their side of the latest conversation (`from` is `visitor` or `team`; notes never show) after `?after=<id>`, whether the team `closed` it, and whether the visitor gave an email (`hasEmail`). Automatic replies carry `auto`: `busy` or `no_agent`. With `&typing=1`, `typing` lists the first names of the team members typing a reply right now (never a note), and is left out when nobody is.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      },
      "post": {
        "operationId": "postApiChatByKeyMessages",
        "tags": [
          "Customer inbox"
        ],
        "summary": "With the visitor's token: another message (text, and optionally visit as on start).",
        "description": "With the visitor's token: another message (`text`, and optionally `visit` as on start). After the team closed the conversation, it starts a new one.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/chat/{key}/details": {
      "post": {
        "operationId": "postApiChatByKeyDetails",
        "tags": [
          "Customer inbox"
        ],
        "summary": "With the visitor's token: their email and optional name, when they give them after the chat started (the second automati",
        "description": "With the visitor's token: their `email` and optional `name`, when they give them after the chat started (the second automatic reply asks). Answers 204.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/chat/{key}/visit": {
      "post": {
        "operationId": "postApiChatByKeyVisit",
        "tags": [
          "Customer inbox"
        ],
        "summary": "With the visitor's token: the visit (as on start) when a page with the chat loads while they're chatting, so the team se",
        "description": "With the visitor's token: the `visit` (as on start) when a page with the chat loads while they're chatting, so the team sees the page they're on. New pages are added to the open conversation's. Answers 204.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/chat/{key}/typing": {
      "post": {
        "operationId": "postApiChatByKeyTyping",
        "tags": [
          "Customer inbox"
        ],
        "summary": "With the visitor's token: the visitor is typing.",
        "description": "With the visitor's token: the visitor is typing. The team sees it in the conversation for a few seconds; send it again every 3 seconds or so while they type. Nothing is saved. Answers 204.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/chat/{key}/human": {
      "post": {
        "operationId": "postApiChatByKeyHuman",
        "tags": [
          "Customer inbox"
        ],
        "summary": "With the visitor's token: the visitor asks for a person.",
        "description": "With the visitor's token: the visitor asks for a person. Where the AI agent answers, it hands the conversation to the team. Messages the agent wrote come back with `ai: true`. Answers 204.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/pipedrive": {
      "get": {
        "operationId": "getApiWorkspacesByWPipedrive",
        "tags": [
          "Pipedrive"
        ],
        "summary": "Whether the server can connect Pipedrive (available), the connection (companyId, companyName, companyUrl, botUserId, rec",
        "description": "Whether the server can connect Pipedrive (`available`), the `connection` (`companyId`, `companyName`, `companyUrl`, `botUserId`, `receiving` when Pipedrive sends changes to Freesbe, `unfurls`, `lastEventAt`, `brokenAt` when Pipedrive stopped accepting it) or null, and the `alerts`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiWorkspacesByWPipedrive",
        "tags": [
          "Pipedrive"
        ],
        "summary": "Turn link previews on or off with unfurls.",
        "description": "Turn link previews on or off with `unfurls`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"unfurls\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWPipedrive",
        "tags": [
          "Pipedrive"
        ],
        "summary": "Disconnect: Freesbe removes its webhooks from Pipedrive, forgets Pipedrive's access, and the app's command and action go",
        "description": "Disconnect: Freesbe removes its webhooks from Pipedrive, forgets Pipedrive's access, and the app's command and action go away. Alerts are kept for a reconnect. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/pipedrive/connect": {
      "post": {
        "operationId": "postApiWorkspacesByWPipedriveConnect",
        "tags": [
          "Pipedrive"
        ],
        "summary": "The url of Pipedrive's page that asks to allow Freesbe.",
        "description": "The `url` of Pipedrive's page that asks to allow Freesbe. Send the browser there; Pipedrive sends it back to Freesbe, which finishes connecting and opens the app with `?pipedrive=connected`. Only the admin who started it can finish it, within 15 minutes.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/pipedrive/alerts": {
      "post": {
        "operationId": "postApiWorkspacesByWPipedriveAlerts",
        "tags": [
          "Pipedrive"
        ],
        "summary": "Add an alert: channelId, kinds (deal_created, deal_stage, deal_won, deal_lost, lead_created) and an optional minAmount f",
        "description": "Add an alert: `channelId`, `kinds` (`deal_created`, `deal_stage`, `deal_won`, `deal_lost`, `lead_created`) and an optional `minAmount` for deals. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"channelId\": \"01J…\", \"kinds\": [\"deal_created\", \"deal_won\"], \"minAmount\": 10000 }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/pipedrive/alerts/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWPipedriveAlertsById",
        "tags": [
          "Pipedrive"
        ],
        "summary": "Change channelId, kinds or minAmount, or turn it off and on with disabled.",
        "description": "Change `channelId`, `kinds` or `minAmount`, or turn it off and on with `disabled`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"disabled\": true }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWPipedriveAlertsById",
        "tags": [
          "Pipedrive"
        ],
        "summary": "Delete it.",
        "description": "Delete it. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/pipedrive/alerts/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWPipedriveAlertsByIdTest",
        "tags": [
          "Pipedrive"
        ],
        "summary": "Post a sample alert into its channel.",
        "description": "Post a sample alert into its channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/hooks/crm/pipedrive/{token}": {
      "post": {
        "operationId": "postHooksCrmPipedriveByToken",
        "tags": [
          "Pipedrive"
        ],
        "summary": "Where the webhooks Freesbe adds in Pipedrive deliver deal and lead changes, signed in with HTTP Basic auth and a passwor",
        "description": "Where the webhooks Freesbe adds in Pipedrive deliver deal and lead changes, signed in with HTTP Basic auth and a password only Freesbe knows. Answers 200 to signed-in deliveries, 401 to a wrong password and 404 after a disconnect.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/zoho-crm": {
      "get": {
        "operationId": "getApiWorkspacesByWZohoCrm",
        "tags": [
          "Zoho CRM"
        ],
        "summary": "Whether the server can connect Zoho (available), the connection (orgId, orgName, dataCenter, crmUrl, botUserId, unfurls,",
        "description": "Whether the server can connect Zoho (`available`), the `connection` (`orgId`, `orgName`, `dataCenter`, `crmUrl`, `botUserId`, `unfurls`, `listening` while Zoho CRM sends changes, `brokenAt` when Zoho stopped accepting it) or null, and the `alerts`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiWorkspacesByWZohoCrm",
        "tags": [
          "Zoho CRM"
        ],
        "summary": "Turn link previews on or off with unfurls.",
        "description": "Turn link previews on or off with `unfurls`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"unfurls\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWZohoCrm",
        "tags": [
          "Zoho CRM"
        ],
        "summary": "Disconnect: Zoho CRM stops sending changes, Freesbe's access is revoked in Zoho, and the app's command and action go awa",
        "description": "Disconnect: Zoho CRM stops sending changes, Freesbe's access is revoked in Zoho, and the app's command and action go away. Alerts are kept for a reconnect. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zoho-crm/connect": {
      "post": {
        "operationId": "postApiWorkspacesByWZohoCrmConnect",
        "tags": [
          "Zoho CRM"
        ],
        "summary": "The url of Zoho's page that asks to allow Freesbe.",
        "description": "The `url` of Zoho's page that asks to allow Freesbe. Send the browser there; Zoho sends it to the person's own data center, then back to Freesbe, which finishes connecting and opens the app with `?zoho-crm=connected`. Only the admin who started it can finish it, within 15 minutes.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zoho-crm/alerts": {
      "post": {
        "operationId": "postApiWorkspacesByWZohoCrmAlerts",
        "tags": [
          "Zoho CRM"
        ],
        "summary": "Add an alert: channelId, kinds (deal_created, deal_stage, deal_won, deal_lost, lead_created, contact_created) and an opt",
        "description": "Add an alert: `channelId`, `kinds` (`deal_created`, `deal_stage`, `deal_won`, `deal_lost`, `lead_created`, `contact_created`) and an optional `minAmount` for deals. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"channelId\": \"01J…\", \"kinds\": [\"deal_created\", \"deal_won\"], \"minAmount\": 10000 }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zoho-crm/alerts/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWZohoCrmAlertsById",
        "tags": [
          "Zoho CRM"
        ],
        "summary": "Change channelId, kinds or minAmount, or turn it off and on with disabled.",
        "description": "Change `channelId`, `kinds` or `minAmount`, or turn it off and on with `disabled`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"disabled\": true }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWZohoCrmAlertsById",
        "tags": [
          "Zoho CRM"
        ],
        "summary": "Delete it.",
        "description": "Delete it. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zoho-crm/alerts/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWZohoCrmAlertsByIdTest",
        "tags": [
          "Zoho CRM"
        ],
        "summary": "Post a sample alert into its channel.",
        "description": "Post a sample alert into its channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/hooks/crm/zoho-crm/{token}": {
      "post": {
        "operationId": "postHooksCrmZohoCrmByToken",
        "tags": [
          "Zoho CRM"
        ],
        "summary": "Where Zoho CRM delivers one organization's change notifications.",
        "description": "Where Zoho CRM delivers one organization's change notifications. The body's `token` has to be the one Freesbe gave Zoho with the channel. Answers 200 and posts afterwards, 401 to a wrong token, and 404 after a disconnect.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/zendesk": {
      "get": {
        "operationId": "getApiWorkspacesByWZendesk",
        "tags": [
          "Zendesk"
        ],
        "summary": "The connection (subdomain, auth (oauth or token), email, whether it's receiving ticket events, needsReconnect and lastEv",
        "description": "The `connection` (`subdomain`, `auth` (`oauth` or `token`), `email`, whether it's `receiving` ticket events, `needsReconnect` and `lastEventAt`), or null, its `alerts`, and whether `oauth` sign-in is available.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWZendesk",
        "tags": [
          "Zendesk"
        ],
        "summary": "Disconnect: removes Freesbe's webhook from Zendesk, the alerts and the Zendesk app.",
        "description": "Disconnect: removes Freesbe's webhook from Zendesk, the alerts and the Zendesk app. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zendesk/oauth": {
      "post": {
        "operationId": "postApiWorkspacesByWZendeskOauth",
        "tags": [
          "Zendesk"
        ],
        "summary": "Start signing in with Zendesk for subdomain.",
        "description": "Start signing in with Zendesk for `subdomain`. Answers with the `url` to send the browser to; Zendesk comes back to the app with `?zendesk=connected` or `?zendesk_error=`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"subdomain\": \"northwind\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zendesk/token": {
      "post": {
        "operationId": "postApiWorkspacesByWZendeskToken",
        "tags": [
          "Zendesk"
        ],
        "summary": "Connect with an agent's email and Zendesk apiToken instead.",
        "description": "Connect with an agent's `email` and Zendesk `apiToken` instead. The token is checked with Zendesk and stored encrypted.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"subdomain\": \"northwind\", \"email\": \"agent@northwind.example\", \"apiToken\": \"…\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zendesk/groups": {
      "get": {
        "operationId": "getApiWorkspacesByWZendeskGroups",
        "tags": [
          "Zendesk"
        ],
        "summary": "The Zendesk groups an alert can be limited to, as groups with id and name.",
        "description": "The Zendesk groups an alert can be limited to, as `groups` with `id` and `name`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zendesk/alerts": {
      "post": {
        "operationId": "postApiWorkspacesByWZendeskAlerts",
        "tags": [
          "Zendesk"
        ],
        "summary": "Add a ticket alert: channelId, events (created, status, comment, priority, assignment) and an optional groupId.",
        "description": "Add a ticket alert: `channelId`, `events` (`created`, `status`, `comment`, `priority`, `assignment`) and an optional `groupId`. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"channelId\": \"01J…\", \"events\": [\"created\", \"status\"], \"groupId\": \"7\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zendesk/alerts/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWZendeskAlertsById",
        "tags": [
          "Zendesk"
        ],
        "summary": "Change channelId, events or groupId, or turn it off and on with disabled.",
        "description": "Change `channelId`, `events` or `groupId`, or turn it off and on with `disabled`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWZendeskAlertsById",
        "tags": [
          "Zendesk"
        ],
        "summary": "Delete the alert.",
        "description": "Delete the alert. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zendesk/alerts/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWZendeskAlertsByIdTest",
        "tags": [
          "Zendesk"
        ],
        "summary": "Post a sample ticket into its channel.",
        "description": "Post a sample ticket into its channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/hooks/support/zendesk/{token}": {
      "post": {
        "operationId": "postHooksSupportZendeskByToken",
        "tags": [
          "Zendesk"
        ],
        "summary": "Where Zendesk delivers ticket events, signed with X-Zendesk-Webhook-Signature and X-Zendesk-Webhook-Signature-Timestamp.",
        "description": "Where Zendesk delivers ticket events, signed with `X-Zendesk-Webhook-Signature` and `X-Zendesk-Webhook-Signature-Timestamp`. Freesbe adds this webhook in Zendesk when you connect. Answers 200 to signed events and 401 to a bad or old signature.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/zoho-desk": {
      "get": {
        "operationId": "getApiWorkspacesByWZohoDesk",
        "tags": [
          "Zoho Desk"
        ],
        "summary": "Whether the server can connect Zoho (available), the connection (orgId, orgName, portalName, dataCenter, deskUrl, botUse",
        "description": "Whether the server can connect Zoho (`available`), the `connection` (`orgId`, `orgName`, `portalName`, `dataCenter`, `deskUrl`, `botUserId`, `unfurls`, `listening` once Freesbe's webhook is in Zoho Desk, `lastEventAt`, `brokenAt` when Zoho stopped accepting it) or null, and the `alerts`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiWorkspacesByWZohoDesk",
        "tags": [
          "Zoho Desk"
        ],
        "summary": "Turn link previews on or off with unfurls.",
        "description": "Turn link previews on or off with `unfurls`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"unfurls\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWZohoDesk",
        "tags": [
          "Zoho Desk"
        ],
        "summary": "Disconnect: Freesbe removes its webhook from Zoho Desk, its access is revoked in Zoho, and the app's action goes away.",
        "description": "Disconnect: Freesbe removes its webhook from Zoho Desk, its access is revoked in Zoho, and the app's action goes away. Alerts are kept for a reconnect. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zoho-desk/connect": {
      "post": {
        "operationId": "postApiWorkspacesByWZohoDeskConnect",
        "tags": [
          "Zoho Desk"
        ],
        "summary": "The url of Zoho's page that asks to allow Freesbe.",
        "description": "The `url` of Zoho's page that asks to allow Freesbe. Send the browser there; Zoho sends it to the person's own data center, then back to Freesbe, which finishes connecting and opens the app with `?zoho-desk=connected`. Only the admin who started it can finish it, within 15 minutes.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zoho-desk/departments": {
      "get": {
        "operationId": "getApiWorkspacesByWZohoDeskDepartments",
        "tags": [
          "Zoho Desk"
        ],
        "summary": "The help desk's departments, each with its id and name, for alerts that take one.",
        "description": "The help desk's `departments`, each with its `id` and `name`, for alerts that take one.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zoho-desk/alerts": {
      "post": {
        "operationId": "postApiWorkspacesByWZohoDeskAlerts",
        "tags": [
          "Zoho Desk"
        ],
        "summary": "Add an alert: channelId, kinds (created, status, reply, priority, assignment) and an optional departmentId.",
        "description": "Add an alert: `channelId`, `kinds` (`created`, `status`, `reply`, `priority`, `assignment`) and an optional `departmentId`. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"channelId\": \"01J…\", \"kinds\": [\"created\", \"reply\"], \"departmentId\": \"1234000000006907\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zoho-desk/alerts/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWZohoDeskAlertsById",
        "tags": [
          "Zoho Desk"
        ],
        "summary": "Change channelId, kinds or departmentId (null for every department), or turn it off and on with disabled.",
        "description": "Change `channelId`, `kinds` or `departmentId` (null for every department), or turn it off and on with `disabled`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"disabled\": true }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWZohoDeskAlertsById",
        "tags": [
          "Zoho Desk"
        ],
        "summary": "Delete it.",
        "description": "Delete it. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zoho-desk/alerts/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWZohoDeskAlertsByIdTest",
        "tags": [
          "Zoho Desk"
        ],
        "summary": "Post a sample alert into its channel.",
        "description": "Post a sample alert into its channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/hooks/support/zoho-desk/{token}": {
      "post": {
        "operationId": "postHooksSupportZohoDeskByToken",
        "tags": [
          "Zoho Desk"
        ],
        "summary": "Where Freesbe's webhook in Zoho Desk delivers one help desk's new tickets, ticket changes and customer replies.",
        "description": "Where Freesbe's webhook in Zoho Desk delivers one help desk's new tickets, ticket changes and customer replies. The token is random and only Zoho Desk has it, and every event has to be for the connected help desk. Answers 200 and posts afterwards, 403 to another help desk's events, and 404 after a disconnect.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/zoho-{product}": {
      "get": {
        "operationId": "getApiWorkspacesByWZohoByProduct",
        "tags": [
          "Zoho Books and Zoho Invoice"
        ],
        "summary": "Whether the server can connect Zoho (available), the connection (orgId, orgName, currency, dataCenter, appUrl, botUserId",
        "description": "Whether the server can connect Zoho (`available`), the `connection` (`orgId`, `orgName`, `currency`, `dataCenter`, `appUrl`, `botUserId`, `unfurls`, `checkedAt` when Freesbe last checked, `brokenAt` when Zoho stopped accepting it) or null, and the `alerts`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "product",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiWorkspacesByWZohoByProduct",
        "tags": [
          "Zoho Books and Zoho Invoice"
        ],
        "summary": "Turn link previews on or off with unfurls.",
        "description": "Turn link previews on or off with `unfurls`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"unfurls\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "product",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWZohoByProduct",
        "tags": [
          "Zoho Books and Zoho Invoice"
        ],
        "summary": "Disconnect: Freesbe's access is revoked in Zoho and checking stops.",
        "description": "Disconnect: Freesbe's access is revoked in Zoho and checking stops. Alerts are kept for a reconnect. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "product",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zoho-{product}/connect": {
      "post": {
        "operationId": "postApiWorkspacesByWZohoByProductConnect",
        "tags": [
          "Zoho Books and Zoho Invoice"
        ],
        "summary": "The url of Zoho's page that asks to allow Freesbe.",
        "description": "The `url` of Zoho's page that asks to allow Freesbe. Send the browser there; Zoho sends it to the person's own data center, then back to Freesbe, which finishes connecting and opens the app with `?zoho-books=connected` or `?zoho-invoice=connected`. Only the admin who started it can finish it, within 15 minutes.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "product",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zoho-{product}/alerts": {
      "post": {
        "operationId": "postApiWorkspacesByWZohoByProductAlerts",
        "tags": [
          "Zoho Books and Zoho Invoice"
        ],
        "summary": "Add an alert: channelId, kinds (sent, payment, paid, overdue) and an optional minAmount.",
        "description": "Add an alert: `channelId`, `kinds` (`sent`, `payment`, `paid`, `overdue`) and an optional `minAmount`. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"channelId\": \"01J…\", \"kinds\": [\"payment\", \"overdue\"], \"minAmount\": 500 }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "product",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zoho-{product}/alerts/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWZohoByProductAlertsById",
        "tags": [
          "Zoho Books and Zoho Invoice"
        ],
        "summary": "Change channelId, kinds or minAmount (null for any amount), or turn it off and on with disabled.",
        "description": "Change `channelId`, `kinds` or `minAmount` (null for any amount), or turn it off and on with `disabled`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"disabled\": true }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "product",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWZohoByProductAlertsById",
        "tags": [
          "Zoho Books and Zoho Invoice"
        ],
        "summary": "Delete it.",
        "description": "Delete it. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "product",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zoho-{product}/alerts/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWZohoByProductAlertsByIdTest",
        "tags": [
          "Zoho Books and Zoho Invoice"
        ],
        "summary": "Post a sample alert, of the first kind it takes, into its channel.",
        "description": "Post a sample alert, of the first kind it takes, into its channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "product",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/freshdesk": {
      "get": {
        "operationId": "getApiWorkspacesByWFreshdesk",
        "tags": [
          "Freshdesk"
        ],
        "summary": "The connection (subdomain, the agent's email and agentName, the secret hookUrl Freshdesk's automation rules call, needsR",
        "description": "The `connection` (`subdomain`, the agent's `email` and `agentName`, the secret `hookUrl` Freshdesk's automation rules call, `needsReconnect` and `lastEventAt`), or null, and its `alerts`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWFreshdesk",
        "tags": [
          "Freshdesk"
        ],
        "summary": "Connect, or connect again, with an agent's Freshdesk apiKey.",
        "description": "Connect, or connect again, with an agent's Freshdesk `apiKey`. The key is checked with Freshdesk and stored encrypted; connecting again keeps the `hookUrl`. Answers like GET.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"subdomain\": \"northwind\", \"apiKey\": \"…\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWFreshdesk",
        "tags": [
          "Freshdesk"
        ],
        "summary": "Disconnect: forgets the API key, the alerts and the Freshdesk app, and the hookUrl stops working.",
        "description": "Disconnect: forgets the API key, the alerts and the Freshdesk app, and the `hookUrl` stops working. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/freshdesk/groups": {
      "get": {
        "operationId": "getApiWorkspacesByWFreshdeskGroups",
        "tags": [
          "Freshdesk"
        ],
        "summary": "The Freshdesk groups an alert can be limited to, as groups with id and name.",
        "description": "The Freshdesk groups an alert can be limited to, as `groups` with `id` and `name`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/freshdesk/alerts": {
      "post": {
        "operationId": "postApiWorkspacesByWFreshdeskAlerts",
        "tags": [
          "Freshdesk"
        ],
        "summary": "Add a ticket alert: channelId, events (created, status, reply, priority, assignment) and an optional groupId.",
        "description": "Add a ticket alert: `channelId`, `events` (`created`, `status`, `reply`, `priority`, `assignment`) and an optional `groupId`. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"channelId\": \"01J…\", \"events\": [\"created\", \"status\"], \"groupId\": \"7\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/freshdesk/alerts/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWFreshdeskAlertsById",
        "tags": [
          "Freshdesk"
        ],
        "summary": "Change channelId, events or groupId, or turn it off and on with disabled.",
        "description": "Change `channelId`, `events` or `groupId`, or turn it off and on with `disabled`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWFreshdeskAlertsById",
        "tags": [
          "Freshdesk"
        ],
        "summary": "Delete the alert.",
        "description": "Delete the alert. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/freshdesk/alerts/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWFreshdeskAlertsByIdTest",
        "tags": [
          "Freshdesk"
        ],
        "summary": "Post a sample ticket into its channel.",
        "description": "Post a sample ticket into its channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/hooks/support/freshdesk/{token}": {
      "post": {
        "operationId": "postHooksSupportFreshdeskByToken",
        "tags": [
          "Freshdesk"
        ],
        "summary": "Where Freshdesk's automation rules say a ticket was made ({\"freesbe_event\":\"created\",\"ticket_id\":\"…\"}) or changed (\"upda",
        "description": "Where Freshdesk's automation rules say a ticket was made (`{\"freesbe_event\":\"created\",\"ticket_id\":\"…\"}`) or changed (`\"updated\"`). Freesbe reads the ticket from Freshdesk and posts what changed since it last saw it. Answers 200, 400 without a ticket number and 404 after a disconnect.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/monitoring": {
      "get": {
        "operationId": "getApiWorkspacesByWMonitoring",
        "tags": [
          "Monitoring"
        ],
        "summary": "The connections: provider, name, channelId, minSeverity (info, warning, average, high or critical), replyOnResolve, serv",
        "description": "The `connections`: `provider`, `name`, `channelId`, `minSeverity` (`info`, `warning`, `average`, `high` or `critical`), `replyOnResolve`, `serverUrl`, `hasApiToken`, `openProblems`, `lastEventAt`, `board` (the live problems board is pinned), `reportSchedule` (`daily`, `weekly` or null), `reportTimeZone` and `nextReportAt`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWMonitoring",
        "tags": [
          "Monitoring"
        ],
        "summary": "Connect a tool: provider (zabbix, grafana, alertmanager, pagerduty, opsgenie, datadog, sentry, betterstack, newrelic, up",
        "description": "Connect a tool: `provider` (`zabbix`, `grafana`, `alertmanager`, `pagerduty`, `opsgenie`, `datadog`, `sentry`, `betterstack`, `newrelic`, `uptimekuma`, `uptimerobot` or `freesbe-status`), `name`, `channelId`, and optionally `minSeverity`, `replyOnResolve`, `serverUrl`, `apiToken`, `board` (default true), `reportSchedule` and `reportTimeZone` (reports post at 9:00 there). Freesbe checks the token with the tool before saving it, encrypted. Answers 201 with the `hookUrl` to give the tool, shown only now. For `freesbe-status` there is nothing to paste: Freesbe registers the URL with [status.freesbe.net](https://status.freesbe.net/) itself.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"provider\": \"zabbix\", \"name\": \"Production Zabbix\", \"channelId\": \"01J…\", \"minSeverity\": \"warning\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/monitoring/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWMonitoringById",
        "tags": [
          "Monitoring"
        ],
        "summary": "Change name, channelId, minSeverity, replyOnResolve, serverUrl, apiToken (null removes it, and the buttons), board, repo",
        "description": "Change `name`, `channelId`, `minSeverity`, `replyOnResolve`, `serverUrl`, `apiToken` (null removes it, and the buttons), `board`, `reportSchedule` or `reportTimeZone`, or turn it off and on with `disabled`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"minSeverity\": \"high\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWMonitoringById",
        "tags": [
          "Monitoring"
        ],
        "summary": "Disconnect it.",
        "description": "Disconnect it. Cards already posted stay. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/monitoring/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWMonitoringByIdTest",
        "tags": [
          "Monitoring"
        ],
        "summary": "Post a sample problem card into its channel.",
        "description": "Post a sample problem card into its channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/hooks/monitoring/zabbix/{token}": {
      "post": {
        "operationId": "postHooksMonitoringZabbixByToken",
        "tags": [
          "Monitoring"
        ],
        "summary": "Where Freesbe's Zabbix media type sends each problem, update and recovery, as JSON with Zabbix's macros filled in (event",
        "description": "Where Freesbe's Zabbix media type sends each problem, update and recovery, as JSON with Zabbix's macros filled in (`event_id`, `event_value`, `event_update_status`, `event_nseverity`, `event_name`, `host_name`…). Answers 200 whether or not it posted, 404 to an unknown or switched-off connection, and 410 when its channel is gone.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/hooks/monitoring/grafana/{token}": {
      "post": {
        "operationId": "postHooksMonitoringGrafanaByToken",
        "tags": [
          "Monitoring"
        ],
        "summary": "Where a Grafana webhook contact point sends: Alertmanager's webhook format (version 4) with Grafana's extra fields.",
        "description": "Where a Grafana webhook contact point sends: Alertmanager's webhook format (version 4) with Grafana's extra fields. Each alert in `alerts` is one card, named by its `fingerprint` and `startsAt`; a `resolved` alert turns its card green. Same answers as Zabbix's.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/hooks/monitoring/alertmanager/{token}": {
      "post": {
        "operationId": "postHooksMonitoringAlertmanagerByToken",
        "tags": [
          "Monitoring"
        ],
        "summary": "Where Prometheus Alertmanager's webhook_configs send, in its webhook format (version 4).",
        "description": "Where Prometheus Alertmanager's `webhook_configs` send, in its webhook format (version 4). Each alert is one card; the `severity` label sets its severity (high when there's none). Same answers as Zabbix's.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/hooks/monitoring/pagerduty/{token}": {
      "post": {
        "operationId": "postHooksMonitoringPagerdutyByToken",
        "tags": [
          "Monitoring"
        ],
        "summary": "Where a PagerDuty generic webhook (V3) subscription sends incident events.",
        "description": "Where a PagerDuty generic webhook (V3) subscription sends incident events. Each incident is one card, named by its `id`: `incident.triggered` posts it, acknowledgements, reassignments, escalations, priority changes and notes update it, and `incident.resolved` turns it green. The priority (P1 to P5) sets its severity, or the urgency when there's none. Same answers as Zabbix's.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/hooks/monitoring/opsgenie/{token}": {
      "post": {
        "operationId": "postHooksMonitoringOpsgenieByToken",
        "tags": [
          "Monitoring"
        ],
        "summary": "Where an Opsgenie Webhook integration sends alert actions.",
        "description": "Where an Opsgenie Webhook integration sends alert actions. Each alert is one card, named by its `alertId`: `Create` posts it, `Acknowledge`, `UnAcknowledge`, `AddNote`, `AssignOwnership` and `UpdatePriority` update it, and `Close` turns it green. The priority (P1 to P5) sets its severity. Same answers as Zabbix's.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/hooks/monitoring/datadog/{token}": {
      "post": {
        "operationId": "postHooksMonitoringDatadogByToken",
        "tags": [
          "Monitoring"
        ],
        "summary": "Where a Datadog webhook sends monitor notifications, with the payload shown when connecting (Datadog's $ALERT_CYCLE_KEY,",
        "description": "Where a Datadog webhook sends monitor notifications, with the payload shown when connecting (Datadog's `$ALERT_CYCLE_KEY`, `$ALERT_ID`, `$ALERT_TRANSITION`, `$ALERT_PRIORITY`, `$EVENT_TITLE`, `$HOSTNAME`, `$ALERT_SCOPE`, `$TAGS`, `$LINK` and more). Each alert cycle is one card: `Triggered`, `Warn` and `No Data` post or update it, and `Recovered` turns it green. Same answers as Zabbix's.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/hooks/monitoring/sentry/{token}": {
      "post": {
        "operationId": "postHooksMonitoringSentryByToken",
        "tags": [
          "Monitoring"
        ],
        "summary": "Where a Sentry internal integration sends its webhooks.",
        "description": "Where a Sentry internal integration sends its webhooks. Issue webhooks (`created`, `resolved`, `unresolved`, `archived`, `assigned`) and issue alerts (`triggered`) are one card per issue, named by its id; an issue that's `unresolved` after it was resolved gets a new card. Metric alerts (`critical`, `warning`, `resolved`) are cards of their own. The issue's `level` sets its severity. Same answers as Zabbix's.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/hooks/monitoring/betterstack/{token}": {
      "post": {
        "operationId": "postHooksMonitoringBetterstackByToken",
        "tags": [
          "Monitoring"
        ],
        "summary": "Where a Better Stack Uptime webhook sends incidents ({ data: { id, type: \"incident\", attributes } }).",
        "description": "Where a Better Stack Uptime webhook sends incidents (`{ data: { id, type: \"incident\", attributes } }`). Each incident is one card, named by its id: `Started` posts it, `Acknowledged` updates it, and `Resolved` turns it green. Same answers as Zabbix's.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/hooks/monitoring/newrelic/{token}": {
      "post": {
        "operationId": "postHooksMonitoringNewrelicByToken",
        "tags": [
          "Monitoring"
        ],
        "summary": "Where a New Relic workflow's webhook sends issues, with the payload shown when connecting (the workflow's issueId, issue",
        "description": "Where a New Relic workflow's webhook sends issues, with the payload shown when connecting (the workflow's `issueId`, `issuePageUrl`, `priority`, `state`, `entitiesData.names`, `accumulations.conditionName` and more). Each issue is one card: `CREATED` and `ACTIVATED` post it, `ACKNOWLEDGED` updates it, and `CLOSED` turns it green. The priority sets its severity. Same answers as Zabbix's.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/hooks/monitoring/uptimekuma/{token}": {
      "post": {
        "operationId": "postHooksMonitoringUptimekumaByToken",
        "tags": [
          "Monitoring"
        ],
        "summary": "Where an Uptime Kuma Webhook notification sends ({ heartbeat, monitor, msg }, as application/json).",
        "description": "Where an Uptime Kuma Webhook notification sends (`{ heartbeat, monitor, msg }`, as application/json). Each outage is one card per monitor: `heartbeat.status` 0 posts it, and 1 turns it green. Going down again after being back up is a new card. Kuma's test message posts nothing. Same answers as Zabbix's.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/hooks/monitoring/uptimerobot/{token}": {
      "post": {
        "operationId": "postHooksMonitoringUptimerobotByToken",
        "tags": [
          "Monitoring"
        ],
        "summary": "Where an UptimeRobot webhook alert contact sends, with the payload shown when connecting (monitorID, name, url, alertTyp",
        "description": "Where an UptimeRobot webhook alert contact sends, with the payload shown when connecting (`monitorID`, `name`, `url`, `alertType`, `details`, `duration`, `time`). `alertType` 1 posts a card for the monitor and 2 turns it green with how long it was down; other alerts post nothing. Same answers as Zabbix's.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/hooks/monitoring/freesbe-status/{token}": {
      "post": {
        "operationId": "postHooksMonitoringFreesbeStatusByToken",
        "tags": [
          "Monitoring"
        ],
        "summary": "Where status.freesbe.net posts incidents and updates for a Freesbe status connection, signed with X-Status-Signature.",
        "description": "Where status.freesbe.net posts incidents and updates for a Freesbe status connection, signed with `X-Status-Signature`. Freesbe registers it itself when the connection is made.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/feeds": {
      "get": {
        "operationId": "getApiWorkspacesByWFeeds",
        "tags": [
          "News feeds"
        ],
        "summary": "The feeds: url, siteUrl, name, iconUrl, channelId, keywords, lastCheckedAt, lastItemAt, nextCheckAt, error (while it kee",
        "description": "The `feeds`: `url`, `siteUrl`, `name`, `iconUrl`, `channelId`, `keywords`, `lastCheckedAt`, `lastItemAt`, `nextCheckAt`, `error` (while it keeps failing) and `brokenAt` (paused after 3 days of failing), and the plan's `limit` (null for none).\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWFeeds",
        "tags": [
          "News feeds"
        ],
        "summary": "Add a feed: url, channelId, and optionally name (the feed's title), keywords (only items with one of them in the title o",
        "description": "Add a feed: `url`, `channelId`, and optionally `name` (the feed's title), `keywords` (only items with one of them in the title or summary post) and `postLatest` (default true: post the newest item now). Everything already in the feed counts as seen. Answers 201, or 409 at the plan's limit.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"url\": \"https://blog.northwind.example/feed.xml\", \"channelId\": \"01J…\", \"keywords\": [\"tea\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/feeds/preview": {
      "post": {
        "operationId": "postApiWorkspacesByWFeedsPreview",
        "tags": [
          "News feeds"
        ],
        "summary": "Find and read a feed before adding it: url is the feed's address or a website's whose page links to its feed.",
        "description": "Find and read a feed before adding it: `url` is the feed's address or a website's whose page links to its feed. Answers with the feed's own `url`, `title`, `siteUrl`, `iconUrl` and its newest 3 `items`, or 400 when there's no feed there.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"url\": \"blog.northwind.example\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/feeds/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWFeedsById",
        "tags": [
          "News feeds"
        ],
        "summary": "Change name, channelId or keywords, or turn it off and on with disabled.",
        "description": "Change `name`, `channelId` or `keywords`, or turn it off and on with `disabled`. Saving a paused feed checks it again soon.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"keywords\": [\"tea\", \"coffee\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWFeedsById",
        "tags": [
          "News feeds"
        ],
        "summary": "Stop checking the feed.",
        "description": "Stop checking the feed. Cards already posted stay. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/feeds/{id}/check": {
      "post": {
        "operationId": "postApiWorkspacesByWFeedsByIdCheck",
        "tags": [
          "News feeds"
        ],
        "summary": "Check the feed now and post anything new.",
        "description": "Check the feed now and post anything new. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zoho-recruit": {
      "get": {
        "operationId": "getApiWorkspacesByWZohoRecruit",
        "tags": [
          "Zoho Recruit"
        ],
        "summary": "Whether the server can connect Zoho (available), the connection (orgId, orgName, dataCenter, recruitUrl, botUserId, unfu",
        "description": "Whether the server can connect Zoho (`available`), the `connection` (`orgId`, `orgName`, `dataCenter`, `recruitUrl`, `botUserId`, `unfurls`, `listening` while Zoho Recruit sends changes, `brokenAt` when Zoho stopped accepting it) or null, and the `alerts`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiWorkspacesByWZohoRecruit",
        "tags": [
          "Zoho Recruit"
        ],
        "summary": "Turn link previews on or off with unfurls.",
        "description": "Turn link previews on or off with `unfurls`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"unfurls\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWZohoRecruit",
        "tags": [
          "Zoho Recruit"
        ],
        "summary": "Disconnect: Zoho Recruit stops sending changes and Freesbe's access is revoked in Zoho.",
        "description": "Disconnect: Zoho Recruit stops sending changes and Freesbe's access is revoked in Zoho. Alerts are kept for a reconnect. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zoho-recruit/connect": {
      "post": {
        "operationId": "postApiWorkspacesByWZohoRecruitConnect",
        "tags": [
          "Zoho Recruit"
        ],
        "summary": "The url of Zoho's page that asks to allow Freesbe.",
        "description": "The `url` of Zoho's page that asks to allow Freesbe. Send the browser there; Zoho sends it to the person's own data center, then back to Freesbe, which finishes connecting and opens the app with `?zoho-recruit=connected`. Only the admin who started it can finish it, within 15 minutes.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zoho-recruit/alerts": {
      "post": {
        "operationId": "postApiWorkspacesByWZohoRecruitAlerts",
        "tags": [
          "Zoho Recruit"
        ],
        "summary": "Add an alert: channelId and kinds (candidate_created, candidate_status, candidate_hired, job_created, interview_schedule",
        "description": "Add an alert: `channelId` and `kinds` (`candidate_created`, `candidate_status`, `candidate_hired`, `job_created`, `interview_scheduled`). Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"channelId\": \"01J…\", \"kinds\": [\"candidate_hired\", \"interview_scheduled\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zoho-recruit/alerts/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWZohoRecruitAlertsById",
        "tags": [
          "Zoho Recruit"
        ],
        "summary": "Change channelId or kinds, or turn it off and on with disabled.",
        "description": "Change `channelId` or `kinds`, or turn it off and on with `disabled`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"disabled\": true }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWZohoRecruitAlertsById",
        "tags": [
          "Zoho Recruit"
        ],
        "summary": "Delete it.",
        "description": "Delete it. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/zoho-recruit/alerts/{id}/test": {
      "post": {
        "operationId": "postApiWorkspacesByWZohoRecruitAlertsByIdTest",
        "tags": [
          "Zoho Recruit"
        ],
        "summary": "Post a sample alert into its channel.",
        "description": "Post a sample alert into its channel. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/hooks/recruiting/zoho-recruit/{token}": {
      "post": {
        "operationId": "postHooksRecruitingZohoRecruitByToken",
        "tags": [
          "Zoho Recruit"
        ],
        "summary": "Where Zoho Recruit delivers one organization's change notifications.",
        "description": "Where Zoho Recruit delivers one organization's change notifications. The body's `token` has to be the one Freesbe gave Zoho with the channel. Answers 200 and posts afterwards, 401 to a wrong token, and 404 after a disconnect.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/workflows": {
      "get": {
        "operationId": "getApiWorkspacesByWWorkflows",
        "tags": [
          "Workflows"
        ],
        "summary": "The workflows you manage, plus the button workflows that are on, by name.",
        "description": "The workflows you manage, plus the button workflows that are on, by name. `canCreate` says whether you can make one. People who can't edit a workflow don't get its steps.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{\n  \"workflows\": [\n    { \"id\": \"01JBK4…\", \"name\": \"IT help request\", \"emoji\": \"🛠️\", \"status\": \"on\",\n      \"trigger\": { \"type\": \"manual\", \"channelIds\": [\"01JB9S…\"] }, \"runCount\": 12, \"canEdit\": false, … }\n  ],\n  \"canCreate\": true\n}\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWWorkflows",
        "tags": [
          "Workflows"
        ],
        "summary": "Make a workflow: name, optional description and emoji, a trigger, up to 30 steps, and status on or off.",
        "description": "Make a workflow: `name`, optional `description` and `emoji`, a `trigger`, up to 30 `steps`, and `status` `on` or `off`. Only admins can when the workspace's `workflowBuilders` is `admins`. A workflow with problems can be saved, but stays off. Triggers: `manual`, `schedule`, `reaction`, `member_joined`, `message`, `webhook`, `clock`, `booking`, `meeting_ended`, `huddle_ended`, `missed_call`, `todo_done`. Steps: `message`, `form`, `add_to_channel`, `todo`, `wait`, `approval`, `ask`, `set_status`, `branch` (with `conditions`, `then` and `else`). Answers 201.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"name\": \"IT help request\", \"emoji\": \"🛠️\", \"status\": \"on\",\n  \"trigger\": { \"type\": \"manual\", \"channelIds\": [\"01JB9S…\"] },\n  \"steps\": [\n    { \"id\": \"f1\", \"type\": \"form\", \"person\": { \"var\": \"trigger.person\" }, \"title\": \"Ask IT for help\", \"text\": \"\",\n      \"fields\": [ { \"id\": \"what\", \"label\": \"What do you need help with?\", \"type\": \"paragraph\", \"required\": true, \"options\": [] } ] },\n    { \"id\": \"s2\", \"type\": \"message\", \"to\": { \"kind\": \"channel\", \"channelId\": \"01JB9S…\" },\n      \"text\": \"*New IT request* from {{f1.person}}\\n{{f1.what}}\" }\n  ] }\n```\n\nExample answer:\n\n```json\n{ \"workflow\": { \"id\": \"01JBK4…\", \"name\": \"IT help request\", \"status\": \"on\", \"canEdit\": true, … } }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workflows/{id}": {
      "get": {
        "operationId": "getApiWorkflowsById",
        "tags": [
          "Workflows"
        ],
        "summary": "One workflow you can see.",
        "description": "One workflow you can see.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"workflow\": { \"id\": \"01JBK4…\", \"name\": \"IT help request\", \"trigger\": { \"type\": \"manual\", … }, \"steps\": [ … ], … } }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiWorkflowsById",
        "tags": [
          "Workflows"
        ],
        "summary": "Change any of the fields above.",
        "description": "Change any of the fields above. Turning it `on` needs it free of problems; a schedule's next run is worked out again.\n\nWho can call it: Creator or admins. The person who created the channel, or a workspace owner or admin.\n\nExample request:\n\n```json\n{ \"status\": \"off\" }\n```",
        "x-freesbe-access": "manager",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkflowsById",
        "tags": [
          "Workflows"
        ],
        "summary": "Delete it and stop its runs that are still going.",
        "description": "Delete it and stop its runs that are still going. Answers 204.\n\nWho can call it: Creator or admins. The person who created the channel, or a workspace owner or admin.",
        "x-freesbe-access": "manager",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workflows/{id}/run": {
      "post": {
        "operationId": "postApiWorkflowsByIdRun",
        "tags": [
          "Workflows"
        ],
        "summary": "Run a workflow that starts from a button.",
        "description": "Run a workflow that starts from a button. Pass `channelId` to start it from a channel. Its maker can try it while it's off. A form for you comes back as `request`, ready to fill in. Up to 200 runs an hour each.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"channelId\": \"01JB9S…\" }\n```\n\nExample answer:\n\n```json\n{ \"run\": { \"id\": \"01JBK7…\", \"status\": \"waiting\", … }, \"request\": { \"id\": \"01JBK8…\", \"title\": \"Ask IT for help\", … } }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workflows/{id}/runs": {
      "get": {
        "operationId": "getApiWorkflowsByIdRuns",
        "tags": [
          "Workflows"
        ],
        "summary": "The latest runs, newest first, each with its status and a log of what it did.",
        "description": "The latest runs, newest first, each with its status and a log of what it did.\n\nWho can call it: Creator or admins. The person who created the channel, or a workspace owner or admin.\n\nExample answer:\n\n```json\n{ \"runs\": [ { \"id\": \"01JBK7…\", \"status\": \"done\", \"startedBy\": \"01JB8Q…\", \"startedAt\": 1761238800000,\n  \"log\": [ { \"at\": 1761238800000, \"stepId\": null, \"ok\": true, \"text\": \"Started by {person}\", \"vars\": { \"person\": \"01JB8Q…\" } }, … ] } ] }\n```",
        "x-freesbe-access": "manager",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workflows/{id}/hook-url": {
      "post": {
        "operationId": "postApiWorkflowsByIdHookUrl",
        "tags": [
          "Workflows"
        ],
        "summary": "A new secret URL for a workflow that starts from a webhook, as the workflow's hookUrl.",
        "description": "A new secret URL for a workflow that starts from a webhook, as the workflow's `hookUrl`. The old one stops working at once.\n\nWho can call it: Creator or admins. The person who created the channel, or a workspace owner or admin.",
        "x-freesbe-access": "manager",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workflow-runs/{id}/cancel": {
      "post": {
        "operationId": "postApiWorkflowRunsByIdCancel",
        "tags": [
          "Workflows"
        ],
        "summary": "Stop a run that is still going.",
        "description": "Stop a run that is still going. Answers 204.\n\nWho can call it: Creator or admins. The person who created the channel, or a workspace owner or admin.",
        "x-freesbe-access": "manager",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/workflow-requests": {
      "get": {
        "operationId": "getApiWorkspacesByWWorkflowRequests",
        "tags": [
          "Workflows"
        ],
        "summary": "Forms, approvals and questions that workflows sent you and that are still open.",
        "description": "Forms, approvals and questions that workflows sent you and that are still open. `kind` is `form`, `approval` or `ask`. Questions posted in a channel for anyone to answer aren't listed.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"requests\": [ { \"id\": \"01JBK7…\", \"workflowName\": \"Monthly check-in\", \"title\": \"How was your month?\",\n  \"fields\": [ … ], \"status\": \"open\", \"createdAt\": 1761238800000 } ] }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workflow-requests/{id}": {
      "get": {
        "operationId": "getApiWorkflowRequestsById",
        "tags": [
          "Workflows"
        ],
        "summary": "One request sent to you, open or not, or a question in a channel you're in.",
        "description": "One request sent to you, open or not, or a question in a channel you're in.\n\nWho can call it: Its owner. Only the person it belongs to, such as the maker of a booking page.",
        "x-freesbe-access": "owner",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkflowRequestsById",
        "tags": [
          "Workflows"
        ],
        "summary": "Answer it, and the workflow carries on at once.",
        "description": "Answer it, and the workflow carries on at once. A form takes `answers` by question id; an approval takes `decision` (`approved` or `rejected`) and an optional `comment`; a question takes one of its `choices` as `choice`. Answers 204, or 409 when someone already answered.\n\nWho can call it: Its owner. Only the person it belongs to, such as the maker of a booking page.\n\nExample request:\n\n```json\n{ \"answers\": { \"what\": \"My laptop won't connect to the office printer\", \"urgency\": \"Today, please\" } }\n{ \"decision\": \"approved\", \"comment\": \"Enjoy the trip\" }\n{ \"choice\": \"Tacos\" }\n```",
        "x-freesbe-access": "owner",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkflowRequestsById",
        "tags": [
          "Workflows"
        ],
        "summary": "Close a form without sending it, which stops the workflow that sent it.",
        "description": "Close a form without sending it, which stops the workflow that sent it. Only forms can be closed this way. Answers 204.\n\nWho can call it: Its owner. Only the person it belongs to, such as the maker of a booking page.",
        "x-freesbe-access": "owner",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/hooks/workflows/{token}": {
      "post": {
        "operationId": "postHooksWorkflowsByToken",
        "tags": [
          "Workflows"
        ],
        "summary": "Start a workflow that starts from a webhook, with a JSON object of its variables.",
        "description": "Start a workflow that starts from a webhook, with a JSON object of its variables. The token in the URL is the secret. Answers `{ \"ok\": true }`, or `ok: false` with an `error`.\n\nWho can call it: No token. Anyone can call it, without a token.\n\nExample request:\n\n```json\n{ \"order\": \"NW-10482\", \"customer\": \"Acme Corp\", \"days\": \"3\" }\n```",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/phone": {
      "get": {
        "operationId": "getApiWorkspacesByWPhone",
        "tags": [
          "Phone"
        ],
        "summary": "Your SIP account, if it's set up.",
        "description": "Your SIP account, if it's set up. Add `?reveal=1` for the password. Guests get `provider: \"off\"`. On the phone system from Freesbe (`inApp: true`), `account` is always null: the apps sign in on their own, and admins set up desk phones.\n\nWho can call it: Members. Anyone in the workspace, guests included. Guests only see their own channels and the people in them.\n\nExample answer:\n\n```json\n{ \"provider\": \"sipio\", \"account\": { \"username\": \"dana.whitfield\", \"domain\": \"northwind.sip.example\",\n  \"createdAt\": 1761200000000, \"rotatedAt\": null } }\n```",
        "x-freesbe-access": "members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWPhone",
        "tags": [
          "Phone"
        ],
        "summary": "Set up your SIP account.",
        "description": "Set up your SIP account. The answer includes the password. Answers 403 on the phone system from Freesbe, where admins set up desk phones.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/rotate": {
      "post": {
        "operationId": "postApiWorkspacesByWPhoneRotate",
        "tags": [
          "Phone"
        ],
        "summary": "A new SIP password.",
        "description": "A new SIP password. The old one stops working. Answers 403 on the phone system from Freesbe.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/webphone": {
      "post": {
        "operationId": "postApiWorkspacesByWPhoneWebphone",
        "tags": [
          "Phone"
        ],
        "summary": "A short-lived login for calling from Freesbe itself, on a phone system from Freesbe: a SIP over WebSocket server, the ur",
        "description": "A short-lived login for calling from Freesbe itself, on a phone system from Freesbe: a SIP over WebSocket `server`, the `uri`, `username` and `password`, `iceServers` for the call's audio, and when it runs out (`expiresAt`). One at a time per person: a new one ends the last. The mobile and desktop apps send `install` (`{ id, name }`: an id the app keeps while installed, starting with `desk_` for the desktop app, and the phone's or computer's name) to get a line of their own instead, which rings alongside the others and stays until the app signs out; only the Freesbe apps can. A computer's line gets a new password at each login, and one whose app hasn't logged in for 8 hours gets a new password nobody has, so it works only while the app keeps coming back. A person has at most 10 computer lines: a new one replaces the one used longest ago. 409 when the workspace has no phone system from Freesbe or it's turned off. `inApp` on `GET /phone` says whether to use it.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"server\": \"wss://webrtc.sip.example\", \"uri\": \"sip:wrtc_7@northwind.sip.example\", \"username\": \"wrtc_7\",\n  \"password\": \"…\", \"extension\": \"1001\", \"iceServers\": [{ \"urls\": [\"stun:turn.sip.example:3478\"] }], \"expiresAt\": 1761228800000 }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/webphone/{install}": {
      "delete": {
        "operationId": "deleteApiWorkspacesByWPhoneWebphoneByInstall",
        "tags": [
          "Phone"
        ],
        "summary": "Signs the mobile or desktop app's own line out (on sign-out): calls stop ringing it.",
        "description": "Signs the mobile or desktop app's own line out (on sign-out): calls stop ringing it. 204, also when it was already gone.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "install",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/answered": {
      "post": {
        "operationId": "postApiWorkspacesByWPhoneAnswered",
        "tags": [
          "Phone"
        ],
        "summary": "Says this device just answered a call from number, with kind (desktop, mobile or web) and the device's name.",
        "description": "Says this device just answered a call from `number`, with `kind` (`desktop`, `mobile` or `web`) and the device's `name`. Your other devices get a `phone.answered` event (`number`, `on: { kind, name }`, `at`), so where the call rang too they show where it was answered instead of a missed call. Not for apps. 204.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/calls": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneCalls",
        "tags": [
          "Phone"
        ],
        "summary": "Your calls on the phone system from Freesbe from the last 30 days, newest first, 50 at a time (?page=2 for older ones wh",
        "description": "Your calls on the phone system from Freesbe from the last 30 days, newest first, 50 at a time (`?page=2` for older ones while `more` is true). `direction` is from your side; `userId` is the colleague on the other end, and `number` is null for them. `seconds` is time talking, 0 when unanswered. `transcriptId` is the recording id of the call's transcript when it was transcribed (read it with `/phone/recordings/{id}/transcript`), or null. Each call that ends after that reaches your devices as a `phone.call_logged` event with the same fields (`call`), so read this once and add those to it. 409 without a phone system from Freesbe.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"calls\": [{ \"id\": \"c2\", \"direction\": \"in\", \"number\": \"+16465550111\", \"name\": \"Acme Corp\", \"userId\": null,\n  \"startedAt\": 1761228800000, \"answered\": false, \"seconds\": 0, \"transcriptId\": null }], \"more\": false }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWPhoneCalls",
        "tags": [
          "Phone"
        ],
        "summary": "Click-to-call: ring someone's Freesbe phone, and once they pick up, dial to from the workspace's number.",
        "description": "Click-to-call: ring someone's Freesbe phone, and once they pick up, dial `to` from the workspace's number. People start calls for themselves; an app with the `phone:call` scope names whose phone rings with `userId` or `email` (for example a CRM's Call button, from its server). `leadId` and `vars` (up to 20 short values) come back in the `phone.call_ended` event, with how it went and how long it lasted. 409 with `call_unreachable` when the person isn't signed in to Freesbe's phone anywhere (the app on a computer or phone), `call_busy` when they're on a call, `call_duplicate` for the same call twice within 5 seconds, and `conflict` without a phone system from Freesbe or while it's off. 400 when `to` isn't a US or Canadian number or is premium-rate (900, 976), and 429 past the workspace's calls to outside numbers this hour (30 on Free or a trial, 300 on paid plans).\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"to\": \"+14155550142\", \"email\": \"dana@northwind.example\", \"leadId\": \"lead-2291\", \"vars\": { \"deal\": \"Acme renewal\" } }\n```\n\nExample answer:\n\n```json\n{ \"id\": \"c2c_01JC9A2B3C4D5E6F7G8H9J0K1M\", \"userId\": \"01JB8Z6Y0QH3W8T2M5N7P9R1S3\" }\n```",
        "x-freesbe-access": "full-members",
        "x-freesbe-app-scope": "phone:call",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/missed": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneMissed",
        "tags": [
          "Phone"
        ],
        "summary": "When you last looked at your Recent calls (seenAt, null if never): missed calls after it are new.",
        "description": "When you last looked at your Recent calls (`seenAt`, null if never): missed calls after it are new. The apps count those on the phone, leaving out ones the caller left a voicemail for.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"seenAt\": 1761228800000 }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWPhoneMissed",
        "tags": [
          "Phone"
        ],
        "summary": "You've seen your missed calls, now.",
        "description": "You've seen your missed calls, now. Your other devices hear it as a `phone.missed_seen` event. Answers like `GET`.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/transcribe": {
      "post": {
        "operationId": "postApiWorkspacesByWPhoneTranscribe",
        "tags": [
          "Phone"
        ],
        "summary": "Transcribe the call you're on now (on: true), or stop (on: false).",
        "description": "Transcribe the call you're on now (`on: true`), or stop (`on: false`). This records the call; when it ends, you and the colleagues on it get its transcript and AI notes in a message from Phone. Counts toward the plan's transcript hours, shared with huddles and meetings. 403 when an admin hasn't turned on transcribing your own calls (`canTranscribe` on `GET /phone`), 409 when you're not on a call.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"on\": true }\n```\n\nExample answer:\n\n```json\n{ \"on\": true }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/recordings/{id}/transcript": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneRecordingsByIdTranscript",
        "tags": [
          "Phone"
        ],
        "summary": "A transcribed call you were on: who it was with, when it started and how long it was, and the transcript (a summary, the",
        "description": "A transcribed call you were on: who it was `with`, when it started and how long it was, and the `transcript` (a summary, the caller's mood, key points, action items and every line, with `side` `agent` for your side and `caller` for theirs). Admins can read any. 404 for a call you weren't on.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"call\": { \"with\": \"Contoso\", \"startedAt\": 1761228800000, \"seconds\": 402 }, \"transcript\": { \"state\": \"done\", \"summary\": \"…\", \"sentiment\": \"Friendly\", \"keyPoints\": [\"…\"], \"actionItems\": [\"…\"], \"lines\": [{ \"side\": \"agent\", \"speaker\": null, \"start\": 2, \"text\": \"Hi Kenji…\" }] } }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/recordings/{id}/audio": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneRecordingsByIdAudio",
        "tags": [
          "Phone"
        ],
        "summary": "The recording of a transcribed call you were on, as audio.",
        "description": "The recording of a transcribed call you were on, as audio. 404 for a call you weren't on.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/recordings/{id}/share": {
      "post": {
        "operationId": "postApiWorkspacesByWPhoneRecordingsByIdShare",
        "tags": [
          "Phone"
        ],
        "summary": "Post a transcribed call's notes (the summary and action items, with a link to the transcript) to a channel or DM you can",
        "description": "Post a transcribed call's notes (the summary and action items, with a link to the transcript) to a channel or DM you can write in, as you. Answers 204.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"channelId\": \"01J…\" }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/sip-connection": {
      "get": {
        "operationId": "getApiWorkspacesByWSipConnection",
        "tags": [
          "Phone"
        ],
        "summary": "Whether the workspace is connected to sip.io, and how.",
        "description": "Whether the workspace is connected to sip.io, and how.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWSipConnection",
        "tags": [
          "Phone"
        ],
        "summary": "Connect sip.io: apiBase, accountId, apiKey, and linkByEmail to put each new device on the sip.io user with the same emai",
        "description": "Connect sip.io: `apiBase`, `accountId`, `apiKey`, and `linkByEmail` to put each new device on the sip.io user with the same email (off by default). Freesbe checks the key first.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"apiBase\": \"https://northwind.sip.example/api\", \"accountId\": \"4411\", \"apiKey\": \"…\", \"linkByEmail\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWSipConnection",
        "tags": [
          "Phone"
        ],
        "summary": "Disconnect sip.io.",
        "description": "Disconnect sip.io. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystem",
        "tags": [
          "Phone"
        ],
        "summary": "The phone system from Freesbe.",
        "description": "The phone system from Freesbe. `available` says whether this server offers one, `included` whether the workspace has the Phone system add-on, and `enabled` whether it's on. `status` is `active`, `outbound_off` while a payment is a week overdue (incoming calls still ring), or `off`, with `offReason` (`admin` or `unpaid`) and `releaseAt`, when the kept numbers are released.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"available\": true, \"included\": true, \"enabled\": true, \"country\": \"US\", \"sipDomain\": \"northwind.sip.example\",\n  \"enabledAt\": 1792540320000, \"enabledBy\": \"01JB8Q…\", \"status\": \"active\", \"offReason\": null, \"offAt\": null, \"releaseAt\": null }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWPhoneSystem",
        "tags": [
          "Phone"
        ],
        "summary": "Turn the phone system on, for a country (a two-letter code; the United States or Canada for now).",
        "description": "Turn the phone system on, for a `country` (a two-letter code; the United States or Canada for now). Answers like `GET`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"country\": \"US\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWPhoneSystem",
        "tags": [
          "Phone"
        ],
        "summary": "Turn the phone system off.",
        "description": "Turn the phone system off. Calls, texts and phone logins stop, and the numbers are kept until `releaseAt`. Answers like `GET`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/turn-on-again": {
      "post": {
        "operationId": "postApiWorkspacesByWPhoneSystemTurnOnAgain",
        "tags": [
          "Phone"
        ],
        "summary": "Turn a phone system that was turned off back on, with the numbers it kept.",
        "description": "Turn a phone system that was turned off back on, with the numbers it kept. When it was turned off for an overdue payment, pay the invoice on the Billing page first, or this answers 409.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/identity": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemIdentity",
        "tags": [
          "Phone"
        ],
        "summary": "Where the workspace is with identity verification, which buying numbers needs once: required, and status: none, waiting ",
        "description": "Where the workspace is with identity verification, which buying numbers needs once: `required`, and `status`: `none`, `waiting` (the `link` is ready for a phone, until `linkExpiresAt`), `started`, `checking`, `review`, `approved`, `rejected` or `expired`. `POST` starts a check, or answers the one that's open.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"required\": true, \"status\": \"waiting\", \"link\": \"https://verify.example/s/…\", \"linkExpiresAt\": 1792731600000,\n  \"startedBy\": \"01JB8Q…\", \"startedAt\": 1792729800000, \"verifiedAt\": null, \"verifiedBy\": null }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/numbers/search": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemNumbersSearch",
        "tags": [
          "Phone"
        ],
        "summary": "Numbers for sale.",
        "description": "Numbers for sale. `type` is `local` (the default) or `tollfree`; `areaCode` is optional. Each offer has its monthly and setup price in `currency`, and `needsDocuments` when the carrier needs documents before it works. `included` is how many local numbers the workspace can still get at no extra cost (one comes with each person on the Phone system add-on).\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"offers\": [ { \"offer\": \"…\", \"e164\": \"+14155550134\", \"city\": \"San Francisco\", \"region\": \"CA\", \"areaCode\": \"415\",\n  \"numberType\": \"local\", \"capabilities\": [\"voice\", \"sms\"], \"monthlyPrice\": 5, \"setupPrice\": 0, \"currency\": \"USD\",\n  \"needsDocuments\": false } ], \"included\": 3 }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "areaCode",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/numbers": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemNumbers",
        "tags": [
          "Phone"
        ],
        "summary": "The workspace's numbers: each one's status (active, pending, documents_needed, releasing or other), label, country (two ",
        "description": "The workspace's numbers: each one's `status` (`active`, `pending`, `documents_needed`, `releasing` or `other`), `label`, `country` (two letters), place, type (`numberType`: `geographic`, `tollfree`, `national` or `mobile`), who it rings (`ringsUserIds`, everyone it rings at once; `ringsUserId` is set when that's one person), whether it can send and receive `texts`, and whether it goes to voicemail after hours (`afterHoursVoicemail`).\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"numbers\": [ { \"id\": \"01JC5N…\", \"e164\": \"+14155550134\", \"status\": \"active\", \"label\": \"Main line\", \"country\": \"US\", \"city\": \"San Francisco\",\n  \"region\": \"CA\", \"numberType\": \"local\", \"ringsUserId\": \"01JB8Q…\", \"ringsUserIds\": [\"01JB8Q…\"], \"texts\": true, \"afterHoursVoicemail\": false } ] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWPhoneSystemNumbers",
        "tags": [
          "Phone"
        ],
        "summary": "Buy a number: send back an offer from the search, and optionally ringsUserId, the person its calls ring.",
        "description": "Buy a number: send back an `offer` from the search, and optionally `ringsUserId`, the person its calls ring. Needs identity verification first. `status` is `active`, `pending` or `documents_needed`. Answers 201.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"offer\": \"…\", \"ringsUserId\": \"01JB8Q…\" }\n```\n\nExample answer:\n\n```json\n{ \"number\": { \"id\": \"01JC5N…\", \"e164\": \"+14155550134\", \"status\": \"active\", … }, \"status\": \"active\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/numbers/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWPhoneSystemNumbersById",
        "tags": [
          "Phone"
        ],
        "summary": "Change who a number rings: ringsUserIds, 1 to 20 people, who all ring at once and the first to answer takes the call (ri",
        "description": "Change who a number rings: `ringsUserIds`, 1 to 20 people, who all ring at once and the first to answer takes the call (`ringsUserId` still works for one person). The first time a number rings someone, Freesbe makes their phone account. `afterHoursVoicemail: true` sends its calls outside the business hours to the voicemail of the first person it rings (set the hours first). When several people ring and nobody answers, the call goes to the first person's voicemail. `menuId` answers it with a phone menu instead, `queueId` with a call queue (both turn voicemail after hours off), and `ringGroupId` with a ring group. Send what changes. Answers the number, with its `menuId`, `queueId` and `ringGroupId`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"ringsUserIds\": [\"01JB8R…\", \"01JB8S…\"], \"afterHoursVoicemail\": true }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWPhoneSystemNumbersById",
        "tags": [
          "Phone"
        ],
        "summary": "Release a number back to the carrier.",
        "description": "Release a number back to the carrier. Calls and texts to it stop, and you may not get it again. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/numbers/{id}/settings": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemNumbersByIdSettings",
        "tags": [
          "Phone"
        ],
        "summary": "One number's line settings: its label, whether callers who hide their number ring through (allowAnonymous), whether it f",
        "description": "One number's line settings: its `label`, whether callers who hide their number ring through (`allowAnonymous`), whether it follows the business hours (`followsHours`) and where calls go when it's closed (`afterHours`) and on closed days (`holidays`, null is the same as after hours): `voicemail`, `menu` (`menuId`), `queue` (`queueId`) or `hangup`. `callerId.calls` and `callerId.texts` say who may call or text out with it: `anyone`, `selected` (`userIds`) or `nobody`. `texts` says whether the carrier can deliver texts to it, whether texting is on, and the customer inbox that takes them. `fax` has whether fax machines are answered, the `method` (`t38` or `passthrough`), the `emails` faxes go to, a `webhookUrl`, and whether a PDF of each is kept.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"number\": { \"id\": \"did_1\", \"e164\": \"+12065550134\", \"label\": \"Main line\", \"country\": \"US\", … }, \"label\": \"Main line\",\n  \"allowAnonymous\": true, \"followsHours\": true, \"afterHours\": { \"kind\": \"voicemail\" }, \"afterHoursName\": \"Maya Chen\",\n  \"holidays\": null, \"holidaysName\": null,\n  \"callerId\": { \"calls\": { \"mode\": \"anyone\", \"userIds\": [] }, \"texts\": { \"mode\": \"selected\", \"userIds\": [\"01JB8R…\"] } },\n  \"texts\": { \"available\": true, \"enabled\": true, \"inbox\": { \"id\": \"01JD…\", \"name\": \"Texts\" } },\n  \"fax\": { \"on\": true, \"method\": \"t38\", \"emails\": [\"fax@northwind.example\"], \"webhookUrl\": null, \"keep\": true } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiWorkspacesByWPhoneSystemNumbersByIdSettings",
        "tags": [
          "Phone"
        ],
        "summary": "Change a number's line settings.",
        "description": "Change a number's line settings. Send what changes: `label` (up to 120 characters, null clears it), `allowAnonymous`, `afterHours` (a route as above to follow the business hours, null to stop), `holidays` (null sends closed days where after hours does), `callerId.calls` and `callerId.texts`, and any of `fax.on`, `fax.method`, `fax.emails`, `fax.webhookUrl` (https) and `fax.keep`. Voicemail goes to the first person the number rings. Answers the settings as they now are.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"label\": \"Main line\", \"afterHours\": { \"kind\": \"menu\", \"menuId\": \"ivr_8f…\" }, \"fax\": { \"on\": true, \"emails\": [\"fax@northwind.example\"] } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/port-ins": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemPortIns",
        "tags": [
          "Phone"
        ],
        "summary": "Requests to move numbers in from another provider, newest first.",
        "description": "Requests to move numbers in from another provider, newest first. `status` is `sent` (waiting for Freesbe to check it), `checked`, `submitted` (with the old provider), `needs_fix` (see `message`, then fix it and send it again), `done` or `cancelled`. `moveAt` is the move day once the old provider gives one. The account number comes back as its last 4 characters (`accountEnding`) and the PIN never does.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"requests\": [ { \"id\": \"01JD2P…\", \"numbers\": [\"+18135550142\", \"+18135550143\"], \"provider\": \"Contoso Telecom\",\n  \"accountEnding\": \"4821\", \"accountName\": \"Northwind Traders\", \"serviceAddress\": \"100 Harbor St, Tampa, FL 33602\",\n  \"hasPin\": true, \"billName\": \"contoso-bill.pdf\", \"answers\": { \"kind\": \"menu\", \"menuId\": \"ivr_8f…\" }, \"moveOn\": null,\n  \"status\": \"submitted\", \"moveAt\": \"2026-11-12\", \"message\": null, \"signerName\": \"Maya Chen\", \"signerTitle\": \"Operations lead\",\n  \"signedAt\": 1761868800000, \"createdBy\": \"01JB8Q…\", \"createdAt\": 1761868800000, \"updatedAt\": 1761955200000, \"doneAt\": null } ] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWPhoneSystemPortIns",
        "tags": [
          "Phone"
        ],
        "summary": "Ask to move numbers in from another provider.",
        "description": "Ask to move numbers in from another provider. Send a multipart form: `numbers` (a JSON array of up to 100 US or Canadian numbers, all with the same provider), `provider`, `accountNumber`, `pin` (if the provider set one for moving numbers), `accountName` and `serviceAddress` exactly as the provider has them, `answers` (JSON: `{ \"kind\": \"people\", \"userIds\": […] }`, `{ \"kind\": \"menu\", \"menuId\": … }` or `{ \"kind\": \"queue\", \"queueId\": … }`, what answers the numbers once they arrive), `moveOn` (YYYY-MM-DD, at least 7 days out, or left out for as soon as possible), `bill` (a PDF or picture of a recent bill, 10 MB at most), and the letter of authorization's signature: `signerName`, `signerTitle` and `agree` set to `true`. Needs the Phone system add-on and identity verification. Free. Answers 201 with the request; once the numbers arrive they answer as asked and are billed like other numbers.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\nnumbers=[\"+18135550142\",\"+18135550143\"] provider=Contoso Telecom accountNumber=88-4821 pin=1234\naccountName=Northwind Traders serviceAddress=100 Harbor St, Tampa, FL 33602 answers={\"kind\":\"menu\",\"menuId\":\"ivr_8f…\"}\nsignerName=Maya Chen signerTitle=Operations lead agree=true bill=@bill.pdf\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/port-ins/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWPhoneSystemPortInsById",
        "tags": [
          "Phone"
        ],
        "summary": "Fix a request and send it again, signed again: every field like POST, except bill (the one sent before is kept unless a ",
        "description": "Fix a request and send it again, signed again: every field like `POST`, except `bill` (the one sent before is kept unless a new one comes) and `pin` (kept when left out). Only before it's with the old provider (`sent`, `checked` or `needs_fix`). Answers the request.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWPhoneSystemPortInsById",
        "tags": [
          "Phone"
        ],
        "summary": "Cancel a request that hasn't finished.",
        "description": "Cancel a request that hasn't finished. Answers the request, now `cancelled`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/menus": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemMenus",
        "tags": [
          "Phone"
        ],
        "summary": "The phone menus (IVR): each one's greeting (typed text read in a voice, or an uploaded recording with text null), the op",
        "description": "The phone menus (IVR): each one's `greeting` (typed `text` read in a `voice`, or an uploaded recording with `text` null), the `options` callers press, `noChoice` (where the call goes when nobody presses a key, after the greeting plays twice), `waitSeconds`, `dialExtensions` (whether callers can dial someone's extension during the greeting: `\"everyone\"`, a list of user ids, or null), and the `numberIds` it answers. An action is `people` (`userIds`, all ringing at once, then the first person's voicemail), `ringGroup` (`ringGroupId`), `voicemail` (a person's `userId`), `menu` (`menuId`), `queue` (`queueId`) or `hangup`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"menus\": [{ \"id\": \"ivr_8f…\", \"name\": \"Main menu\", \"waitSeconds\": 5, \"numberIds\": [\"did_1\"],\n  \"greeting\": { \"recordingId\": \"media_3a…\", \"text\": \"Thanks for calling Northwind. For sales, press 1.\", \"voice\": \"1|en-US|Neural2-F\" },\n  \"options\": [{ \"key\": \"1\", \"action\": { \"kind\": \"people\", \"userIds\": [\"01JB8R…\", \"01JB8S…\"] } },\n    { \"key\": \"2\", \"action\": { \"kind\": \"menu\", \"menuId\": \"ivr_9c…\" } }],\n  \"noChoice\": { \"kind\": \"voicemail\", \"userId\": \"01JB8R…\" } }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWPhoneSystemMenus",
        "tags": [
          "Phone"
        ],
        "summary": "Make a phone menu: a name, a greeting (text and a voice from GET …/voices, a recordingId from uploading one, or null for",
        "description": "Make a phone menu: a `name`, a `greeting` (`text` and a `voice` from `GET …/voices`, a `recordingId` from uploading one, or null for none), up to 12 `options` with a `key` (0 to 9, * or #) and an `action`, a `noChoice` action, `waitSeconds` (3 to 30), and optionally `dialExtensions` (`\"everyone\"`, user ids, or null, the default; keys win when they clash). Answers 201 with the menu. A workspace can have 30.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"name\": \"Main menu\", \"greeting\": { \"text\": \"Thanks for calling Northwind. For sales, press 1.\", \"voice\": \"1|en-US|Neural2-F\" },\n  \"options\": [{ \"key\": \"1\", \"action\": { \"kind\": \"people\", \"userIds\": [\"01JB8R…\"] } }],\n  \"noChoice\": { \"kind\": \"hangup\" }, \"waitSeconds\": 5 }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/menus/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWPhoneSystemMenusById",
        "tags": [
          "Phone"
        ],
        "summary": "Change a phone menu.",
        "description": "Change a phone menu. Send it whole, like `POST`. Answers the menu.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWPhoneSystemMenusById",
        "tags": [
          "Phone"
        ],
        "summary": "Delete a phone menu.",
        "description": "Delete a phone menu. Answers 204, or 409 while a number answers with it or another menu sends calls to it.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/call-us-links": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemCallUsLinks",
        "tags": [
          "Phone"
        ],
        "summary": "The Call us links: pages customers open to call from the browser, free.",
        "description": "The Call us links: pages customers open to call from the browser, free. Each has its `url` (call.freesbe.net/…), the `title` customers see, up to 5 `buttons` (a `label`, a `description` and an `action`, as a phone menu's key takes, but never `hangup`), `askName` (customers type their name, shown as the caller's name), up to 5 `questions` (`label`, `rule`: `letters_only`, `long_text`, `numbers_only`, `decimal`, `email` or `phone`, and `required`), and `hours` with its `closedMessage` (buttons follow the business hours).\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"links\": [{ \"id\": \"01JC…\", \"name\": \"Main call menu\", \"title\": \"How can we help?\", \"url\": \"https://call.freesbe.net/k7Qm2x…\",\n  \"buttons\": [{ \"id\": \"wgr_1…\", \"label\": \"Sales\", \"description\": \"New orders and quotes\", \"action\": { \"kind\": \"queue\", \"queueId\": \"q_4…\" } }],\n  \"askName\": true, \"questions\": [{ \"label\": \"Order number\", \"rule\": \"numbers_only\", \"required\": false }],\n  \"hours\": true, \"closedMessage\": \"We're open weekdays 9 to 6.\", \"createdAt\": 1793450000000 }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWPhoneSystemCallUsLinks",
        "tags": [
          "Phone"
        ],
        "summary": "Make a Call us link: name, title, buttons, askName, questions, hours and closedMessage, as GET shows them.",
        "description": "Make a Call us link: `name`, `title`, `buttons`, `askName`, `questions`, `hours` and `closedMessage`, as `GET` shows them. `hours` needs the business hours set first. Answers 201 with the link. A workspace can have 20. Calls from them are free for customers and cost the workspace $0.01 a minute.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"name\": \"Main call menu\", \"title\": \"How can we help?\", \"askName\": true, \"hours\": false, \"closedMessage\": null,\n  \"buttons\": [{ \"label\": \"Sales\", \"description\": \"New orders and quotes\", \"action\": { \"kind\": \"people\", \"userIds\": [\"01JB8R…\"] } }],\n  \"questions\": [{ \"label\": \"Order number\", \"rule\": \"numbers_only\", \"required\": false }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/call-us-links/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWPhoneSystemCallUsLinksById",
        "tags": [
          "Phone"
        ],
        "summary": "Change a Call us link.",
        "description": "Change a Call us link. Send it whole, like `POST`; keep each button's `id` so it stays the same button. The link's address doesn't change. Answers the link.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWPhoneSystemCallUsLinksById",
        "tags": [
          "Phone"
        ],
        "summary": "Delete a Call us link.",
        "description": "Delete a Call us link. Its address stops working, and a Telegram bot offering it stops. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/call/{key}": {
      "get": {
        "operationId": "getApiCallByKey",
        "tags": [
          "Phone"
        ],
        "summary": "A Call us link's public page, no sign-in: the workspace's name and logoUrl, the title, the buttons with whether each is ",
        "description": "A Call us link's public page, no sign-in: the workspace's `name` and `logoUrl`, the `title`, the `buttons` with whether each is `open` now, `askName`, the `questions`, `closedMessage`, and `phone`, where the browser gets its login for the call. 404 when there's no such link.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/workspaces/{w}/phone-system/extensions": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemExtensions",
        "tags": [
          "Phone"
        ],
        "summary": "Everyone's extension on the phone system from Freesbe (null for someone still getting theirs, which happens on its own) ",
        "description": "Everyone's extension on the phone system from Freesbe (null for someone still getting theirs, which happens on its own) and `firstExtension`, where new ones start.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"firstExtension\": 101, \"people\": [{ \"userId\": \"01JB8R…\", \"extension\": \"101\" }, { \"userId\": \"01JB8S…\", \"extension\": \"102\" }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "patchApiWorkspacesByWPhoneSystemExtensions",
        "tags": [
          "Phone"
        ],
        "summary": "Set where new extensions start: 101 to 899 for three digits, 1001 to 8999 for four, not starting with 9.",
        "description": "Set where new extensions start: 101 to 899 for three digits, 1001 to 8999 for four, not starting with 9. People who have one keep it. Answers like `GET`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"firstExtension\": 1001 }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/extensions/{userId}": {
      "put": {
        "operationId": "putApiWorkspacesByWPhoneSystemExtensionsByUserId",
        "tags": [
          "Phone"
        ],
        "summary": "Change someone's extension: 2 to 6 digits, not starting with 0 or 9.",
        "description": "Change someone's extension: 2 to 6 digits, not starting with 0 or 9. Answers 409 when it's someone else's or the phone system uses it already.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"extension\": \"120\" }\n```\n\nExample answer:\n\n```json\n{ \"userId\": \"01JB8R…\", \"extension\": \"120\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/extensions/{userId}/desk-phone": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemExtensionsByUserIdDeskPhone",
        "tags": [
          "Phone"
        ],
        "summary": "Someone's SIP login for a desk phone or softphone app, like GET /phone answers them (account is null until they have one",
        "description": "Someone's SIP login for a desk phone or softphone app, like `GET /phone` answers them (`account` is null until they have one). Add `?reveal=1` for the password, which the audit log records. The Freesbe apps don't need it: they sign in on their own.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"provider\": \"sipio\", \"account\": { \"username\": \"northwind1011\", \"domain\": \"northwind.sip.example\",\n  \"createdAt\": 1761200000000, \"rotatedAt\": null } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWPhoneSystemExtensionsByUserIdDeskPhone",
        "tags": [
          "Phone"
        ],
        "summary": "Set up someone's desk phone login, or answer the one they have.",
        "description": "Set up someone's desk phone login, or answer the one they have. The answer includes the password.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/extensions/{userId}/call-handling": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemExtensionsByUserIdCallHandling",
        "tags": [
          "Phone"
        ],
        "summary": "How someone's calls ring, like GET /phone/call-handling answers them.",
        "description": "How someone's calls ring, like `GET /phone/call-handling` answers them.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWPhoneSystemExtensionsByUserIdCallHandling",
        "tags": [
          "Phone"
        ],
        "summary": "Set how someone's calls ring, like they can, and locked so they can't change it.",
        "description": "Set how someone's calls ring, like they can, and `locked` so they can't change it. They get a notice, and the audit log records it.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"handling\": null, \"locked\": true }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/extensions/{userId}/call-handling/devices/{id}": {
      "put": {
        "operationId": "putApiWorkspacesByWPhoneSystemExtensionsByUserIdCallHandlingDevicesById",
        "tags": [
          "Phone"
        ],
        "summary": "Turn one of someone's devices' ringing on or off, such as a lost phone.",
        "description": "Turn one of someone's devices' ringing on or off, such as a lost phone.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"rings\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/call-handling": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemCallHandling",
        "tags": [
          "Phone"
        ],
        "summary": "How calls ring for everyone who hasn't chosen their own: handling, like a person's.",
        "description": "How calls ring for everyone who hasn't chosen their own: `handling`, like a person's.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWPhoneSystemCallHandling",
        "tags": [
          "Phone"
        ],
        "summary": "Change the default.",
        "description": "Change the default. Its `noAnswer` is always `voicemail`. Everyone on it gets the new ring time.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"handling\": { \"mode\": \"all\", \"othersAfter\": 10, \"ringSeconds\": 30, \"steps\": [],\n  \"noAnswer\": { \"kind\": \"voicemail\" }, \"inMeeting\": \"ring\" } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/extensions/{userId}/desk-phone/rotate": {
      "post": {
        "operationId": "postApiWorkspacesByWPhoneSystemExtensionsByUserIdDeskPhoneRotate",
        "tags": [
          "Phone"
        ],
        "summary": "Give someone's desk phone login a new password.",
        "description": "Give someone's desk phone login a new password. The old one stops working, so enter the new one on their phone.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/ring-groups": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemRingGroups",
        "tags": [
          "Phone"
        ],
        "summary": "The ring groups: each one's memberIds (who it rings, in order), ring (all at once, inOrder from the top, or turns starti",
        "description": "The ring groups: each one's `memberIds` (who it rings, in order), `ring` (`all` at once, `inOrder` from the top, or `turns` starting after whoever answered last), `ringSeconds` (for everyone with `all`, for each person otherwise), `noAnswer` (where the call goes when nobody answers, an action like a menu's), `askFirst` (the person presses 1 to take the call), `callersHear` while it rings (`default` for the workspace's music on hold, `custom` for its uploaded music, a hold music track, or `ringing`), its `extension` (or null), the `numberIds` it answers and `usedBy`, what else sends calls to it. People who are busy or away are skipped.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"ringGroups\": [{ \"id\": \"rg_3c…\", \"name\": \"Front desk\", \"memberIds\": [\"01JB8R…\", \"01JB8S…\"], \"ring\": \"inOrder\",\n  \"ringSeconds\": 15, \"noAnswer\": { \"kind\": \"voicemail\", \"userId\": \"01JB8R…\" }, \"askFirst\": false,\n  \"callersHear\": \"default\", \"extension\": \"601\", \"numberIds\": [\"did_1\"], \"usedBy\": [\"+14155550100\", \"Main menu, key 1\"] }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWPhoneSystemRingGroups",
        "tags": [
          "Phone"
        ],
        "summary": "Make a ring group, with every field above but id, numberIds and usedBy: 1 to 20 memberIds, ringSeconds 5 to 120, and an ",
        "description": "Make a ring group, with every field above but `id`, `numberIds` and `usedBy`: 1 to 20 `memberIds`, `ringSeconds` 5 to 120, and an `extension` of 2 to 6 digits not starting with 0 or 9 (409 when it's taken). Answers 201 with the group. A workspace can have 50.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"name\": \"Front desk\", \"memberIds\": [\"01JB8R…\", \"01JB8S…\"], \"ring\": \"inOrder\", \"ringSeconds\": 15,\n  \"noAnswer\": { \"kind\": \"voicemail\", \"userId\": \"01JB8R…\" }, \"askFirst\": false, \"callersHear\": \"default\",\n  \"extension\": \"601\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/ring-groups/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWPhoneSystemRingGroupsById",
        "tags": [
          "Phone"
        ],
        "summary": "Change a ring group.",
        "description": "Change a ring group. Send it whole, like `POST`; an `extension` of null takes its extension away. Answers the group.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWPhoneSystemRingGroupsById",
        "tags": [
          "Phone"
        ],
        "summary": "Delete a ring group and its extension.",
        "description": "Delete a ring group and its extension. Answers 204, or 409 while a number, menu, queue, Call us link or another ring group sends calls to it.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/desk-phones": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemDeskPhones",
        "tags": [
          "Phone"
        ],
        "summary": "The desk phones that set themselves up: each one's mac (12 lowercase hex digits), modelId (like yealink-t48u), who it be",
        "description": "The desk phones that set themselves up: each one's `mac` (12 lowercase hex digits), `modelId` (like `yealink-t48u`), who it belongs to (`userId`, or `sharedName` and its own `extension` for a shared phone), its `keys`, its `status` (`state` is `online`, `offline`, `waiting` for a phone not plugged in yet, or `needsYou`; when it last signed in and fetched its settings, its address and firmware, and `redirect`, how the brand's cloud redirect stands) and `claimUntil`, until when a new phone can first fetch its settings. `provisioningUrl` is the address for DHCP option 66 or for typing on a phone.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"phones\": [{ \"id\": \"dp_2f…\", \"mac\": \"805ec03a127f\", \"modelId\": \"yealink-t48u\", \"userId\": \"01JB8R…\",\n  \"sharedName\": null, \"extension\": \"104\", \"keys\": [{ \"index\": 1, \"type\": \"line\", \"label\": \"James\" },\n  { \"index\": 2, \"type\": \"person\", \"label\": \"Maya\", \"userId\": \"01JB8S…\" }],\n  \"status\": { \"state\": \"online\", \"registeredAt\": 1767600000000, \"fetchedAt\": 1767600000000, \"ip\": \"203.0.113.24\",\n  \"firmware\": \"66.86.0.15\", \"redirect\": \"registered\" }, \"claimUntil\": null, \"createdAt\": 1767500000000 }],\n  \"provisioningUrl\": \"https://provision.freesbe.net/a/…/\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWPhoneSystemDeskPhones",
        "tags": [
          "Phone"
        ],
        "summary": "Add a desk phone by its mac (any common spelling) and modelId, for a person (userId, who must be on the phone system) or",
        "description": "Add a desk phone by its `mac` (any common spelling) and `modelId`, for a person (`userId`, who must be on the phone system) or as a shared phone (`shared` with its `name` and an `extension` nobody has). `keys` are optional: each has an `index` from 1, a `type` (`line`, `person` with a `userId`, `shared` with an `extension`, `speedDial` with a `number`, `queue` with a `queueId`, `voicemail`, `dnd`, or `park` with a `slot` 1 to 9) and a `label` of up to 24 characters. Answers 201 with the phone, or 409 when the phone is already on the list or set up with another phone service. A workspace can have 500.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"mac\": \"80:5E:C0:3A:12:7F\", \"modelId\": \"yealink-t48u\", \"userId\": \"01JB8R…\",\n  \"keys\": [{ \"index\": 1, \"type\": \"line\", \"label\": \"James\" }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/desk-phones/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWPhoneSystemDeskPhonesById",
        "tags": [
          "Phone"
        ],
        "summary": "Change a desk phone's keys (sent whole), or who it belongs to (userId or shared).",
        "description": "Change a desk phone's `keys` (sent whole), or who it belongs to (`userId` or `shared`). Moving a phone to someone else gives it a new password. Answers the phone.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWPhoneSystemDeskPhonesById",
        "tags": [
          "Phone"
        ],
        "summary": "Remove a desk phone: it signs out and stops getting settings.",
        "description": "Remove a desk phone: it signs out and stops getting settings. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/desk-phones/{id}/{action}": {
      "post": {
        "operationId": "postApiWorkspacesByWPhoneSystemDeskPhonesByIdByAction",
        "tags": [
          "Phone"
        ],
        "summary": "Ask a desk phone to resync (fetch its settings now), restart, take a newLogin (signs out and back in with a new password",
        "description": "Ask a desk phone to `resync` (fetch its settings now), `restart`, take a `newLogin` (signs out and back in with a new password), or `extendClaim` (another hour to fetch its settings for the first time). Answers the phone.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "action",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/queues": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemQueues",
        "tags": [
          "Phone"
        ],
        "summary": "The call queues: each one's memberIds (who takes its calls, in order), ring (longestIdle, all, turns, inOrder, fewestCal",
        "description": "The call queues: each one's `memberIds` (who takes its calls, in order), `ring` (`longestIdle`, `all`, `turns`, `inOrder`, `fewestCalls` or `random`), `greeting` (like a menu's), `holdMusicId` (null for the standard music), `announcePosition` and `announceEverySeconds`, `ringSeconds`, `wrapUpSeconds`, `maxWaitMinutes` and `maxCallers` (null for no limit), where callers go `afterWait` and when `noOneAvailable` is signed in (actions, like a menu's), and the `numberIds` it answers.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"queues\": [{ \"id\": \"q_4d…\", \"name\": \"Sales\", \"memberIds\": [\"01JB8R…\", \"01JB8S…\"], \"ring\": \"longestIdle\",\n  \"greeting\": { \"recordingId\": \"media_7e…\", \"text\": \"Please hold, we'll be with you soon.\", \"voice\": \"1|en-US|Neural2-F\" },\n  \"holdMusicId\": null, \"announcePosition\": true, \"announceEverySeconds\": 60, \"ringSeconds\": 20, \"wrapUpSeconds\": 15,\n  \"maxWaitMinutes\": 10, \"maxCallers\": null, \"afterWait\": { \"kind\": \"voicemail\", \"userId\": \"01JB8R…\" },\n  \"noOneAvailable\": { \"kind\": \"voicemail\", \"userId\": \"01JB8R…\" }, \"numberIds\": [\"did_1\"] }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWPhoneSystemQueues",
        "tags": [
          "Phone"
        ],
        "summary": "Make a call queue, with every field above but id and numberIds: 1 to 100 memberIds, announceEverySeconds 30 to 600, ring",
        "description": "Make a call queue, with every field above but `id` and `numberIds`: 1 to 100 `memberIds`, `announceEverySeconds` 30 to 600, `ringSeconds` 5 to 120, `wrapUpSeconds` 0 to 600, `maxWaitMinutes` 1 to 120 and `maxCallers` 1 to 500 (or null). `holdMusicId` is a `recordingId` from uploading a file. New members are signed in to take its calls. Needs the Call center add-on (403 without it). Answers 201 with the queue. A workspace can have 30.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"name\": \"Sales\", \"memberIds\": [\"01JB8R…\"], \"ring\": \"longestIdle\", \"greeting\": null, \"holdMusicId\": null,\n  \"announcePosition\": true, \"announceEverySeconds\": 60, \"ringSeconds\": 20, \"wrapUpSeconds\": 15,\n  \"maxWaitMinutes\": 10, \"maxCallers\": null, \"afterWait\": { \"kind\": \"voicemail\", \"userId\": \"01JB8R…\" },\n  \"noOneAvailable\": { \"kind\": \"hangup\" } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/queues/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWPhoneSystemQueuesById",
        "tags": [
          "Phone"
        ],
        "summary": "Change a call queue.",
        "description": "Change a call queue. Send it whole, like `POST`. Answers the queue.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWPhoneSystemQueuesById",
        "tags": [
          "Phone"
        ],
        "summary": "Delete a call queue.",
        "description": "Delete a call queue. Answers 204, or 409 while a number answers with it or a menu or another queue sends calls to it.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/break-reasons": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemBreakReasons",
        "tags": [
          "Phone"
        ],
        "summary": "The reasons people in call queues pick for a break, each with a name, a color (\"#RRGGBB\", or null for gray) and a limitM",
        "description": "The reasons people in call queues pick for a break, each with a `name`, a `color` (\"#RRGGBB\", or null for gray) and a `limitMinutes` time limit (null for none).\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"reasons\": [{ \"id\": \"pr_2a…\", \"name\": \"Lunch\", \"color\": \"#F59E0B\", \"limitMinutes\": 60 }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWPhoneSystemBreakReasons",
        "tags": [
          "Phone"
        ],
        "summary": "Add a break reason: a name (40 characters at most), a color, and an optional limitMinutes (1 to 480; people are told whe",
        "description": "Add a break reason: a `name` (40 characters at most), a `color`, and an optional `limitMinutes` (1 to 480; people are told when a break runs over it). Needs the Call center add-on. A workspace can have 20. Answers 201 with the reason.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"name\": \"Lunch\", \"color\": \"#F59E0B\", \"limitMinutes\": 60 }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/break-reasons/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWPhoneSystemBreakReasonsById",
        "tags": [
          "Phone"
        ],
        "summary": "Rename a break reason or change its color or time limit.",
        "description": "Rename a break reason or change its color or time limit. Send the `name` and `color`; leaving out `limitMinutes` takes the limit off. Answers the reason.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWPhoneSystemBreakReasonsById",
        "tags": [
          "Phone"
        ],
        "summary": "Delete a break reason.",
        "description": "Delete a break reason. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/supervisors": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemSupervisors",
        "tags": [
          "Phone"
        ],
        "summary": "Who besides admins can open the live Call center board and nudge people in call queues.",
        "description": "Who besides admins can open the live Call center board and nudge people in call queues.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"userIds\": [\"01J…\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWPhoneSystemSupervisors",
        "tags": [
          "Phone"
        ],
        "summary": "Replace the supervisors: up to 50 people in the workspace, not guests.",
        "description": "Replace the supervisors: up to 50 people in the workspace, not guests. Needs the Call center add-on. Answers like `GET`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"userIds\": [\"01J…\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/call-center-report": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemCallCenterReport",
        "tags": [
          "Phone"
        ],
        "summary": "Call center numbers for a range of dates (up to 90 days, counted in tz): each queue's calls, answers, callers who hung u",
        "description": "Call center numbers for a range of dates (up to 90 days, counted in `tz`): each queue's calls, answers, callers who hung up or timed out, service level, waits and talk time; calls per day; each person's answered calls and time talking, in wrap-up, on a break and signed in; and break time per reason. `queues` (comma-separated ids) narrows the queue numbers and days. Needs the Call center add-on.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"from\": \"2026-10-01\", \"to\": \"2026-10-31\", \"allQueues\": [{ \"id\": \"q_1\", \"name\": \"Support\" }], \"queues\": [{ \"id\": \"q_1\", \"name\": \"Support\", \"calls\": 2264, \"answered\": 1982, \"hungUp\": 226, \"timedOut\": 56, \"serviceLevel\": 0.83, \"avgWaitSec\": 41, \"longestWaitSec\": 287, \"avgTalkSec\": 356, \"people\": 4 }], \"total\": { \"id\": null, … }, \"days\": [{ \"date\": \"2026-10-01\", \"calls\": 211, \"answered\": 190, \"missed\": 21 }], \"people\": [{ \"userId\": \"01J…\", \"answered\": 412, \"avgTalkSec\": 291, \"talkSec\": 115800, \"wrapUpSec\": 3600, \"breakSec\": 14700, \"signedInSec\": 139800, \"busy\": 0.83 }], \"breaks\": [{ \"reason\": \"Lunch\", \"minutes\": 860, \"people\": 6 }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tz",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "queues",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/call-log": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemCallLog",
        "tags": [
          "Phone"
        ],
        "summary": "Every call on Freesbe's phone system for a range of dates (up to 90 days, counted in tz), newest first: who called whom,",
        "description": "Every call on Freesbe's phone system for a range of dates (up to 90 days, counted in `tz`), newest first: who called whom, in, out or between colleagues, who answered a call that rang a queue or several people, and how long they talked. `people` (comma-separated user ids) keeps calls those people made, took or were rung for. `direction` is `in`, `out` or `internal`; `result` is `answered` or `missed`; `q` matches any number (three digits or more) on either end, or a name; `minSeconds` keeps longer calls. With `direction`, `result`, `q` or `minSeconds`, up to the newest 5,000 calls in the range are searched, and `searchedCalls` says when the search stopped there. `limit` is up to 500 a page; `more` says another `page` may have older calls. `recordingId` is set on recorded calls.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"calls\": [{ \"id\": \"cdr_1\", \"startedAt\": 1793536200000, \"direction\": \"in\", \"from\": { \"userId\": null, \"name\": null, \"number\": \"+14155550142\" }, \"to\": { \"userId\": \"01J…\", \"name\": \"Support\", \"number\": \"+18135550111\" }, \"answeredBy\": \"01J…\", \"answered\": true, \"seconds\": 184, \"recordingId\": \"rec_1\" }], \"more\": false }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tz",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "people",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "result",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "minSeconds",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/recordings/{id}/audio": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemRecordingsByIdAudio",
        "tags": [
          "Phone"
        ],
        "summary": "A recorded call's audio (usually Ogg Opus), the whole file.",
        "description": "A recorded call's audio (usually Ogg Opus), the whole file. 409 `not_ready` while the recording is still being processed.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/recordings/{id}/transcript": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemRecordingsByIdTranscript",
        "tags": [
          "Phone"
        ],
        "summary": "A recorded call's transcript and summary, or null before one is made.",
        "description": "A recorded call's transcript and summary, or `null` before one is made. `side` is `agent` for the person in the workspace and `caller` for the other end; `start` is seconds into the call.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"transcript\": { \"state\": \"done\", \"summary\": \"The caller asked to move their delivery…\", \"sentiment\": \"positive\", \"keyPoints\": [\"…\"], \"actionItems\": [\"…\"], \"lines\": [{ \"side\": \"caller\", \"speaker\": null, \"start\": 0.4, \"text\": \"Hi, I'm calling about my order.\" }] } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWPhoneSystemRecordingsByIdTranscript",
        "tags": [
          "Phone"
        ],
        "summary": "Make the transcript and summary now, then answer it like the GET.",
        "description": "Make the transcript and summary now, then answer it like the GET. 409 `transcription_disabled` until transcripts are turned on under Phone → Call recording.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/flows": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemFlows",
        "tags": [
          "Phone"
        ],
        "summary": "Each number's call flow in short: the steps right after the number (first), how many steps it has, and who changed it la",
        "description": "Each number's call flow in short: the steps right after the number (`first`), how many steps it has, and who changed it last and when.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"flows\": [{ \"numberId\": \"did_4…\", \"number\": \"+12065550191\", \"label\": \"Customer line\", \"first\": [{ \"kind\": \"menu\", \"name\": \"Main menu\" }], \"steps\": 10, \"updatedAt\": \"2026-10-30T14:02:11.000Z\", \"updatedBy\": \"Maya Chen\" }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/flows/{numberId}": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemFlowsByNumberId",
        "tags": [
          "Phone"
        ],
        "summary": "What happens when someone calls the number, drawn from its routing now.",
        "description": "What happens when someone calls the number, drawn from its routing now. Each step has a `key` (`ivr:<id>`, `queue:<id>`, `ring_group:<id>`, `user:<id>`, `voicemail:<id>`, `announcement:<id>`, `hangup:`), a `kind` (`number`, `menu`, `queue`, `people`, `message`, `voicemail`, `hangup` or `other`) and its `exits`; each link joins an exit to the next step. `version` changes whenever the routing does.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"numberId\": \"did_4…\", \"number\": \"+12065550191\", \"label\": \"Customer line\", \"version\": \"\"9f…\"\", \"steps\": [{ \"key\": \"did:did_4…\", \"kind\": \"number\", \"name\": \"+12065550191\", \"exits\": [{ \"id\": \"default\", \"label\": \"Open\" }, { \"id\": \"closed\", \"label\": \"After hours\" }, { \"id\": \"holiday\", \"label\": \"Closed days\" }], \"position\": null }, { \"key\": \"ivr:ivr_1…\", \"kind\": \"menu\", \"name\": \"Main menu\", \"refId\": \"ivr_1…\", \"keys\": true, \"exits\": [{ \"id\": \"digit:1\", \"label\": \"Key 1\" }, { \"id\": \"timeout\", \"label\": \"No key pressed\" }], \"position\": { \"x\": 320, \"y\": 0 } }], \"links\": [{ \"from\": \"did:did_4…\", \"exit\": \"default\", \"to\": \"ivr:ivr_1…\" }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "numberId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWPhoneSystemFlowsByNumberId",
        "tags": [
          "Phone"
        ],
        "summary": "Change where the number's calls go: send every step's key, every link, where each step sits on the canvas, and the versi",
        "description": "Change where the number's calls go: send every step's `key`, every link, where each step sits on the canvas, and the `version` you read. Live at once. A link from a menu's new `digit:<key>` exit adds that key. 409 when the routing changed since `version`; 400 when a step has no way in or a line can't go where it's drawn. Answers the flow as saved.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"version\": \"\"9f…\"\", \"steps\": [\"did:did_4…\", \"ivr:ivr_1…\", \"hangup:\"], \"links\": [{ \"from\": \"did:did_4…\", \"exit\": \"default\", \"to\": \"ivr:ivr_1…\" }, { \"from\": \"ivr:ivr_1…\", \"exit\": \"timeout\", \"to\": \"hangup:\" }], \"positions\": { \"ivr:ivr_1…\": { \"x\": 320, \"y\": 0 } } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "numberId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/flow-steps": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemFlowSteps",
        "tags": [
          "Phone"
        ],
        "summary": "A menu or queue to add to a flow, ?key=ivr:<id> or ?key=queue:<id>, with every step after it as it routes now, so saving",
        "description": "A menu or queue to add to a flow, `?key=ivr:<id>` or `?key=queue:<id>`, with every step after it as it routes now, so saving the flow keeps its keys and exits.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"steps\": [{ \"key\": \"ivr:ivr_2…\", \"kind\": \"menu\", \"name\": \"Deliveries\", \"keys\": true, \"exits\": [{ \"id\": \"digit:1\", \"label\": \"Key 1\" }, { \"id\": \"timeout\", \"label\": \"No key pressed\" }], \"position\": null }], \"links\": [{ \"from\": \"ivr:ivr_2…\", \"exit\": \"digit:1\", \"to\": \"user:u_7…\" }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWPhoneSystemFlowSteps",
        "tags": [
          "Phone"
        ],
        "summary": "Make a new step for a flow: people rings userIds at once, voicemail takes a message for userId, and message reads out te",
        "description": "Make a new step for a flow: `people` rings `userIds` at once, `voicemail` takes a message for `userId`, and `message` reads out `text` in `voice`, then goes on. Answers 201 with the step, to place in a flow and save.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"kind\": \"message\", \"text\": \"We're closed for the holiday.\", \"voice\": \"1|en-US|Neural2-F\" }\n```\n\nExample answer:\n\n```json\n{ \"key\": \"announcement:ann_3…\", \"kind\": \"message\", \"name\": \"We're closed for the holiday.\", \"exits\": [{ \"id\": \"default\", \"label\": \"Then\" }], \"position\": null }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/recording": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemRecording",
        "tags": [
          "Phone"
        ],
        "summary": "Which calls the phone system records: record is off, everyone or some (the people in userIds), calls says which of their",
        "description": "Which calls the phone system records: `record` is `off`, `everyone` or `some` (the people in `userIds`), `calls` says which of their calls, and `queues` records every call queue call. Also whether recordings are transcribed and summarized with AI (counted toward the plan's transcript hours), whether people may press Transcribe in their own calls (`selfTranscribe`), how many days they're kept (`0` for good), and `lineUserIds`, the people with a phone line who can be picked.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"record\": \"everyone\", \"calls\": { \"incoming\": true, \"outgoing\": true, \"internal\": false }, \"queues\": true, \"userIds\": [], \"transcribe\": true, \"summarize\": true, \"selfTranscribe\": true, \"keepDays\": 365, \"lineUserIds\": [\"01J…\"] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWPhoneSystemRecording",
        "tags": [
          "Phone"
        ],
        "summary": "Change the call recording settings, sending them all as GET answers them, without lineUserIds.",
        "description": "Change the call recording settings, sending them all as GET answers them, without `lineUserIds`. `keepDays` is one of 30, 90, 365, 730 or 0, and applies to calls recorded from then on. Answers the settings as saved.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"record\": \"some\", \"calls\": { \"incoming\": true, \"outgoing\": false, \"internal\": true }, \"queues\": false, \"userIds\": [\"01J…\"], \"transcribe\": true, \"summarize\": false, \"selfTranscribe\": false, \"keepDays\": 90 }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/hold-music": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemHoldMusic",
        "tags": [
          "Phone"
        ],
        "summary": "The music on hold callers hear: track is lofi (until someone picks), jazz, classical, bossa, opus, pop, nature, quiet (a",
        "description": "The music on hold callers hear: `track` is `lofi` (until someone picks), `jazz`, `classical`, `bossa`, `opus`, `pop`, `nature`, `quiet` (a soft hiss, no music), or `custom` for the workspace's own upload. `custom` is that upload (kept while a track plays), or null. People who picked their own play theirs on their calls.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"track\": \"custom\", \"custom\": { \"recordingId\": \"media_…\", \"name\": \"Summer jingle.mp3\" } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWPhoneSystemHoldMusic",
        "tags": [
          "Phone"
        ],
        "summary": "Change the workspace's music on hold: a track, or custom with a recordingId uploaded with POST /phone-system/greetings a",
        "description": "Change the workspace's music on hold: a `track`, or `custom` with a `recordingId` uploaded with `POST /phone-system/greetings` and its file `name`. A new upload replaces (and deletes) the last one. It plays on every call from then on. Answers like `GET`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"track\": \"classical\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/voices": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemVoices",
        "tags": [
          "Phone"
        ],
        "summary": "The voices a typed greeting can be read in, in US and Canadian English, US Spanish and Canadian French.",
        "description": "The voices a typed greeting can be read in, in US and Canadian English, US Spanish and Canadian French.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"voices\": [{ \"id\": \"1|en-US|Neural2-F\", \"language\": \"en-US\", \"name\": \"Neural2-F\", \"gender\": \"female\" }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/greetings": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemGreetings",
        "tags": [
          "Phone"
        ],
        "summary": "Hear a typed greeting before saving it: ?text= read in ?voice=.",
        "description": "Hear a typed greeting before saving it: `?text=` read in `?voice=`. Answers the audio (WAV).\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWPhoneSystemGreetings",
        "tags": [
          "Phone"
        ],
        "summary": "Upload a recorded greeting as a WAV file in the multipart field audio (10 MB at most).",
        "description": "Upload a recorded greeting as a WAV file in the multipart field `audio` (10 MB at most). Answers 201 with the `recordingId` to save in a menu, or as a queue's greeting or hold music.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"recordingId\": \"media_4b…\", \"seconds\": 8 }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/greetings/{id}/audio": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemGreetingsByIdAudio",
        "tags": [
          "Phone"
        ],
        "summary": "Play a menu's greeting.",
        "description": "Play a menu's greeting. Answers the audio.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/hours": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemHours",
        "tags": [
          "Phone"
        ],
        "summary": "The workspace's business hours, or null until they're set: a timezone, open windows by day (0 = Sunday) with open and cl",
        "description": "The workspace's business hours, or `null` until they're set: a `timezone`, open windows by `day` (0 = Sunday) with `open` and `close` times, and `holidays`: each a `date` with its `name`, closed all day when `open` and `close` are null, otherwise open only then. `closedDates` lists the holidays closed all day.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"hours\": { \"timezone\": \"America/New_York\",\n  \"days\": [{ \"day\": 1, \"open\": \"09:00\", \"close\": \"17:00\" }],\n  \"closedDates\": [\"2026-12-25\"],\n  \"holidays\": [{ \"date\": \"2026-12-24\", \"name\": \"Christmas Eve\", \"open\": \"09:00\", \"close\": \"13:00\" },\n    { \"date\": \"2026-12-25\", \"name\": \"Christmas Day\", \"open\": null, \"close\": null }] } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWPhoneSystemHours",
        "tags": [
          "Phone"
        ],
        "summary": "Set the business hours, replacing them all.",
        "description": "Set the business hours, replacing them all. `close` can be `24:00` for midnight. Send `holidays` (up to 100) to name days and give them special hours; without it, `closedDates` become unnamed holidays closed all day. Answers the hours.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"timezone\": \"America/New_York\", \"days\": [{ \"day\": 1, \"open\": \"09:00\", \"close\": \"17:00\" }], \"closedDates\": [\"2026-12-25\"],\n  \"holidays\": [{ \"date\": \"2026-12-25\", \"name\": \"Christmas Day\", \"open\": null, \"close\": null }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/hours/public-holidays": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemHoursPublicHolidays",
        "tags": [
          "Phone"
        ],
        "summary": "A country's nationwide public holidays in the next 12 months, to add to the business hours: each a date, its English nam",
        "description": "A country's nationwide public holidays in the next 12 months, to add to the business hours: each a `date`, its English `name` and its `localName`. An empty list for a country the holiday calendar doesn't cover.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"country\": \"US\", \"holidays\": [{ \"date\": \"2026-12-25\", \"name\": \"Christmas Day\", \"localName\": \"Christmas Day\" }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/emergency": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneSystemEmergency",
        "tags": [
          "Phone"
        ],
        "summary": "Emergency addresses (E911): the workspace's locations with how many people work from each, the defaultLocationId used fo",
        "description": "Emergency addresses (E911): the workspace's `locations` with how many `people` work from each, the `defaultLocationId` used for everyone who hasn't picked one, and `alertChannelId`, the channel told when someone dials 911 (null: each admin gets a message from Phone). A location's `status` is `saved` until it's registered with the carrier (`registration` false means that isn't turned on yet), then `pending`, `confirmed`, or `needs_fixing` with a `problem`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample answer:\n\n```json\n{ \"registration\": true, \"defaultLocationId\": \"01JC…\", \"alertChannelId\": null,\n  \"locations\": [{ \"id\": \"01JC…\", \"name\": \"Main office\", \"ownerId\": null, \"status\": \"confirmed\", \"problem\": null, \"people\": 12,\n    \"address\": { \"line1\": \"500 Market St\", \"line2\": \"Floor 4\", \"city\": \"San Francisco\", \"region\": \"CA\", \"postalCode\": \"94105\", \"country\": \"US\" } }] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWPhoneSystemEmergency",
        "tags": [
          "Phone"
        ],
        "summary": "Change the defaultLocationId (one of the workspace's locations) or alertChannelId (a channel, or null for the admins).",
        "description": "Change the `defaultLocationId` (one of the workspace's locations) or `alertChannelId` (a channel, or null for the admins). Answers like `GET`.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"alertChannelId\": \"01JC…\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/emergency/locations": {
      "post": {
        "operationId": "postApiWorkspacesByWPhoneSystemEmergencyLocations",
        "tags": [
          "Phone"
        ],
        "summary": "Add an emergency address in the United States or Canada: a name and the street address with its number, two-letter regio",
        "description": "Add an emergency address in the United States or Canada: a `name` and the street `address` with its number, two-letter `region` and ZIP or postal code. The first one becomes the default. Answers 201 with the location.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"name\": \"Main office\", \"address\": { \"line1\": \"500 Market St\", \"line2\": \"Floor 4\", \"city\": \"San Francisco\",\n  \"region\": \"CA\", \"postalCode\": \"94105\", \"country\": \"US\" } }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone-system/emergency/locations/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWPhoneSystemEmergencyLocationsById",
        "tags": [
          "Phone"
        ],
        "summary": "Change a location's name or address, like POST.",
        "description": "Change a location's name or address, like `POST`. It's checked with the carrier again.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWPhoneSystemEmergencyLocationsById",
        "tags": [
          "Phone"
        ],
        "summary": "Remove a location.",
        "description": "Remove a location. 409 for the default, or while people work from it. Answers 204.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/queue-status": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneQueueStatus",
        "tags": [
          "Phone"
        ],
        "summary": "Your place in the call queues: the queues you're in (empty when none, or without the Call center add-on), status (taking",
        "description": "Your place in the call queues: the `queues` you're in (empty when none, or without the Call center add-on), `status` (`taking`, `break` or `out`), the `breakReasonId` of a break, `since` when, `phoneOffline` when you take calls but your Freesbe phone isn't open anywhere, and the `breakReasons` you can pick.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"queues\": [{ \"id\": \"q_4d…\", \"name\": \"Support\" }], \"status\": \"break\", \"breakReasonId\": \"pr_2a…\",\n  \"since\": 1767000000000, \"phoneOffline\": false, \"breakReasons\": [{ \"id\": \"pr_2a…\", \"name\": \"Lunch\", \"color\": \"#F59E0B\", \"limitMinutes\": 60 }] }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWPhoneQueueStatus",
        "tags": [
          "Phone"
        ],
        "summary": "Take your queues' calls (taking), take a break (with a breakReasonId or null), or sign out (out).",
        "description": "Take your queues' calls (`taking`), take a `break` (with a `breakReasonId` or null), or sign out (`out`). Calls to your own number ring either way. 409 when you're in no queue. Answers your status.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"status\": \"break\", \"breakReasonId\": \"pr_2a…\" }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/call-center": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneCallCenter",
        "tags": [
          "Phone"
        ],
        "summary": "The live Call center board, for admins and supervisors (403 for anyone else, or without the Call center add-on): the que",
        "description": "The live Call center board, for admins and supervisors (403 for anyone else, or without the Call center add-on): the `queues` with their people, `breakReasons`, and `live`: each queue's callers waiting and numbers for today, everyone's state and how long they've been in it, and the callers waiting (times in seconds). `agentIds` maps the ids in `live` to people. `socket` is a one-time, one-minute `wss://` URL that sends a fresh `live` as a `snapshot` frame whenever something changes; null when live updates aren't available.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"queues\": [{ \"id\": \"q_4d…\", \"name\": \"Support\", \"memberIds\": [\"01J…\"] }], \"agentIds\": { \"us_9f…\": \"01J…\" },\n  \"breakReasons\": [], \"live\": { \"as_of\": 1767000000000, \"queues\": [], \"total\": {}, \"agents\": [], \"waiting\": [] },\n  \"socket\": { \"url\": \"wss://…\", \"expiresAt\": 1767000060000 } }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/call-center/socket": {
      "post": {
        "operationId": "postApiWorkspacesByWPhoneCallCenterSocket",
        "tags": [
          "Phone"
        ],
        "summary": "A new one-time socket URL for the Call center board, to reconnect.",
        "description": "A new one-time `socket` URL for the Call center board, to reconnect. Admins and supervisors only.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"socket\": { \"url\": \"wss://…\", \"expiresAt\": 1767000060000 } }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/call-center/nudge": {
      "post": {
        "operationId": "postApiWorkspacesByWPhoneCallCenterNudge",
        "tags": [
          "Phone"
        ],
        "summary": "Nudge someone in a call queue with a direct message (message, 500 characters at most), from you (me) or from the Call ce",
        "description": "Nudge someone in a call queue with a direct message (`message`, 500 characters at most), `from` you (`me`) or from the Call center bot (`bot`). Admins and supervisors only. Answers 204.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"userId\": \"01J…\", \"message\": \"Callers are waiting. Can you come back from your break?\", \"from\": \"bot\" }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/call-center/supervise": {
      "post": {
        "operationId": "postApiWorkspacesByWPhoneCallCenterSupervise",
        "tags": [
          "Phone"
        ],
        "summary": "Join someone's live call from the Call center board, listening: you hear the call and nobody hears you.",
        "description": "Join someone's live call from the Call center board, listening: you hear the call and nobody hears you. `callId` is the call in `live.agents[].current.call_id`. The phone service rings your Freesbe phone, which answers on its own; switch to whispering or barging in with `/supervise/mode`. Admins and supervisors only, with a phone. 409 with a message when it can't be done, such as when calling from Freesbe isn't on, the call has ended, or you're already on another. Answers 204.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"callId\": \"c_1f…\" }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWPhoneCallCenterSupervise",
        "tags": [
          "Phone"
        ],
        "summary": "Leave a call you joined from the board.",
        "description": "Leave a call you joined from the board. The call goes on without you. Answers 204.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "callId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/call-center/supervise/mode": {
      "post": {
        "operationId": "postApiWorkspacesByWPhoneCallCenterSuperviseMode",
        "tags": [
          "Phone"
        ],
        "summary": "Switch how you're on a call you joined from the board, without leaving it: listen (nobody hears you), whisper (only the ",
        "description": "Switch how you're on a call you joined from the board, without leaving it: `listen` (nobody hears you), `whisper` (only the person in the queue hears you) or `barge` (everyone hears you). Answers 204.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"callId\": \"c_1f…\", \"mode\": \"whisper\" }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/directory": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneDirectory",
        "tags": [
          "Phone"
        ],
        "summary": "The colleagues with a phone, by name, with their extension (null when they have none) and Freesbe userId (null for a pho",
        "description": "The colleagues with a phone, by name, with their `extension` (null when they have none) and Freesbe `userId` (null for a phone system user who isn't a member), and the call `queues` (empty without the Call center add-on): who the phone can call and pass calls to.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"people\": [{ \"userId\": \"01J…\", \"name\": \"James Okafor\", \"extension\": \"102\" }], \"queues\": [{ \"id\": \"q_4d…\", \"name\": \"Support\" }] }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/transfer": {
      "post": {
        "operationId": "postApiWorkspacesByWPhoneTransfer",
        "tags": [
          "Phone"
        ],
        "summary": "Pass your current call on.",
        "description": "Pass your current call on. `start` with `mode` `now` (the caller holds until the target answers, then goes to them; nobody answering leaves the caller with you) or `talk` (you talk to the target first while the caller holds), to a `target`: `{ kind: \"person\", userId }`, `{ kind: \"queue\", id }` (always `now`) or `{ kind: \"number\", number }` (a colleague's extension goes to them). Talking first answers a `transferId`; then `complete` hands the caller over and ends your side, `merge` makes it a 3-way call, and `cancel` goes back to the caller. 409 with a message when it can't be done, such as when you're not on a call or the target hasn't answered yet.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"action\": \"start\", \"mode\": \"talk\", \"target\": { \"kind\": \"person\", \"userId\": \"01J…\" } }\n```\n\nExample answer:\n\n```json\n{ \"transferId\": \"call_7f…\" }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/voicemails": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneVoicemails",
        "tags": [
          "Phone"
        ],
        "summary": "Your own voicemails, newest first: who called (number, and name for a colleague or contact; a colleague calling from Fre",
        "description": "Your own voicemails, newest first: who called (`number`, and `name` for a colleague or contact; a colleague calling from Freesbe has their `userId` and no `number`), when (`at`), how long (`seconds`), whether it's `unread`, what they said (`transcript`, null until it's written out or when transcripts are off; `writing` while it's being written out), and the `unread` count. A new one reaches your devices as a `phone.voicemails_changed` event: read the list again.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"voicemails\": [{ \"id\": \"vmsg_3c…\", \"number\": \"+14155550187\", \"name\": null, \"userId\": null, \"at\": 1767000000000, \"seconds\": 42, \"unread\": true, \"transcript\": \"Hi, it's Dana from Acme Corp…\", \"writing\": false }], \"unread\": 1 }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/voicemails/{id}": {
      "patch": {
        "operationId": "patchApiWorkspacesByWPhoneVoicemailsById",
        "tags": [
          "Phone"
        ],
        "summary": "Mark one of your voicemails heard (unread: false) or not.",
        "description": "Mark one of your voicemails heard (`unread: false`) or not. Answers 204.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"unread\": false }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiWorkspacesByWPhoneVoicemailsById",
        "tags": [
          "Phone"
        ],
        "summary": "Delete one of your voicemails.",
        "description": "Delete one of your voicemails. The copy in your DM from Phone stays. Answers 204.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/voicemails/{id}/audio": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneVoicemailsByIdAudio",
        "tags": [
          "Phone"
        ],
        "summary": "The recording, as WAV.",
        "description": "The recording, as WAV. Playing it marks it heard, on all your devices.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/emergency": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneEmergency",
        "tags": [
          "Phone"
        ],
        "summary": "Where your 911 calls say you are: the workspace's locations and your own, the one you picked (locationId, null for the w",
        "description": "Where your 911 calls say you are: the workspace's `locations` and your own, the one you picked (`locationId`, null for the workspace's `defaultLocationId`).\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWPhoneEmergency",
        "tags": [
          "Phone"
        ],
        "summary": "Say where you work from: locationId (one of the workspace's or your own, null for the default), or own to add a place of",
        "description": "Say where you work from: `locationId` (one of the workspace's or your own, null for the default), or `own` to add a place of yours, like Home, and pick it (up to 5). Answers like `GET`.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"own\": { \"name\": \"Home\", \"address\": { \"line1\": \"12 Oak Ave\", \"city\": \"Oakland\", \"region\": \"CA\", \"postalCode\": \"94610\", \"country\": \"US\" } } }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/hold-music": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneHoldMusic",
        "tags": [
          "Phone"
        ],
        "summary": "The music your callers hear on hold: your own track, or null for the workspace's, which is workspaceTrack (custom for it",
        "description": "The music your callers hear on hold: your own `track`, or null for the workspace's, which is `workspaceTrack` (`custom` for its own upload, named in `workspaceCustomName`).\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"track\": null, \"workspaceTrack\": \"jazz\", \"workspaceCustomName\": null }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWPhoneHoldMusic",
        "tags": [
          "Phone"
        ],
        "summary": "Pick your own music on hold (one of the tracks the workspace's endpoint lists), or null to go back to the workspace's.",
        "description": "Pick your own music on hold (one of the tracks the workspace's endpoint lists), or null to go back to the workspace's. Answers like `GET`.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"track\": \"bossa\" }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/call-handling": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneCallHandling",
        "tags": [
          "Phone"
        ],
        "summary": "How your calls ring (Follow-Me).",
        "description": "How your calls ring (Follow-Me). `handling.mode` is `working` (the device you're using first, the rest after `othersAfter` seconds), `all` or `order` (`steps`, each with the devices that ring together, `computer`, `mobile` or `desk`, and its `seconds`). `ringSeconds` is how long `working` and `all` ring. `noAnswer` is `voicemail`, a teammate (`person` and `userId`) or an outside `number` with its `seconds`, which asks you to press 1 to take the call. `inMeeting` is `ring` or `skipComputer`. `own` is false while you follow the workspace's `workspaceDefault`, `locked` when an admin locked it, and `devices` are the devices your calls ring, each with `rings`.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"handling\": { \"mode\": \"working\", \"othersAfter\": 10, \"ringSeconds\": 25, \"steps\": [],\n  \"noAnswer\": { \"kind\": \"voicemail\" }, \"inMeeting\": \"ring\" }, \"own\": false, \"locked\": false,\n  \"workspaceDefault\": { \"mode\": \"working\", … }, \"noAnswerPerson\": null,\n  \"devices\": [{ \"id\": \"computer\", \"kind\": \"computer\", \"name\": \"\", \"usedAt\": null, \"rings\": true }] }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWPhoneCallHandling",
        "tags": [
          "Phone"
        ],
        "summary": "Choose how your calls ring, or null to follow the workspace's default again.",
        "description": "Choose how your calls ring, or `null` to follow the workspace's default again. Steps and ring times are 5 to 120 seconds, up to 5 steps and 3 minutes in all. 403 when an admin locked it. Answers like `GET`.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"handling\": { \"mode\": \"order\", \"othersAfter\": 10, \"ringSeconds\": 25,\n  \"steps\": [{ \"ring\": [\"computer\"], \"seconds\": 10 }, { \"ring\": [\"mobile\", \"desk\"], \"seconds\": 15 }],\n  \"noAnswer\": { \"kind\": \"number\", \"number\": \"+12065550142\", \"seconds\": 20 }, \"inMeeting\": \"ring\" } }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/call-handling/devices/{id}": {
      "put": {
        "operationId": "putApiWorkspacesByWPhoneCallHandlingDevicesById",
        "tags": [
          "Phone"
        ],
        "summary": "Turn one of your devices' ringing on or off: computer, desk, or a phone's id from devices.",
        "description": "Turn one of your devices' ringing on or off: `computer`, `desk`, or a phone's `id` from `devices`. Answers like `GET`.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"rings\": false }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/voicemail": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneVoicemail",
        "tags": [
          "Phone"
        ],
        "summary": "Your voicemail on the phone system from Freesbe, set up for you on its own: ready once your box takes messages, email wh",
        "description": "Your voicemail on the phone system from Freesbe, set up for you on its own: `ready` once your box takes messages, `email` when each voicemail is also emailed to you with the recording attached, the `address` it goes to, and your `greeting`: the `standard` one's words and `mine`, your own (`recordingId`, with `text` and `voice` when typed), or null for the standard one.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"ready\": true, \"email\": false, \"address\": \"maya@northwind.example\",\n  \"greeting\": { \"standard\": \"You've reached Maya Chen at extension 101. Maya isn't available right now. Please leave a message after the tone.\", \"mine\": null } }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "putApiWorkspacesByWPhoneVoicemail",
        "tags": [
          "Phone"
        ],
        "summary": "Have each voicemail emailed to you too (email: true), written in locale (English when left out), or keep them in Freesbe",
        "description": "Have each voicemail emailed to you too (`email: true`), written in `locale` (English when left out), or keep them in Freesbe only. Voicemails always arrive in your DM from Phone and the Voicemail tab. Answers like `GET`.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"email\": true, \"locale\": \"en\" }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/voicemail/greeting": {
      "put": {
        "operationId": "putApiWorkspacesByWPhoneVoicemailGreeting",
        "tags": [
          "Phone"
        ],
        "summary": "Set what callers hear before the beep: typed words read in a voice (text, up to 1,000 characters, and a voice from GET /",
        "description": "Set what callers hear before the beep: typed words read in a voice (`text`, up to 1,000 characters, and a `voice` from `GET /phone/voices`), a recording you uploaded (`recordingId`), or null for the standard greeting. Typed and uploaded greetings count toward the plan's phone greetings a day. Answers like `GET /phone/voicemail`.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample request:\n\n```json\n{ \"greeting\": { \"text\": \"Hi, this is Maya. Leave a message after the tone.\", \"voice\": \"1|en-US|Neural2-F\" } }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWPhoneVoicemailGreeting",
        "tags": [
          "Phone"
        ],
        "summary": "Upload a recording for your greeting: multipart audio, a WAV file of up to 10 MB.",
        "description": "Upload a recording for your greeting: multipart `audio`, a WAV file of up to 10 MB. Answers 201 with its `recordingId` to save with `PUT`.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"recordingId\": \"media_01J…\", \"seconds\": 9 }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "get": {
        "operationId": "getApiWorkspacesByWPhoneVoicemailGreeting",
        "tags": [
          "Phone"
        ],
        "summary": "Hear typed words in a voice before saving them: ?text=…&voice=….",
        "description": "Hear typed words in a voice before saving them: `?text=…&voice=…`. Answers audio/wav.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/voicemail/greeting/audio": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneVoicemailGreetingAudio",
        "tags": [
          "Phone"
        ],
        "summary": "Your greeting as callers hear it now, or ?id= a recording you just uploaded.",
        "description": "Your greeting as callers hear it now, or `?id=` a recording you just uploaded. Answers audio/wav.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/voices": {
      "get": {
        "operationId": "getApiWorkspacesByWPhoneVoices",
        "tags": [
          "Phone"
        ],
        "summary": "The voices a typed greeting can be read in, each with its id, language, name and gender.",
        "description": "The voices a typed greeting can be read in, each with its `id`, `language`, `name` and `gender`.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.\n\nExample answer:\n\n```json\n{ \"voices\": [{ \"id\": \"1|en-US|Neural2-F\", \"language\": \"en-US\", \"name\": \"Neural2-F\", \"gender\": \"female\" }] }\n```",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/phone/emergency/locations/{id}": {
      "delete": {
        "operationId": "deleteApiWorkspacesByWPhoneEmergencyLocationsById",
        "tags": [
          "Phone"
        ],
        "summary": "Remove one of your own places.",
        "description": "Remove one of your own places. If you worked from it, your calls use the workspace's default again. Answers like `GET`.\n\nWho can call it: Members, not guests. Owners, admins and members. Guests get 403 forbidden.",
        "x-freesbe-access": "full-members",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/imports": {
      "get": {
        "operationId": "getApiWorkspacesByWImports",
        "tags": [
          "Slack import"
        ],
        "summary": "Imports, newest first, with their status, phase and counts.",
        "description": "Imports, newest first, with their status, phase and counts.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "postApiWorkspacesByWImports",
        "tags": [
          "Slack import"
        ],
        "summary": "Start an upload: the zip's fileName and size.",
        "description": "Start an upload: the zip's `fileName` and `size`. The answer's `partSize` is how big each part is.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"fileName\": \"Northwind Slack export.zip\", \"size\": 734003200 }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/imports/{id}": {
      "get": {
        "operationId": "getApiWorkspacesByWImportsById",
        "tags": [
          "Slack import"
        ],
        "summary": "One import and its progress.",
        "description": "One import and its progress.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/imports/{id}/parts/{part}": {
      "put": {
        "operationId": "putApiWorkspacesByWImportsByIdPartsByPart",
        "tags": [
          "Slack import"
        ],
        "summary": "Upload part 1, 2, 3… of the zip as raw bytes.",
        "description": "Upload part 1, 2, 3… of the zip as raw bytes. Every part but the last is exactly `partSize`. Answers `partNumber` and `etag`.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "part",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/imports/{id}/start": {
      "post": {
        "operationId": "postApiWorkspacesByWImportsByIdStart",
        "tags": [
          "Slack import"
        ],
        "summary": "The upload is complete: send every part's partNumber and etag, and the import starts.",
        "description": "The upload is complete: send every part's `partNumber` and `etag`, and the import starts.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"parts\": [ { \"partNumber\": 1, \"etag\": \"…\" }, { \"partNumber\": 2, \"etag\": \"…\" } ] }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/imports/{id}/cancel": {
      "post": {
        "operationId": "postApiWorkspacesByWImportsByIdCancel",
        "tags": [
          "Slack import"
        ],
        "summary": "Stop an upload or a running import.",
        "description": "Stop an upload or a running import.\n\nWho can call it: Admins. Workspace owners and admins.",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/workspaces/{w}/claims": {
      "post": {
        "operationId": "postApiWorkspacesByWClaims",
        "tags": [
          "Slack import"
        ],
        "summary": "Sign-in links for imported people who haven't signed in: everyone, or userIds.",
        "description": "Sign-in links for imported people who haven't signed in: everyone, or `userIds`. `email: true` also emails each person theirs.\n\nWho can call it: Admins. Workspace owners and admins.\n\nExample request:\n\n```json\n{ \"email\": true, \"locale\": \"en\" }\n```",
        "x-freesbe-access": "admins",
        "parameters": [
          {
            "name": "w",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/claims/{token}": {
      "get": {
        "operationId": "getApiClaimsByToken",
        "tags": [
          "Slack import"
        ],
        "summary": "What a sign-in link shows: the workspace, the person's name and email from Slack, and whether that email already has an ",
        "description": "What a sign-in link shows: the workspace, the person's name and email from Slack, and whether that email already has an account.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/auth/claim-email": {
      "post": {
        "operationId": "postApiAuthClaimEmail",
        "tags": [
          "Slack import"
        ],
        "summary": "Email a sign-in link if the address belongs to an imported account.",
        "description": "Email a sign-in link if the address belongs to an imported account. Answers 204 either way.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/auth/claim": {
      "post": {
        "operationId": "postApiAuthClaim",
        "tags": [
          "Slack import"
        ],
        "summary": "Take over an imported account: the link's token, a password, and an email when Slack had none.",
        "description": "Take over an imported account: the link's `token`, a `password`, and an `email` when Slack had none. Answers like login.\n\nWho can call it: No token. Anyone can call it, without a token.",
        "x-freesbe-access": "public",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      }
    },
    "/api/claims/{token}/accept": {
      "post": {
        "operationId": "postApiClaimsByTokenAccept",
        "tags": [
          "Slack import"
        ],
        "summary": "Add the imported account's history to the account you're signed in to.",
        "description": "Add the imported account's history to the account you're signed in to.\n\nWho can call it: Signed in. Any valid token. It isn't tied to a workspace, so workspace sign-in rules don't apply.",
        "x-freesbe-access": "signed-in",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "A person's token from POST /api/auth/login with wantToken: true, or an app's bot token (fsb-bot-…)."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "bad_request",
                  "invalid",
                  "unauthorized",
                  "forbidden",
                  "sso_required",
                  "mfa_required",
                  "missing_scope",
                  "not_allowed_token_type",
                  "file_blocked",
                  "unclaimed",
                  "not_found",
                  "conflict",
                  "too_large",
                  "rate_limited",
                  "upstream",
                  "unavailable",
                  "internal"
                ]
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      }
    },
    "responses": {
      "Error": {
        "description": "An error. See https://freesbe.net/docs/api/#errors for every code.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}