openapi: 3.1.0
info:
  title: /dev/null API
  version: 2026.11.09-32315b33
  summary: 'The social network for developers: commits, the log, Remotes.'
  description: |-
    The API behind the /dev/null mobile, Mac and terminal apps, documented from the server source
    ([nunomaduro/dev-null.sh@32315b3](https://github.com/nunomaduro/dev-null.sh/tree/32315b33f52f7c2e1141a0234285f64357acd79a), 2026-11-09).

    There are two APIs under `https://dev-null.sh/api`:

    - **`/v1`**: JSON. The public read endpoints work without auth. Everything else is a request signed with an
      SSH key the user approved as a device.
    - **`/cli`**: plain text. It's what the `devnull commit` script uses, signed with any SSH key on the author's GitHub account.

    ## Quick start

    ```sh
    curl -s https://dev-null.sh/api/v1/users/nunomaduro
    curl -s https://dev-null.sh/api/v1/users/nunomaduro/commits
    curl -s "https://dev-null.sh/api/v1/users/nunomaduro/commits?replies=1"
    curl -s https://dev-null.sh/api/v1/commits/01a1c63c-ae57-70cc-adf3-2298cc075627
    ```

    Public endpoints: `GET /v1/users/{handle}`, `/v1/users/{handle}/commits`, `/v1/commits/{commit}`,
    `/v1/commits/{commit}/related`, `/v1/organizations/{handle}` (and its `/commits` and `/mentions`), `/v1/apps/mac`.

    ## Authentication

    There are no tokens or passwords. Each request is signed with an SSH key.

    ### Signed requests (`/v1`)

    Build this message, with exactly four `\n` separators, so five fields:

    ```
    <unix timestamp>\n<nonce>\n<METHOD>\n<path and query>\n<body>
    ```

    - **timestamp**: Unix seconds, within ±300 s of the server clock.
    - **nonce**: 32 lowercase hex characters (16 random bytes). Each nonce can be used once.
    - **METHOD**: uppercase, e.g. `GET`.
    - **path and query**: the request URI as sent, e.g. `/api/v1/log/latest?cursor=abc`.
    - **body**: the raw JSON body. Use an empty string for requests without one. Signed bodies **must be JSON**;
      form-encoded bodies are rejected.

    Sign it as an SSHSIG with namespace **`devnull-api`**:

    ```sh
    ssh-keygen -Y sign -n devnull-api -f ~/.ssh/id_ed25519 message
    ```

    Then send these headers:

    | header | value |
    |---|---|
    | `X-Devnull-Timestamp` | the timestamp |
    | `X-Devnull-Nonce` | the nonce |
    | `X-SSH-Signature` | the base64 inside the armor, without the `-----BEGIN/END-----` lines or newlines |

    On public endpoints, a request with **any** of these headers has to verify. It never falls back to the guest view.

    ### Requests with files

    Commits, reports and messages can carry images, and messages can carry a voice note. To attach files, send
    `multipart/form-data` with:

    - `payload`: the JSON body, as a file part;
    - `images[]`: up to 3 files, **or** `voice`: one file.

    No other fields are allowed. The signed message gets one more line, before the body: the comma-separated SHA-256 hex
    hashes of the files, in the order attached. The namespace becomes **`devnull-api-images`**:

    ```
    <timestamp>\n<nonce>\n<METHOD>\n<path>\n<sha256[,sha256…]>\n<payload JSON>
    ```

    ### Signing in (approving a key as a device)

    The flow is OAuth-style with PKCE (RFC 7636 / RFC 8252):

    1. Generate an SSH key pair on the device, and a PKCE `code_verifier` (43-128 chars) with
       `code_challenge = BASE64URL(SHA256(code_verifier))`.
    2. Open `https://dev-null.sh/mobile/authorize` in a browser with these query parameters: `fingerprint` (`SHA256:…`
       of the key), `device_name`, `code_challenge`, `code_challenge_method=S256`, `state`, and a `redirect_uri` that
       starts with `devnull://` or is `http://127.0.0.1:<port>` (for CLIs). `app_id` and `app_name` are optional.
       The user signs in with GitHub and approves. The browser is then redirected to `redirect_uri?code=…&state=…`
       (or `error=access_denied`).
    3. Call `POST /v1/devices` with `{"code", "code_verifier"}`, **signed with the new key**. The key is approved, and the
       response is the same as `GET /v1/me`.

    Users can see and revoke their devices at Settings → Devices, or with `GET/DELETE /v1/me/devices`.

    ### CLI commits (`/cli`)

    See `POST /cli/commits`. This flow has no device step: the key just needs to be on the author's GitHub account.

    ## Pagination

    Most lists use **cursor pagination**: `{ data, links, meta }`. Follow `links.next`, or pass `meta.next_cursor` as
    `?cursor=`, until it's `null`. Page sizes are fixed: 20 for commits, 30 for followers/following.
    `GET /v1/scheduled-commits` uses page numbers instead (`?page=`, with `meta.total`).

    Single resources are wrapped as `{ "data": … }`. Some endpoints add top-level keys next to `data`, such as `log` or
    `unread_notifications_count`.

    ## Errors

    | status | body |
    |---|---|
    | 400 / 401 / 403 / 404 / 422 / 429 / 503 from the signed API | `{ "message", "code" }`. See `ApiErrorCode` |
    | 422 validation | `{ "message", "errors": { field: [messages] } }` |
    | others | `{ "message" }` |

    Content that is missing, deleted or hidden from you returns the same 404. Remotes endpoints return 404 when Remotes
    are off for you, or when you can't see the conversation.

    ## Rate limits

    `/v1` allows **120 requests/min per user** for signed requests and **60/min per IP** for unsigned ones. Some actions
    have their own limits too: commits 10/min, searches 15/min, messages 30/min, pings 3/min, follows 30/min,
    stars 60/min, pins 20/min, reports 5/min. Each operation lists the limits that apply to it. Signature failures are
    capped at 60/min per IP. A 429 response includes `Retry-After`.

    ## Conventions

    - Timestamps are ISO 8601 UTC (`2026-11-10T16:26:27Z`).
    - Commits, users, devices and notifications have UUID ids. Messages have integer ids.
    - A user's handle is their GitHub login. Organizations share the `@handle` namespace with users.
    - Commit bodies are limited to 4,000 characters, and links count at their display length.
    - This documentation is unofficial and community-written. The server code is the source of truth.
  contact:
    name: /dev/null
    url: https://dev-null.sh/about
  termsOfService: https://dev-null.sh/terms
servers:
- url: https://dev-null.sh/api
  description: Production
externalDocs:
  description: Server source
  url: https://github.com/nunomaduro/dev-null.sh
tags:
- name: Users
  description: Profiles, their commits, and following, muting and blocking.
- name: Organizations
  description: GitHub organizations' pages.
- name: Commits
  description: Posting, reading, starring, pinning, translating and reporting commits.
- name: Log
  description: The Following / Latest / Trending feeds.
- name: Scheduled commits
  description: Commits queued for later.
- name: Search
  description: People, organizations, commits (semantic), mentions and issues.
- name: Me
  description: The signed-in user.
- name: Settings
  description: Private preferences.
- name: Devices
  description: Signing in, devices and push tokens.
- name: Notifications
  description: 'Grouped notifications: follows, replies, mentions, stars, moderation.'
- name: Remotes
  description: 'Direct messages: inbox, threads, messages and reactions.'
- name: Orgs
  description: Group conversations ("orgs" in Remotes, not GitHub organizations).
- name: Calls
  description: Voice/video calls over WebRTC, signalled by polling.
- name: Apps
  description: Release info for the native apps.
- name: CLI
  description: The plain-text API the `devnull commit` script uses.
paths:
  /v1/users/{handle}:
    get:
      tags:
      - Users
      operationId: getUser
      summary: Get a user's profile
      x-rate-limit:
      - api
      description: |-
        A developer's profile with follower/following/commit counts. Signed requests also get their activity graph, streaks, achievements, pinned commit, and your relationship to them.

        **Auth:** public. Sign the request to get the signed-in view (extra fields marked *signed requests only*). A request with any signature header must be signed correctly.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - {}
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Handle'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/User'
                  bio_profiles:
                    type: object
                    properties: {}
                    description: Handles the bio/company mention that have a page on /dev/null, by lowercase handle.
                    additionalProperties:
                      type: string
                  is_following:
                    type: boolean
                    description: Only in responses to signed requests.
                  follows_you:
                    type: boolean
                    description: Only in responses to signed requests.
                  is_muting:
                    type: boolean
                    description: Only in responses to signed requests.
                  pasteis_received:
                    type: integer
                    description: Only in responses to signed requests.
                  activity:
                    type: object
                    properties:
                      scale:
                        type: string
                        enum:
                        - day
                        - week
                        - month
                        - year
                      buckets:
                        type: array
                        items:
                          type: object
                          properties:
                            date:
                              type: string
                            count:
                              type: integer
                    description: Only in responses to signed requests.
                  streaks:
                    type: object
                    properties:
                      longest:
                        type: integer
                      current:
                        type: integer
                    description: Only in responses to signed requests.
                  achievements:
                    $ref: '#/components/schemas/UserAchievements'
                    description: Only in responses to signed requests.
                  pinned_commit:
                    anyOf:
                    - $ref: '#/components/schemas/Commit'
                    - type: 'null'
                    description: Only in responses to signed requests. The pinned commit is left out of the commits list.
                required:
                - data
                - bio_profiles
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/users/{handle}/block:
    post:
      tags:
      - Users
      operationId: blockUser
      summary: Block a user
      x-rate-limit:
      - api
      description: |-
        Ends follows both ways. Neither of you can follow, reply to, star, or see the other's commits.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Handle'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/User'
                  is_blocking:
                    type: boolean
                    const: true
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Users
      operationId: unblockUser
      summary: Unblock a user
      x-rate-limit:
      - api
      description: |-
        Follows don't come back.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Handle'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/User'
                  is_blocking:
                    type: boolean
                    const: false
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/users/{handle}/commits:
    get:
      tags:
      - Users
      operationId: listUserCommits
      summary: List a user's commits
      x-rate-limit:
      - api
      description: |-
        The profile's Commits tab, or its Replies tab with `replies=1`. Newest first, 20 per page.

        **Auth:** public. Sign the request to get the signed-in view (extra fields marked *signed requests only*). A request with any signature header must be signed correctly.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - {}
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Handle'
      - name: replies
        in: query
        required: false
        description: Replies tab instead of top-level commits.
        schema:
          type: boolean
      - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommitPage'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/users/{handle}/dismiss:
    post:
      tags:
      - Users
      operationId: dismissSuggestedUser
      summary: Dismiss a follow suggestion
      x-rate-limit:
      - api
      description: |-
        "Not interested": they're never suggested again.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Handle'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/users/{handle}/follow:
    post:
      tags:
      - Users
      operationId: followUser
      summary: Follow a user
      x-rate-limit:
      - api
      - follows
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `follows` 30/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Handle'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Users
      operationId: unfollowUser
      summary: Unfollow a user
      x-rate-limit:
      - api
      - follows
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `follows` 30/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Handle'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/users/{handle}/followers:
    get:
      tags:
      - Users
      operationId: listUserFollowers
      summary: List a user's followers
      x-rate-limit:
      - api
      description: |-
        30 per page, with `is_followed` / `follows_you` for each. Members only, so scrapers can't walk the graph.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Handle'
      - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserPage'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/users/{handle}/following:
    get:
      tags:
      - Users
      operationId: listUserFollowing
      summary: List who a user follows
      x-rate-limit:
      - api
      description: |-
        30 per page, with `is_followed` / `follows_you` for each.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Handle'
      - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserPage'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/users/{handle}/following/organizations:
    get:
      tags:
      - Users
      operationId: listUserFollowedOrganizations
      summary: List organizations a user follows
      x-rate-limit:
      - api
      description: |-
        30 per page, newest follow first, with `is_followed` for each.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Handle'
      - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Organization'
                  links:
                    $ref: '#/components/schemas/CursorLinks'
                  meta:
                    $ref: '#/components/schemas/CursorMeta'
                required:
                - data
                - links
                - meta
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/users/{handle}/mute:
    post:
      tags:
      - Users
      operationId: muteUser
      summary: Mute a user
      x-rate-limit:
      - api
      description: |-
        Silent: they aren't told.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Handle'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/User'
                  is_muting:
                    type: boolean
                    const: true
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Users
      operationId: unmuteUser
      summary: Unmute a user
      x-rate-limit:
      - api
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Handle'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/User'
                  is_muting:
                    type: boolean
                    const: false
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/organizations/{handle}:
    get:
      tags:
      - Organizations
      operationId: getOrganization
      summary: Get an organization's page
      x-rate-limit:
      - api
      description: |-
        Organizations share `@handle` URLs with users; ask here when no user has the handle.

        **Auth:** public. Sign the request to get the signed-in view (extra fields marked *signed requests only*). A request with any signature header must be signed correctly.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - {}
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/OrgHandle'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Organization'
                  is_following:
                    type: boolean
                  can_claim:
                    type: boolean
                    description: Signed-in users can claim a page until it has an admin.
                  settings_url:
                    type:
                    - string
                    - 'null'
                    format: uri
                    description: For its admins and members.
                required:
                - data
                - is_following
                - can_claim
                - settings_url
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/organizations/{handle}/claim:
    post:
      tags:
      - Organizations
      operationId: claimOrganization
      summary: Claim an organization's page
      x-rate-limit:
      - api
      - claims
      description: |-
        Become its admin; GitHub must confirm you belong to the organization.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `claims` 10/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/OrgHandle'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/organizations/{handle}/commits:
    get:
      tags:
      - Organizations
      operationId: listOrganizationCommits
      summary: List commits posted as an organization
      x-rate-limit:
      - api
      description: |-
        Top-level, approved, newest first, 20 per page.

        **Auth:** public. Sign the request to get the signed-in view (extra fields marked *signed requests only*). A request with any signature header must be signed correctly.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - {}
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/OrgHandle'
      - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommitPage'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/organizations/{handle}/follow:
    post:
      tags:
      - Organizations
      operationId: followOrganization
      summary: Follow an organization
      x-rate-limit:
      - api
      - follows
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `follows` 30/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/OrgHandle'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Organizations
      operationId: unfollowOrganization
      summary: Unfollow an organization
      x-rate-limit:
      - api
      - follows
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `follows` 30/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/OrgHandle'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/organizations/{handle}/mentions:
    get:
      tags:
      - Organizations
      operationId: listOrganizationMentions
      summary: List commits mentioning an organization
      x-rate-limit:
      - api
      description: |-
        Newest first, 20 per page.

        **Auth:** public. Sign the request to get the signed-in view (extra fields marked *signed requests only*). A request with any signature header must be signed correctly.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - {}
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/OrgHandle'
      - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommitPage'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/commits:
    post:
      tags:
      - Commits
      operationId: createCommit
      summary: Post a commit
      x-rate-limit:
      - api
      - commits
      description: |-
        Posts a commit (or a reply, or a quote). It's pending review unless you're an admin. First-time posters must commit once from the web (`commit_rules_required`).

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `commits` 10 commits/min, however they are posted.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      requestBody:
        required: true
        description: |2-


          Send JSON, or `multipart/form-data` when attaching files. With files, the signature uses the `devnull-api-images` namespace and covers their SHA-256 hashes (see *Requests with files*).
        content:
          application/json:
            schema:
              type: object
              properties:
                body:
                  type: string
                  description: 1-4,000 characters (links count as their display length; each link ≤ 2,048). Optional when
                    images are attached.
                  maxLength: 40000
                author:
                  type:
                  - string
                  - 'null'
                  description: An organization's handle to post as (you must be allowed to).
                parent_id:
                  type:
                  - string
                  - 'null'
                  format: uuid
                  description: Reply to this commit.
                reply_recipients:
                  type: array
                  items:
                    type: string
                  description: Handles the parent was addressed to that this reply also goes to.
                  maxItems: 100
                quoted_commit_id:
                  type:
                  - string
                  - 'null'
                  format: uuid
                  description: Quote this commit. Excludes `parent_id` and `poll`.
                poll:
                  anyOf:
                  - $ref: '#/components/schemas/NewPoll'
                  - type: 'null'
                  description: Excludes `parent_id`, `quoted_commit_id` and images.
                image_descriptions:
                  type: array
                  items:
                    type:
                    - string
                    - 'null'
                    maxLength: 1000
                  description: Alt text, in the order of `images[]`.
                  maxItems: 3
              description: The commit. In multipart requests this object is the `payload` part.
          multipart/form-data:
            schema:
              type: object
              properties:
                payload:
                  type: string
                  description: The JSON body as a file part (`application/json`).
                  contentMediaType: application/json
                images[]:
                  type: array
                  items:
                    type: string
                    contentMediaType: image/*
                  description: JPEG, PNG or WebP; up to 3; 10 MB and 6000×6000 px each.
                  maxItems: 3
              required:
              - payload
            encoding:
              payload:
                contentType: application/json
      responses:
        '201':
          description: Created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommitResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/commits/preview:
    post:
      tags:
      - Commits
      operationId: previewCommit
      summary: Preview a draft
      x-rate-limit:
      - api
      description: |-
        Renders a draft as the commit it would become (emoji shortcodes replaced, segments, excerpt, mentions). Nothing is kept and it doesn't count toward the commit rate limit.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                body:
                  type: string
                  maxLength: 40000
              required:
              - body
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      body:
                        type: string
                      body_segments:
                        type: array
                        items:
                          $ref: '#/components/schemas/Segment'
                      preview_segments:
                        type:
                        - array
                        - 'null'
                        items:
                          $ref: '#/components/schemas/Segment'
                      mentions:
                        type: array
                        items:
                          $ref: '#/components/schemas/Mention'
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/commits/{commit}:
    get:
      tags:
      - Commits
      operationId: getCommit
      summary: Get a commit
      x-rate-limit:
      - api
      description: |-
        Signed requests get the commit as its page shows it to you, with the thread above it (`ancestors`) and who else a reply can go to (`reply_participants`).

        **Auth:** public. Sign the request to get the signed-in view (extra fields marked *signed requests only*). A request with any signature header must be signed correctly.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - {}
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Commit'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Commit'
                  ancestors:
                    type: array
                    items:
                      $ref: '#/components/schemas/CommitOrTombstone'
                    description: Only in responses to signed requests. Oldest first.
                  reply_participants:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          format: uuid
                        handle:
                          type: string
                    description: Only in responses to signed requests.
                required:
                - data
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Commits
      operationId: deleteCommit
      summary: Delete your commit
      x-rate-limit:
      - api
      description: |-
        Can be undone for 30 seconds with `POST /v1/commits/{commit}/restoration`.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Commit'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/commits/{commit}/pasteis:
    post:
      tags:
      - Commits
      operationId: givePastel
      summary: Give a pastel
      x-rate-limit:
      - api
      - pasteis
      description: |-
        Gives one pastel from your daily allowance. With none left: `pasteis_exhausted` (422).

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `pasteis` 60/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Commit'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Commit'
                  pasteis_remaining:
                    type: integer
                  pasteis_resets_at:
                    type: string
                    format: date-time
                  author_pasteis_received:
                    type:
                    - integer
                    - 'null'
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/commits/{commit}/pin:
    put:
      tags:
      - Commits
      operationId: pinCommit
      summary: Pin your commit to your profile
      x-rate-limit:
      - api
      - pins
      description: |-
        Replaces the commit pinned before.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `pins` 20/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Commit'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommitResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Commits
      operationId: unpinCommit
      summary: Unpin your commit
      x-rate-limit:
      - api
      - pins
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `pins` 20/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Commit'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommitResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/commits/{commit}/poll/votes:
    post:
      tags:
      - Commits
      operationId: voteOnPoll
      summary: Vote on a poll
      x-rate-limit:
      - api
      description: |-
        Results show once you've voted.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Commit'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                option:
                  type: string
                  description: A `poll.options[].id`.
                  format: uuid
              required:
              - option
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommitResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/commits/{commit}/related:
    get:
      tags:
      - Commits
      operationId: listRelatedCommits
      summary: List related commits
      x-rate-limit:
      - api
      description: |-
        Commits nearest in meaning, by vector similarity and a relevance check.

        **Auth:** public. Sign the request to get the signed-in view (extra fields marked *signed requests only*). A request with any signature header must be signed correctly.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - {}
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Commit'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Commit'
                required:
                - data
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/commits/{commit}/replies:
    get:
      tags:
      - Commits
      operationId: listCommitReplies
      summary: List replies
      x-rate-limit:
      - api
      description: |-
        Works on deleted commits too, so a tombstone's thread can still be read.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Commit'
      - name: newest
        in: query
        required: false
        description: Newest first instead of oldest first.
        schema:
          type: boolean
      - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommitPage'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/commits/{commit}/reports:
    post:
      tags:
      - Commits
      operationId: reportCommit
      summary: Report a commit
      x-rate-limit:
      - api
      - commit-reports
      description: |-
        Reports are private. Reporting the same commit again keeps the first report.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `commit-reports` 5/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Commit'
      requestBody:
        required: true
        description: |2-


          Send JSON, or `multipart/form-data` when attaching files. With files, the signature uses the `devnull-api-images` namespace and covers their SHA-256 hashes (see *Requests with files*).
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
                  enum:
                  - spam
                  - harassment
                  - unsafe
                  - other
                details:
                  type:
                  - string
                  - 'null'
                  maxLength: 500
                image_descriptions:
                  type: array
                  items:
                    type:
                    - string
                    - 'null'
                    maxLength: 1000
                  maxItems: 3
              required:
              - reason
          multipart/form-data:
            schema:
              type: object
              properties:
                payload:
                  type: string
                  description: The JSON body as a file part (`application/json`).
                  contentMediaType: application/json
                images[]:
                  type: array
                  items:
                    type: string
                    contentMediaType: image/*
                  description: 'Screenshots: JPEG, PNG or WebP; up to 3.'
                  maxItems: 3
              required:
              - payload
            encoding:
              payload:
                contentType: application/json
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/commits/{commit}/restoration:
    post:
      tags:
      - Commits
      operationId: restoreCommit
      summary: Undo a deletion
      x-rate-limit:
      - api
      description: |-
        Within the 30-second undo window.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Commit'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommitResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/commits/{commit}/star:
    post:
      tags:
      - Commits
      operationId: starCommit
      summary: Star a commit
      x-rate-limit:
      - api
      - stars
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `stars` 60/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Commit'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommitResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Commits
      operationId: unstarCommit
      summary: Unstar a commit
      x-rate-limit:
      - api
      - stars
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `stars` 60/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Commit'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommitResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/commits/{commit}/stars:
    get:
      tags:
      - Commits
      operationId: listCommitStargazers
      summary: List who starred a commit
      x-rate-limit:
      - api
      description: |-
        Newest first, 20 per page. People across a block are left out.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Commit'
      - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserPage'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/commits/{commit}/translation:
    post:
      tags:
      - Commits
      operationId: translateCommit
      summary: Translate a commit
      x-rate-limit:
      - api
      - translations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `translations` 10/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Commit'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                language:
                  type: string
                  description: One of `GET /v1/me/settings` → `translation_languages[].code`.
                  example: es
              required:
              - language
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  translation:
                    anyOf:
                    - $ref: '#/components/schemas/CommitTranslation'
                    - type: 'null'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
  /v1/starred:
    get:
      tags:
      - Commits
      operationId: listStarredCommits
      summary: List your starred commits
      x-rate-limit:
      - api
      description: |-
        Private to you. 20 per page.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommitPage'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/log/{log}:
    get:
      tags:
      - Log
      operationId: getLog
      summary: Read the log (feed)
      x-rate-limit:
      - api
      description: |-
        Following, Latest or Trending, 20 commits per page. With `since`, also counts commits newer than that one (`new_commits_count`; never on Trending, which is ranked). An empty Following log comes with `suggestions`.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - name: log
        in: path
        required: true
        description: Which log.
        schema:
          type: string
          enum:
          - following
          - latest
          - trending
        example: latest
      - $ref: '#/components/parameters/Cursor'
      - name: since
        in: query
        required: false
        description: Id of the newest commit you already have.
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/CommitOrTombstone'
                  links:
                    $ref: '#/components/schemas/CursorLinks'
                  meta:
                    $ref: '#/components/schemas/CursorMeta'
                  log:
                    type: string
                    enum:
                    - following
                    - latest
                    - trending
                  is_ranked:
                    type: boolean
                    description: True for Trending.
                  new_commits_count:
                    type: integer
                    description: With `since` only.
                  suggestions:
                    type: array
                    items:
                      $ref: '#/components/schemas/Commit'
                required:
                - data
                - links
                - meta
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/scheduled-commits:
    get:
      tags:
      - Scheduled commits
      operationId: listScheduledCommits
      summary: List your scheduled commits
      x-rate-limit:
      - api
      description: |-
        20 per page (page-numbered, not cursor).

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - name: page
        in: query
        required: false
        description: Page number.
        schema:
          type: integer
          minimum: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ScheduledCommit'
                  links:
                    $ref: '#/components/schemas/PageLinks'
                  meta:
                    $ref: '#/components/schemas/PageMeta'
                required:
                - data
                - links
                - meta
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    post:
      tags:
      - Scheduled commits
      operationId: scheduleCommit
      summary: Schedule a commit
      x-rate-limit:
      - api
      - commits
      description: |-
        Only you see it until it's submitted. Can't reply to or quote a commit.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `commits` 10 commits/min, however they are posted.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      requestBody:
        required: true
        description: |2-


          Send JSON, or `multipart/form-data` when attaching files. With files, the signature uses the `devnull-api-images` namespace and covers their SHA-256 hashes (see *Requests with files*).
        content:
          application/json:
            schema:
              type: object
              properties:
                body:
                  type: string
                  maxLength: 40000
                author:
                  type:
                  - string
                  - 'null'
                  description: Organization handle to post as.
                scheduled_at:
                  type: string
                  description: ISO 8601 with offset, in the future, at most 30 days ahead.
                  format: date-time
                  example: '2026-11-12T09:00:00-06:00'
                link_preview_url:
                  type:
                  - string
                  - 'null'
                  description: One of the URLs in `body`, to show as the card.
                poll:
                  anyOf:
                  - $ref: '#/components/schemas/NewPoll'
                  - type: 'null'
                image_descriptions:
                  type: array
                  items:
                    type:
                    - string
                    - 'null'
                    maxLength: 1000
                  maxItems: 3
              required:
              - scheduled_at
          multipart/form-data:
            schema:
              type: object
              properties:
                payload:
                  type: string
                  description: The JSON body as a file part (`application/json`).
                  contentMediaType: application/json
                images[]:
                  type: array
                  items:
                    type: string
                    contentMediaType: image/*
                  description: JPEG, PNG or WebP; up to 3.
                  maxItems: 3
              required:
              - payload
            encoding:
              payload:
                contentType: application/json
      responses:
        '201':
          description: Created.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/ScheduledCommit'
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/scheduled-commits/{scheduledCommit}:
    delete:
      tags:
      - Scheduled commits
      operationId: cancelScheduledCommit
      summary: Cancel a scheduled commit
      x-rate-limit:
      - api
      description: |-
        409 when it was already submitted or canceled.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - name: scheduledCommit
        in: path
        required: true
        description: Scheduled commit id.
        schema:
          type: string
          format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/scheduled-commits/{scheduledCommit}/submission:
    post:
      tags:
      - Scheduled commits
      operationId: submitScheduledCommit
      summary: Post a scheduled commit now
      x-rate-limit:
      - api
      - commits
      description: |-
        Goes through the usual review. 409 when already submitted or canceled.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `commits` 10 commits/min, however they are posted.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - name: scheduledCommit
        in: path
        required: true
        description: Scheduled commit id.
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/ScheduledCommit'
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/search/commits:
    get:
      tags:
      - Search
      operationId: searchCommits
      summary: Search commits by meaning
      x-rate-limit:
      - api
      - search
      description: |-
        Semantic search, closest first; may return fewer than `limit` once irrelevant results are dropped.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `search` 15/min (each search costs an embedding).
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - name: q
        in: query
        required: true
        description: What to look for.
        schema:
          type: string
          minLength: 3
          maxLength: 100
        example: cursor pagination
      - name: limit
        in: query
        required: false
        description: Max results.
        schema:
          type: integer
          minimum: 1
          maximum: 100
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Commit'
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/search/issues:
    get:
      tags:
      - Search
      operationId: suggestIssue
      summary: Look up a /dev/null GitHub issue
      x-rate-limit:
      - api
      - issue-suggestions
      description: |-
        For `#123` references in the composer.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `issue-suggestions` 30/min and 300/day.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - name: q
        in: query
        required: true
        description: Issue number.
        schema:
          type: string
          pattern: ^[1-9][0-9]{0,9}$
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  issue:
                    anyOf:
                    - type: object
                      properties:
                        number:
                          type: integer
                        title:
                          type: string
                        url:
                          type: string
                          format: uri
                    - type: 'null'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/search/mentions:
    get:
      tags:
      - Search
      operationId: suggestMentions
      summary: Suggest @mentions
      x-rate-limit:
      - api
      - people
      description: |-
        People (and, outside orgs, organizations) the composer suggests for an @mention.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `people` 120/min (shared by people search, mention suggestions and hover cards).
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - name: q
        in: query
        required: false
        description: What was typed after `@`.
        schema:
          type: string
          maxLength: 100
      - name: org
        in: query
        required: false
        description: Composing in this org (excludes `reply`/`quote`).
        schema:
          type: string
          format: uuid
      - name: reply
        in: query
        required: false
        description: Composing a reply to this commit.
        schema:
          type: string
          format: uuid
      - name: quote
        in: query
        required: false
        description: Composing a quote of this commit.
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/User'
                  organizations:
                    type: array
                    items:
                      $ref: '#/components/schemas/Organization'
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/search/profiles:
    get:
      tags:
      - Search
      operationId: searchProfiles
      summary: Search people and organizations
      x-rate-limit:
      - api
      - people
      description: |-
        By name or handle. People you muted or blocked (or who blocked you) are left out; organizations only if they already have a page.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `people` 120/min (shared by people search, mention suggestions and hover cards).
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - name: q
        in: query
        required: false
        description: Search term.
        schema:
          type: string
          maxLength: 100
        example: nuno
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  users:
                    type: array
                    items:
                      $ref: '#/components/schemas/User'
                  organizations:
                    type: array
                    items:
                      $ref: '#/components/schemas/Organization'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/search/users:
    get:
      tags:
      - Search
      operationId: searchUsers
      summary: Search people (deprecated)
      x-rate-limit:
      - api
      - people
      description: |-
        Use `GET /v1/search/profiles`. Responds with `Deprecation: true` and a `Link: rel="successor-version"` header.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `people` 120/min (shared by people search, mention suggestions and hover cards).
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - name: q
        in: query
        required: false
        description: Search term.
        schema:
          type: string
          maxLength: 100
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/User'
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
      deprecated: true
  /v1/broadcasting/auth:
    post:
      tags:
      - Me
      operationId: authorizeBroadcast
      summary: Authorize a live-updates channel
      x-rate-limit:
      - api
      - broadcast-authorizations
      description: |-
        Joins your private WebSocket channel (Pusher protocol), signed like any other request.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `broadcast-authorizations` 60/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                socket_id:
                  type: string
                  pattern: ^\d+\.\d+$
                  example: '123456.7890123'
                channel_name:
                  type: string
                  maxLength: 200
              required:
              - socket_id
              - channel_name
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  auth:
                    type: string
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me:
    get:
      tags:
      - Me
      operationId: getCurrentUser
      summary: Get the signed-in user
      x-rate-limit:
      - api
      description: |-
        Your profile plus private settings and the Notifications unread count.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CurrentUserResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Me
      operationId: deleteAccount
      summary: Delete your account
      x-rate-limit:
      - api
      description: |-
        Deletes the account the way the web does, with its devices, so the signing key stops working. Banned users can still do this.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/blocked:
    get:
      tags:
      - Me
      operationId: listBlockedUsers
      summary: List blocked users
      x-rate-limit:
      - api
      description: |-
        Last blocked first, 20 per page.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserPage'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/github:
    put:
      tags:
      - Me
      operationId: syncFromGitHub
      summary: Sync profile from GitHub
      x-rate-limit:
      - api
      - profile-syncs
      description: |-
        Mirrors your GitHub profile again. `github_sync_failed` (503) when GitHub can't be reached.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `profile-syncs` limited per user.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CurrentUserResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
  /v1/me/lane:
    put:
      tags:
      - Me
      operationId: updateLane
      summary: Set your profile color
      x-rate-limit:
      - api
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                lane:
                  type:
                  - integer
                  - 'null'
                  minimum: 0
                  maximum: 5
                  description: Null for Automatic. Required (may be null).
                color:
                  type:
                  - string
                  - 'null'
                  pattern: ^#[0-9a-f]{6}$
                  description: Custom color; excludes `lane`.
              required:
              - lane
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CurrentUserResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/live:
    put:
      tags:
      - Me
      operationId: goLive
      summary: Go live
      x-rate-limit:
      - api
      description: |-
        Marks you live on a YouTube or Twitch stream for 1-12 hours.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                url:
                  type: string
                  description: A YouTube or Twitch stream URL.
                  format: uri
                  maxLength: 2048
                hours:
                  type: integer
                  minimum: 1
                  maximum: 12
              required:
              - url
              - hours
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CurrentUserResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Me
      operationId: endLive
      summary: End your stream early
      x-rate-limit:
      - api
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CurrentUserResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/live-following:
    get:
      tags:
      - Me
      operationId: listLiveFollowing
      summary: Who you follow that's live now
      x-rate-limit:
      - api
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/User'
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/muted:
    get:
      tags:
      - Me
      operationId: listMutedUsers
      summary: List muted users
      x-rate-limit:
      - api
      description: |-
        Last muted first, 20 per page.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserPage'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/pasteis-mode:
    put:
      tags:
      - Me
      operationId: updatePasteisMode
      summary: Turn pastéis mode on or off
      x-rate-limit:
      - api
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                enabled:
                  type: boolean
              required:
              - enabled
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CurrentUserResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/suggested-users:
    get:
      tags:
      - Me
      operationId: listSuggestedUsers
      summary: Who to follow
      x-rate-limit:
      - api
      description: |-
        Three suggestions plus three spares. Each `round` is the next page of the day's picks. Pass `handle` or `commit_id` for suggestions shown beside a profile or commit.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - name: round
        in: query
        required: false
        description: 0, 1, 2… for refreshes.
        schema:
          type: integer
          minimum: 0
      - name: handle
        in: query
        required: false
        description: Suggest beside this profile.
        schema:
          type: string
      - name: commit_id
        in: query
        required: false
        description: Suggest beside this commit (excludes `handle`).
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/User'
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/terms:
    put:
      tags:
      - Me
      operationId: acceptTerms
      summary: Accept the terms
      x-rate-limit:
      - api
      description: |-
        Send the version you showed the person; only the current version is accepted.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                version:
                  type: string
                  description: Must equal `terms_version` from `GET /v1/me`.
              required:
              - version
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CurrentUserResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/automatic-translation:
    put:
      tags:
      - Settings
      operationId: updateAutomaticTranslation
      summary: Turn automatic translation on or off
      x-rate-limit:
      - api
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                enabled:
                  type: boolean
              required:
              - enabled
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CurrentUserResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/push-preferences:
    put:
      tags:
      - Settings
      operationId: updatePushPreferences
      summary: Choose what gets pushed to your phones
      x-rate-limit:
      - api
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PushPreferences'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/PushPreferences'
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/remote-preferences:
    put:
      tags:
      - Settings
      operationId: updateRemotePreferences
      summary: Set who can message you
      x-rate-limit:
      - api
      - conversations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                from:
                  type: string
                  description: '`everyone` only when the site allows it (`remotes.everyone`).'
                  enum:
                  - following
                  - everyone
                pull_receipts:
                  type: boolean
                  description: Share read receipts.
              required:
              - from
              - pull_receipts
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CurrentUserResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/remotes:
    put:
      tags:
      - Settings
      operationId: updateRemotesEnabled
      summary: Turn Remotes (DMs) on or off
      x-rate-limit:
      - api
      description: |-
        While off, nobody can message you and conversations wait for you to come back.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                enabled:
                  type: boolean
              required:
              - enabled
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CurrentUserResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/settings:
    get:
      tags:
      - Settings
      operationId: getSettings
      summary: Get your settings
      x-rate-limit:
      - api
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Settings'
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/timezone:
    put:
      tags:
      - Settings
      operationId: updateTimezone
      summary: Set your timezone
      x-rate-limit:
      - api
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                timezone:
                  type:
                  - string
                  - 'null'
                  description: IANA name, or null. Required (may be null).
                  example: America/Mexico_City
                show_local_time:
                  type:
                  - boolean
                  - 'null'
              required:
              - timezone
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CurrentUserResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/translation-language:
    put:
      tags:
      - Settings
      operationId: updateTranslationLanguage
      summary: Set the translation language
      x-rate-limit:
      - api
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                translation_language:
                  type:
                  - string
                  - 'null'
                  description: A supported code, or null to follow the device. Required (may be null).
              required:
              - translation_language
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CurrentUserResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/devices:
    post:
      tags:
      - Devices
      operationId: redeemDeviceCode
      summary: Redeem a sign-in code for a device
      x-rate-limit:
      - devices
      description: |-
        Step 3 of *Signing in*. Approves the key that signed this request as a device for the user who approved the app on the web, and answers like `GET /v1/me`. Any problem with the code is the same `invalid_grant` (400).

        **Auth:** signed with the key being approved; the key need not be approved yet.

        **Rate limits:** `devices` 60/min per IP.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                code:
                  type: string
                  description: The `code` the web redirected back with.
                  maxLength: 255
                code_verifier:
                  type: string
                  description: PKCE verifier (43-128 chars of `A-Z a-z 0-9 . _ ~ -`).
                  pattern: ^[A-Za-z0-9._~-]{43,128}$
                terms_accepted:
                  type: boolean
                  description: Also record acceptance of the current terms.
              required:
              - code
              - code_verifier
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CurrentUserResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/devices:
    get:
      tags:
      - Devices
      operationId: listDevices
      summary: List your devices
      x-rate-limit:
      - api
      description: |-
        Newest approval first.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Device'
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/devices/{device}:
    delete:
      tags:
      - Devices
      operationId: revokeDevice
      summary: Revoke a device
      x-rate-limit:
      - api
      description: |-
        Revoking the device that signed this request signs the app out on it.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - name: device
        in: path
        required: true
        description: Device id.
        schema:
          type: string
          format: uuid
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/push-token:
    put:
      tags:
      - Devices
      operationId: updatePushToken
      summary: Register this device's push token
      x-rate-limit:
      - api
      description: |-
        For the device that signs the request; replaces its previous token.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                token:
                  type: string
                  maxLength: 4096
                platform:
                  type: string
                  enum:
                  - ios
                  - android
              required:
              - token
              - platform
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Devices
      operationId: deletePushToken
      summary: Stop pushing to this device
      x-rate-limit:
      - api
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/me/web-session:
    post:
      tags:
      - Devices
      operationId: createWebSession
      summary: Create a web session for an in-app web view
      x-rate-limit:
      - api
      description: |-
        Signs in the web session whose cookies this response sets, for the app's web view.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  onboarded:
                    type: boolean
          headers:
            Set-Cookie:
              schema:
                type: string
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/notifications:
    get:
      tags:
      - Notifications
      operationId: listNotifications
      summary: List notifications
      x-rate-limit:
      - api
      description: |-
        Grouped as on the web. **Listing marks every notification as read**, whatever the filter; `read_at` says when, so the ones read since your last `read_at` are the new ones.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - name: type
        in: query
        required: false
        description: '`all`, `none`, or a comma list of `replies`, `quotes`, `stars`, `mentions`, `follows`, `moderation`.
          Remembered for next time.'
        schema:
          type: string
          pattern: ^(?:all|none|(?:replies|quotes|stars|mentions|follows|moderation)(?:,(?:replies|quotes|stars|mentions|follows|moderation))*)$
        example: replies,mentions
      - name: through
        in: query
        required: false
        description: Page through notifications up to this time.
        schema:
          type: string
          format: date-time
      - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Notification'
                  links:
                    $ref: '#/components/schemas/CursorLinks'
                  meta:
                    $ref: '#/components/schemas/CursorMeta'
                  filters:
                    type: object
                    properties:
                      type:
                        type: string
                  read_at:
                    type: string
                    format: date-time
                required:
                - data
                - links
                - meta
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/notifications/{notification}/group:
    get:
      tags:
      - Notifications
      operationId: listNotificationGroup
      summary: Expand a notification group
      x-rate-limit:
      - api
      description: |-
        Every notification in the group, newest first, 20 per page. Marks nothing as read.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - name: notification
        in: path
        required: true
        description: Any notification id in the group.
        schema:
          type: string
          format: uuid
      - name: type
        in: query
        required: false
        description: '`all`, `none`, or a comma list of `replies`, `quotes`, `stars`, `mentions`, `follows`, `moderation`.
          Remembered for next time.'
        schema:
          type: string
          pattern: ^(?:all|none|(?:replies|quotes|stars|mentions|follows|moderation)(?:,(?:replies|quotes|stars|mentions|follows|moderation))*)$
        example: replies,mentions
      - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Notification'
                  links:
                    $ref: '#/components/schemas/CursorLinks'
                  meta:
                    $ref: '#/components/schemas/CursorMeta'
                required:
                - data
                - links
                - meta
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes:
    get:
      tags:
      - Remotes
      operationId: listConversations
      summary: List conversations (inbox)
      x-rate-limit:
      - api
      - conversations
      description: |-
        Pinned first, then newest. Page with `before`.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - name: tab
        in: query
        required: false
        description: '`fetched` (message requests) only when the site enables requests.'
        schema:
          type: string
          enum:
          - open
          - fetched
          - stashed
      - name: q
        in: query
        required: false
        description: Filter by name or handle.
        schema:
          type: string
          maxLength: 100
      - name: before
        in: query
        required: false
        description: Continue after this conversation id.
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Conversation'
                  has_more:
                    type: boolean
                  unread_count:
                    type: integer
                  requests_count:
                    type: integer
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/@{partner}/archive:
    post:
      tags:
      - Remotes
      operationId: stashConversation
      summary: Stash a conversation
      x-rate-limit:
      - api
      - conversations
      description: |-
        For you only; it pops back into Open when either of you writes.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Partner'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Remotes
      operationId: unstashConversation
      summary: Unstash a conversation
      x-rate-limit:
      - api
      - conversations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Partner'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/@{partner}/drop:
    post:
      tags:
      - Remotes
      operationId: dropRequest
      summary: Drop a message request
      x-rate-limit:
      - api
      - conversations
      description: |-
        Drops it for good without telling the sender.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Partner'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/@{partner}/merge:
    post:
      tags:
      - Remotes
      operationId: acceptRequest
      summary: Accept a message request
      x-rate-limit:
      - api
      - conversations
      description: |-
        Merges a fetched request into your open conversations so you can reply.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Partner'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/@{partner}/messages:
    get:
      tags:
      - Remotes
      operationId: getDirectThread
      summary: Read a conversation
      x-rate-limit:
      - api
      - conversations
      description: |-
        The latest page, the page before a message, or everything after one plus reaction changes (polling). Someone you haven't talked to yet has an empty thread whose `access` says whether you can write first.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Partner'
      - name: after
        in: query
        required: false
        description: 'Poll: only messages after this id.'
        schema:
          type: integer
          minimum: 0
      - name: before
        in: query
        required: false
        description: Load the page before this message id.
        schema:
          type: integer
          minimum: 1
      - name: reactions_after
        in: query
        required: false
        description: 'Poll: reaction changes since this `reactions_version`.'
        schema:
          type: integer
          minimum: 0
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/DirectThread'
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    post:
      tags:
      - Remotes
      operationId: sendDirectMessage
      summary: Send a message
      x-rate-limit:
      - api
      - messages
      description: |-
        Starts the conversation if it's the first message.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `messages` 30/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Partner'
      requestBody:
        required: true
        description: |2-


          Send JSON, or `multipart/form-data` when attaching files. With files, the signature uses the `devnull-api-images` namespace and covers their SHA-256 hashes (see *Requests with files*).
        content:
          application/json:
            schema:
              type: object
              properties:
                body:
                  type:
                  - string
                  - 'null'
                  maxLength: 2000
                  description: Required unless images or a voice note are attached.
                client_id:
                  type: string
                  description: A UUID you generate. Resending the same one returns the existing message (200).
                  format: uuid
                reply_to_id:
                  type:
                  - integer
                  - 'null'
                link_preview_url:
                  type:
                  - string
                  - 'null'
                  description: One of the URLs in `body`.
                image_descriptions:
                  type: array
                  items:
                    type:
                    - string
                    - 'null'
                    maxLength: 1000
                  maxItems: 3
                voice_waveform:
                  type: array
                  items:
                    type: integer
                    minimum: 0
                    maximum: 100
                  description: 'Required with `voice`: exactly 48 bars.'
                  minItems: 48
                  maxItems: 48
              required:
              - client_id
              description: The message. In multipart requests this object is the `payload` part.
          multipart/form-data:
            schema:
              type: object
              properties:
                payload:
                  type: string
                  description: The JSON body as a file part (`application/json`).
                  contentMediaType: application/json
                images[]:
                  type: array
                  items:
                    type: string
                    contentMediaType: image/*
                  description: JPEG, PNG or WebP; up to 3; 10 MB each.
                  maxItems: 3
                voice:
                  type: string
                  description: A voice note (0.5-61 s, under ~1.9 MB). Excludes `body` and images.
                  contentMediaType: audio/*
              required:
              - payload
            encoding:
              payload:
                contentType: application/json
      responses:
        '200':
          description: 'Retry with a known `client_id`: the existing message.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
        '201':
          description: Created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/@{partner}/mute:
    put:
      tags:
      - Remotes
      operationId: muteConversation
      summary: Mute or unmute a conversation
      x-rate-limit:
      - api
      - conversations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Partner'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                duration:
                  type: string
                  description: '`off` unmutes.'
                  enum:
                  - hour
                  - tomorrow
                  - week
                  - forever
                  - 'off'
              required:
              - duration
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  muted_until_at:
                    type:
                    - string
                    - 'null'
                    format: date-time
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/@{partner}/pin:
    put:
      tags:
      - Remotes
      operationId: pinConversation
      summary: Pin or unpin a conversation
      x-rate-limit:
      - api
      - conversations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Partner'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                pinned:
                  type: boolean
              required:
              - pinned
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  pinned_at:
                    type:
                    - string
                    - 'null'
                    format: date-time
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/@{partner}/ping:
    post:
      tags:
      - Remotes
      operationId: pingPartner
      summary: Ping (nudge) the partner
      x-rate-limit:
      - api
      - pings
      description: |-
        Only in a conversation that has started.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `pings` 3/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Partner'
      responses:
        '201':
          description: Created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/@{partner}/read:
    put:
      tags:
      - Remotes
      operationId: markDirectRead
      summary: Mark read through a message
      x-rate-limit:
      - api
      - conversations
      description: |-
        Only moves forward.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Partner'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                through:
                  type: integer
                  description: Message id.
                  minimum: 0
              required:
              - through
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/@{partner}/typing:
    put:
      tags:
      - Remotes
      operationId: sendDirectTyping
      summary: Say you're typing
      x-rate-limit:
      - api
      - conversations
      description: |-
        Lasts a few seconds; send every few seconds while composing.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Partner'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/candidates:
    get:
      tags:
      - Remotes
      operationId: listRemoteCandidates
      summary: Find people to message or add
      x-rate-limit:
      - api
      - conversations
      description: |-
        Each candidate comes with the `reason` they can't be picked, if any.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - name: q
        in: query
        required: false
        description: Search term.
        schema:
          type: string
          maxLength: 100
      - name: org
        in: query
        required: false
        description: Adding to this org.
        schema:
          type: string
          format: uuid
      - name: for
        in: query
        required: false
        description: Which picker.
        schema:
          type: string
          enum:
          - remote
          - org
          - share
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  candidates:
                    type: array
                    items:
                      type: object
                      properties:
                        user:
                          $ref: '#/components/schemas/User'
                        reason:
                          type:
                          - string
                          - 'null'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/images/{image}:
    get:
      tags:
      - Remotes
      operationId: getMessageImage
      summary: Download a message image
      description: Use the `url` from a message as is. Signed for you and valid until midnight UTC two days out, so it can
        be cached.
      security: []
      parameters:
      - name: image
        in: path
        required: true
        description: Message image id.
        schema:
          type: string
          format: uuid
      - name: expires
        in: query
        required: true
        description: Unix timestamp the URL expires at.
        schema:
          type: integer
      - name: user
        in: query
        required: true
        description: The user the URL was signed for.
        schema:
          type: string
          format: uuid
      - name: signature
        in: query
        required: true
        description: URL signature.
        schema:
          type: string
      responses:
        '200':
          description: The image.
          content:
            image/webp:
              schema:
                type: string
                contentMediaType: image/webp
        '403':
          description: Invalid or expired signature.
        '404':
          $ref: '#/components/responses/NotFound'
  /v1/remotes/messages/{message}/link-preview:
    get:
      tags:
      - Remotes
      operationId: getMessageLinkPreview
      summary: Get a message's link card
      x-rate-limit:
      - api
      - conversations
      description: |-
        Ask again while `is_pending` is true.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Message'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  link_preview:
                    anyOf:
                    - $ref: '#/components/schemas/LinkPreview'
                    - type: 'null'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/messages/{message}/pin:
    put:
      tags:
      - Remotes
      operationId: pinMessage
      summary: Pin a message in an org
      x-rate-limit:
      - api
      - pins
      description: |-
        Maintainers only. Answers with the org's pinned messages.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `pins` 20/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Message'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  pinned:
                    type: array
                    items:
                      $ref: '#/components/schemas/Message'
                  reactions_version:
                    type: integer
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Remotes
      operationId: unpinMessage
      summary: Unpin a message in an org
      x-rate-limit:
      - api
      - pins
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `pins` 20/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Message'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  pinned:
                    type: array
                    items:
                      $ref: '#/components/schemas/Message'
                  reactions_version:
                    type: integer
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/messages/{message}/reactions:
    post:
      tags:
      - Remotes
      operationId: addReaction
      summary: React to a message
      x-rate-limit:
      - api
      - conversations
      description: |-
        Idempotent per emoji. Events can't be reacted to.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Message'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                emoji:
                  type: string
                  description: A supported emoji.
                  example: 🔥
              required:
              - emoji
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  reactions:
                    type: array
                    items:
                      $ref: '#/components/schemas/Reaction'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Remotes
      operationId: removeReaction
      summary: Remove a reaction
      x-rate-limit:
      - api
      - conversations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Message'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                emoji:
                  type: string
                  maxLength: 32
              required:
              - emoji
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  reactions:
                    type: array
                    items:
                      $ref: '#/components/schemas/Reaction'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/reactions:
    get:
      tags:
      - Remotes
      operationId: listReactionUsage
      summary: Your most-used reaction emoji
      x-rate-limit:
      - api
      - conversations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  usage:
                    type: array
                    items:
                      type: object
                      properties:
                        emoji:
                          type: string
                        count:
                          type: integer
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/voices/{voice}:
    get:
      tags:
      - Remotes
      operationId: getMessageVoice
      summary: Download a voice note
      description: Use the `url` from a message as is.
      security: []
      parameters:
      - name: voice
        in: path
        required: true
        description: Voice note id.
        schema:
          type: string
          format: uuid
      - name: expires
        in: query
        required: true
        description: Unix timestamp the URL expires at.
        schema:
          type: integer
      - name: user
        in: query
        required: true
        description: The user the URL was signed for.
        schema:
          type: string
          format: uuid
      - name: signature
        in: query
        required: true
        description: URL signature.
        schema:
          type: string
      responses:
        '200':
          description: The audio (WebM/Opus or WAV).
          content:
            audio/*:
              schema:
                type: string
                contentMediaType: audio/*
        '403':
          description: Invalid or expired signature.
        '404':
          $ref: '#/components/responses/NotFound'
  /v1/remotes/orgs:
    post:
      tags:
      - Orgs
      operationId: createOrg
      summary: Start an org
      x-rate-limit:
      - api
      - conversations
      - messages
      description: |-
        You become its maintainer; everyone you add contributes. Up to 100 members.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min; `messages` 30/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type:
                  - string
                  - 'null'
                  maxLength: 60
                members:
                  type: array
                  items:
                    type: string
                  description: Handles of /dev/null users.
                  minItems: 1
                  maxItems: 99
              required:
              - members
      responses:
        '201':
          description: Created.
          content:
            application/json:
              schema:
                type: object
                properties:
                  org:
                    type: object
                    properties:
                      id:
                        type: string
                        format: uuid
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/orgs/{org}:
    put:
      tags:
      - Orgs
      operationId: renameOrg
      summary: Rename an org
      x-rate-limit:
      - api
      - conversations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Org'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type:
                  - string
                  - 'null'
                  maxLength: 60
                  description: Null removes the name.
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/orgs/{org}/archive:
    post:
      tags:
      - Orgs
      operationId: stashOrg
      summary: Stash an org
      x-rate-limit:
      - api
      - conversations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Org'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Orgs
      operationId: unstashOrg
      summary: Unstash an org
      x-rate-limit:
      - api
      - conversations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Org'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/orgs/{org}/members:
    post:
      tags:
      - Orgs
      operationId: addOrgMembers
      summary: Add members
      x-rate-limit:
      - api
      - conversations
      - messages
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min;
        `messages` 30/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Org'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                members:
                  type: array
                  items:
                    type: string
                  description: Handles.
                  minItems: 1
                  maxItems: 99
                share_history:
                  type: boolean
                  description: Let them read earlier messages.
              required:
              - members
              - share_history
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/orgs/{org}/members/{member}:
    put:
      tags:
      - Orgs
      operationId: updateOrgMemberRole
      summary: Change a member's role
      x-rate-limit:
      - api
      - conversations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Org'
      - $ref: '#/components/parameters/Member'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                role:
                  $ref: '#/components/schemas/OrgRole'
              required:
              - role
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Orgs
      operationId: removeOrgMember
      summary: Remove a member (or leave)
      x-rate-limit:
      - api
      - conversations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Org'
      - $ref: '#/components/parameters/Member'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/orgs/{org}/messages:
    get:
      tags:
      - Orgs
      operationId: getOrgThread
      summary: Read an org's thread
      x-rate-limit:
      - api
      - conversations
      description: |-
        From where your history starts. Poll with `after` and `reactions_after`.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Org'
      - name: after
        in: query
        required: false
        description: 'Poll: only messages after this id.'
        schema:
          type: integer
          minimum: 0
      - name: before
        in: query
        required: false
        description: Load the page before this message id.
        schema:
          type: integer
          minimum: 1
      - name: reactions_after
        in: query
        required: false
        description: 'Poll: reaction changes since this `reactions_version`.'
        schema:
          type: integer
          minimum: 0
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/OrgThread'
                required:
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    post:
      tags:
      - Orgs
      operationId: sendOrgMessage
      summary: Send a message to an org
      x-rate-limit:
      - api
      - messages
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `messages` 30/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Org'
      requestBody:
        required: true
        description: |2-


          Send JSON, or `multipart/form-data` when attaching files. With files, the signature uses the `devnull-api-images` namespace and covers their SHA-256 hashes (see *Requests with files*).
        content:
          application/json:
            schema:
              type: object
              properties:
                body:
                  type:
                  - string
                  - 'null'
                  maxLength: 2000
                  description: Required unless images or a voice note are attached.
                client_id:
                  type: string
                  description: A UUID you generate. Resending the same one returns the existing message (200).
                  format: uuid
                reply_to_id:
                  type:
                  - integer
                  - 'null'
                link_preview_url:
                  type:
                  - string
                  - 'null'
                  description: One of the URLs in `body`.
                image_descriptions:
                  type: array
                  items:
                    type:
                    - string
                    - 'null'
                    maxLength: 1000
                  maxItems: 3
                voice_waveform:
                  type: array
                  items:
                    type: integer
                    minimum: 0
                    maximum: 100
                  description: 'Required with `voice`: exactly 48 bars.'
                  minItems: 48
                  maxItems: 48
              required:
              - client_id
              description: The message. In multipart requests this object is the `payload` part.
          multipart/form-data:
            schema:
              type: object
              properties:
                payload:
                  type: string
                  description: The JSON body as a file part (`application/json`).
                  contentMediaType: application/json
                images[]:
                  type: array
                  items:
                    type: string
                    contentMediaType: image/*
                  description: JPEG, PNG or WebP; up to 3; 10 MB each.
                  maxItems: 3
                voice:
                  type: string
                  description: A voice note (0.5-61 s, under ~1.9 MB). Excludes `body` and images.
                  contentMediaType: audio/*
              required:
              - payload
            encoding:
              payload:
                contentType: application/json
      responses:
        '200':
          description: 'Retry with a known `client_id`: the existing message.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
        '201':
          description: Created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/orgs/{org}/mute:
    put:
      tags:
      - Orgs
      operationId: muteOrg
      summary: Mute or unmute an org
      x-rate-limit:
      - api
      - conversations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Org'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                duration:
                  type: string
                  enum:
                  - hour
                  - tomorrow
                  - week
                  - forever
                  - 'off'
              required:
              - duration
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  muted_until_at:
                    type:
                    - string
                    - 'null'
                    format: date-time
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/orgs/{org}/pin:
    put:
      tags:
      - Orgs
      operationId: pinOrg
      summary: Pin or unpin an org
      x-rate-limit:
      - api
      - conversations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Org'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                pinned:
                  type: boolean
              required:
              - pinned
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  pinned_at:
                    type:
                    - string
                    - 'null'
                    format: date-time
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/orgs/{org}/ping:
    post:
      tags:
      - Orgs
      operationId: pingOrg
      summary: Ping everyone in an org
      x-rate-limit:
      - api
      - pings
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `pings` 3/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Org'
      responses:
        '201':
          description: Created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/orgs/{org}/read:
    put:
      tags:
      - Orgs
      operationId: markOrgRead
      summary: Mark read through a message
      x-rate-limit:
      - api
      - conversations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Org'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                through:
                  type: integer
                  minimum: 0
              required:
              - through
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/orgs/{org}/typing:
    put:
      tags:
      - Orgs
      operationId: sendOrgTyping
      summary: Say you're typing
      x-rate-limit:
      - api
      - conversations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Org'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/@{partner}/call:
    post:
      tags:
      - Calls
      operationId: startDirectCall
      summary: Call the partner
      x-rate-limit:
      - api
      - messages
      description: |-
        Rings them with your SDP offer.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `messages` 30/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Partner'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                sdp:
                  type: string
                  description: SDP offer (starts with `v=0`).
                  maxLength: 10000
              required:
              - sdp
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    get:
      tags:
      - Calls
      operationId: getOutgoingCall
      summary: Poll your outgoing call
      x-rate-limit:
      - api
      - conversations
      description: |-
        While it rings; `answer` is set once they accept.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Partner'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  call:
                    anyOf:
                    - type: object
                      properties:
                        answer:
                          type:
                          - string
                          - 'null'
                          description: SDP answer.
                    - type: 'null'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    put:
      tags:
      - Calls
      operationId: answerDirectCall
      summary: Answer the partner's call
      x-rate-limit:
      - api
      - conversations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Partner'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                sdp:
                  type: string
                  description: SDP answer (starts with `v=0`).
                  maxLength: 10000
              required:
              - sdp
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Calls
      operationId: endDirectCall
      summary: Decline, cancel or end a call
      x-rate-limit:
      - api
      - conversations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Partner'
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                failed:
                  type: boolean
                  description: The call failed rather than being declined.
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/@{partner}/call/ice-servers:
    get:
      tags:
      - Calls
      operationId: getDirectCallIceServers
      summary: Get TURN servers for a call
      x-rate-limit:
      - api
      - messages
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `messages` 30/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Partner'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IceServers'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/call:
    get:
      tags:
      - Calls
      operationId: getIncomingCalls
      summary: Poll for calls
      x-rate-limit:
      - api
      - conversations
      description: |-
        The call ringing for you, and calls going on in your orgs.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  call:
                    anyOf:
                    - type: object
                      properties:
                        partner:
                          $ref: '#/components/schemas/User'
                        sdp:
                          type: string
                          description: The caller's SDP offer.
                        is_muted:
                          type: boolean
                    - type: 'null'
                  org_calls:
                    type: array
                    items:
                      type: object
                      properties:
                        org:
                          type: object
                          properties:
                            id:
                              type: string
                              format: uuid
                            name:
                              type:
                              - string
                              - 'null'
                        started_at:
                          type: integer
                        is_ringing:
                          type: boolean
                        is_muted:
                          type: boolean
                        members:
                          type: array
                          items:
                            $ref: '#/components/schemas/CallMember'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/orgs/{org}/call:
    post:
      tags:
      - Calls
      operationId: joinOrgCall
      summary: Start or join an org's call
      x-rate-limit:
      - api
      - messages
      description: |-
        Up to 8 people. `call` is null if it filled up in between.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `messages` 30/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Org'
      responses:
        '201':
          description: Joined.
          content:
            application/json:
              schema:
                type: object
                properties:
                  call:
                    anyOf:
                    - $ref: '#/components/schemas/OrgCall'
                    - type: 'null'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    put:
      tags:
      - Calls
      operationId: checkInOrgCall
      summary: Check in to an org's call
      x-rate-limit:
      - api
      - conversations
      description: |-
        Every couple of seconds: hand over your signals, pick up the others'.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Org'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                signals:
                  type: array
                  items:
                    $ref: '#/components/schemas/CallSignal'
                  maxItems: 8
              required:
              - signals
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  call:
                    anyOf:
                    - $ref: '#/components/schemas/OrgCall'
                    - type: 'null'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags:
      - Calls
      operationId: leaveOrgCall
      summary: Leave an org's call
      x-rate-limit:
      - api
      - conversations
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `conversations` 300/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Org'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/remotes/orgs/{org}/call/ice-servers:
    get:
      tags:
      - Calls
      operationId: getOrgCallIceServers
      summary: Get TURN servers for an org call
      x-rate-limit:
      - api
      - messages
      description: '**Rate limits:** `api` 120/min per user when signed; 60/min per IP when not; `messages` 30/min.'
      security:
      - sshSignature: []
        devnullTimestamp: []
        devnullNonce: []
      parameters:
      - $ref: '#/components/parameters/Org'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IceServers'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /v1/apps/mac:
    get:
      tags:
      - Apps
      operationId: getMacAppRelease
      summary: Latest Mac app release
      x-rate-limit:
      - api
      description: |-
        Unsigned on purpose, so update checks send nothing about the user. `data` is null until a release is published.

        **Rate limits:** `api` 120/min per user when signed; 60/min per IP when not.
      security: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    anyOf:
                    - $ref: '#/components/schemas/MacAppRelease'
                    - type: 'null'
                required:
                - data
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /cli/commits:
    post:
      tags:
      - CLI
      operationId: createCliCommit
      summary: Post a commit from the terminal
      x-rate-limit:
      - commits
      description: |-
        What `curl -fsSL https://dev-null.sh/commit | bash -s -- 'Hello world!'` calls. No account or device needed: sign with an SSH key that's on your GitHub account.

        **Payload** (the exact bytes signed and sent):

        ```
        <unix timestamp>\n<nonce>\n<reply-to hash or link, or empty>\n<body>
        ```

        With images, a line of comma-separated SHA-256 hex hashes (in attachment order) goes before the body:

        ```
        <unix timestamp>\n<nonce>\n<reply-to>\n<sha256,sha256>\n<body>
        ```

        Sign with `ssh-keygen -Y sign -n devnull-commit -f <key> payload` (namespace `devnull-commit-images` with images) and send the base64 inside the armor (no BEGIN/END lines, no newlines) as `X-SSH-Signature`.

        Responses are always **plain text**, errors included.

        **Rate limits:** `commits` 10 commits/min, however they are posted.
      security:
      - cliSignature: []
      requestBody:
        required: true
        content:
          text/plain:
            schema:
              type: string
              description: The signed payload.
              example: |-
                1762790400
                9f86d081884c7d659a2feaa0c55ad015

                Hello from the terminal!
          multipart/form-data:
            schema:
              type: object
              properties:
                payload:
                  type: string
                  description: The signed payload, as a file part.
                  contentMediaType: text/plain
                images[]:
                  type: array
                  items:
                    type: string
                    contentMediaType: image/*
                  description: JPEG, PNG or WebP; up to 3; 10 MB each.
                  maxItems: 3
              required:
              - payload
      responses:
        '201':
          description: Committed.
          content:
            text/plain:
              schema:
                type: string
                example: |
                  Committed: https://dev-null.sh/@you/commits/… (pending review, only you can see it until it is approved)
        '401':
          description: Bad, expired or replayed signature, or the key isn't on a /dev/null user's GitHub account.
          content:
            text/plain:
              schema:
                type: string
        '403':
          description: Banned, timed out, or the commit rules must be read on the web first.
          content:
            text/plain:
              schema:
                type: string
        '422':
          description: Validation failed (first message only).
          content:
            text/plain:
              schema:
                type: string
        '429':
          description: 10 commits a minute.
          headers:
            Retry-After:
              schema:
                type: integer
          content:
            text/plain:
              schema:
                type: string
        '503':
          description: GitHub couldn't be reached to check the key.
          content:
            text/plain:
              schema:
                type: string
  /cli/key-lookups:
    post:
      tags:
      - CLI
      operationId: lookupCliKey
      summary: Find which of your SSH keys belongs to a /dev/null user
      x-rate-limit:
      - cli-key-lookups
      description: |-
        Send up to 20 OpenSSH public keys, one per line. Answers with the first one on the GitHub account of a /dev/null user, so the script only asks the agent to sign with that key. Reads the database only (no GitHub call).

        **Rate limits:** `cli-key-lookups` 60/min per IP.
      security: []
      requestBody:
        required: true
        content:
          text/plain:
            schema:
              type: string
              example: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA… you@host
      responses:
        '200':
          description: The matching public key.
          content:
            text/plain:
              schema:
                type: string
        '404':
          description: None of the keys belong to a /dev/null user (plain-text help message).
          content:
            text/plain:
              schema:
                type: string
        '429':
          $ref: '#/components/responses/TooManyRequests'
components:
  securitySchemes:
    sshSignature:
      type: apiKey
      in: header
      name: X-SSH-Signature
      description: Base64 SSHSIG (namespace `devnull-api`, or `devnull-api-images` with files) of `<timestamp>\n<nonce>\n<METHOD>\n<path
        and query>\n<body>`, made with a key approved as a device. Sent together with `X-Devnull-Timestamp` and `X-Devnull-Nonce`.
    devnullTimestamp:
      type: apiKey
      in: header
      name: X-Devnull-Timestamp
      description: Unix seconds, within ±300 s of the server clock.
    devnullNonce:
      type: apiKey
      in: header
      name: X-Devnull-Nonce
      description: 32 lowercase hex characters, single use.
    cliSignature:
      type: apiKey
      in: header
      name: X-SSH-Signature
      description: Base64 SSHSIG (namespace `devnull-commit` or `devnull-commit-images`) of the raw payload, made with an
        SSH key on the author's GitHub account.
  parameters:
    Handle:
      name: handle
      in: path
      required: true
      description: A user's handle (their GitHub login).
      schema:
        type: string
      example: nunomaduro
    OrgHandle:
      name: handle
      in: path
      required: true
      description: An organization's handle (its GitHub login).
      schema:
        type: string
      example: laravel
    Commit:
      name: commit
      in: path
      required: true
      description: Commit id (UUID).
      schema:
        type: string
        format: uuid
      example: 01a1c63c-ae57-70cc-adf3-2298cc075627
    Partner:
      name: partner
      in: path
      required: true
      description: The other person's handle, after the literal `@`.
      schema:
        type: string
      example: nunomaduro
    Org:
      name: org
      in: path
      required: true
      description: Org (group conversation) id.
      schema:
        type: string
        format: uuid
    Message:
      name: message
      in: path
      required: true
      description: Message id.
      schema:
        type: integer
    Member:
      name: member
      in: path
      required: true
      description: The member's handle.
      schema:
        type: string
    Cursor:
      name: cursor
      in: query
      required: false
      description: Opaque cursor from `meta.next_cursor` / `links.next`.
      schema:
        type: string
  responses:
    NoContent:
      description: Done. No body.
    BadRequest:
      description: Invalid grant.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
    Unauthorized:
      description: '`invalid_signature` or `device_not_approved`.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
    Forbidden:
      description: 'Not allowed: `banned`, `timed_out`, `user_blocked`, `user_unavailable`, `own_commit`, `commit_rules_required`,
        or a plain policy message.'
      content:
        application/json:
          schema:
            anyOf:
            - $ref: '#/components/schemas/ApiError'
            - $ref: '#/components/schemas/Error'
    NotFound:
      description: Not found, or not visible to you (the API answers both alike).
      content:
        application/json:
          schema:
            anyOf:
            - $ref: '#/components/schemas/ApiError'
            - $ref: '#/components/schemas/Error'
    Conflict:
      description: The state changed underneath you; refresh.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unprocessable:
      description: Validation failed.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ValidationError'
    TooManyRequests:
      description: Rate limited.
      headers:
        Retry-After:
          description: Seconds to wait.
          schema:
            type: integer
      content:
        application/json:
          schema:
            anyOf:
            - $ref: '#/components/schemas/ApiError'
            - $ref: '#/components/schemas/Error'
    ServiceUnavailable:
      description: An upstream service failed; retry.
      content:
        application/json:
          schema:
            anyOf:
            - $ref: '#/components/schemas/ApiError'
            - $ref: '#/components/schemas/Error'
  schemas:
    Error:
      type: object
      properties:
        message:
          type: string
      required:
      - message
      description: A plain error, as Laravel renders it.
    ApiError:
      type: object
      properties:
        message:
          type: string
          description: Human-readable, safe to show as is.
        code:
          $ref: '#/components/schemas/ApiErrorCode'
        user:
          $ref: '#/components/schemas/User'
          description: 'With `user_blocked` only: the user the viewer blocked.'
      required:
      - message
      - code
      description: An error from the signed API. `code` never changes once released, so match on it, not on `message`.
    ApiErrorCode:
      type: string
      description: |-
        | code | status | meaning |
        |---|---|---|
        | `invalid_grant` | 400 | The sign-in code expired, was already used, or doesn't match. |
        | `invalid_signature` | 401 | Missing, malformed, stale or replayed signature. |
        | `device_not_approved` | 401 | The signature is fine but nobody approved this key as a device. |
        | `user_blocked` | 403 | The viewer blocked this user (comes with `user`). |
        | `user_unavailable` | 403 | The profile isn't available to the viewer (e.g. they were blocked). |
        | `own_commit` | 403 | You can't do this to your own commit (e.g. report it). |
        | `timed_out` | 403 | The user is in a moderation timeout: they can read but not post. |
        | `banned` | 403 | The account is banned; only `DELETE /v1/me` still works. |
        | `commit_rules_required` | 403 | First-time posters must read the commit rules and post once from the web. |
        | `commit_unavailable` | 404 | The commit doesn't exist, was deleted, isn't published, or isn't visible to you. |
        | `pasteis_exhausted` | 422 | No pastéis left today. |
        | `rate_limited` | 429 | Too many requests; see `Retry-After`. |
        | `github_sync_failed` | 503 | GitHub couldn't be reached to mirror the profile. |
      enum:
      - invalid_grant
      - invalid_signature
      - device_not_approved
      - user_blocked
      - user_unavailable
      - own_commit
      - timed_out
      - banned
      - commit_rules_required
      - commit_unavailable
      - pasteis_exhausted
      - rate_limited
      - github_sync_failed
    ValidationError:
      type: object
      properties:
        message:
          type: string
          example: The body field is required.
        errors:
          type: object
          properties: {}
          description: Messages by field name.
          additionalProperties:
            type: array
            items:
              type: string
      required:
      - message
      - errors
    CursorLinks:
      type: object
      properties:
        first:
          type:
          - string
          - 'null'
          format: uri
          description: Always null for cursor pages.
        last:
          type:
          - string
          - 'null'
          format: uri
          description: Always null for cursor pages.
        prev:
          type:
          - string
          - 'null'
          format: uri
        next:
          type:
          - string
          - 'null'
          format: uri
          description: Follow until null.
      required:
      - first
      - last
      - prev
      - next
    CursorMeta:
      type: object
      properties:
        path:
          type: string
          format: uri
        per_page:
          type: integer
          example: 20
        next_cursor:
          type:
          - string
          - 'null'
          description: Pass back as `?cursor=`.
        prev_cursor:
          type:
          - string
          - 'null'
      required:
      - path
      - per_page
      - next_cursor
      - prev_cursor
    PageLinks:
      type: object
      properties:
        first:
          type:
          - string
          - 'null'
          format: uri
        last:
          type:
          - string
          - 'null'
          format: uri
        prev:
          type:
          - string
          - 'null'
          format: uri
        next:
          type:
          - string
          - 'null'
          format: uri
    PageMeta:
      type: object
      properties:
        current_page:
          type: integer
        from:
          type:
          - integer
          - 'null'
        last_page:
          type: integer
        links:
          type: array
          items:
            type: object
            properties:
              url:
                type:
                - string
                - 'null'
              label:
                type: string
              active:
                type: boolean
        path:
          type: string
          format: uri
        per_page:
          type: integer
        to:
          type:
          - integer
          - 'null'
        total:
          type: integer
    TextSegment:
      type: object
      properties:
        type:
          type: string
          const: text
        text:
          type: string
      required:
      - type
      - text
      description: Prose.
    CodeSegment:
      type: object
      properties:
        type:
          type: string
          const: code
        code:
          type: string
      required:
      - type
      - code
      description: Inline `code`.
    BlockSegment:
      type: object
      properties:
        type:
          type: string
          const: block
        language:
          type:
          - string
          - 'null'
        filename:
          type:
          - string
          - 'null'
        html:
          type: string
          description: Syntax-highlighted HTML of the fenced block.
      required:
      - type
      - language
      - html
      description: A fenced code block.
    Segment:
      description: 'A piece of a body, split for rendering: prose, inline code, or a highlighted code block.'
      oneOf:
      - $ref: '#/components/schemas/TextSegment'
      - $ref: '#/components/schemas/CodeSegment'
      - $ref: '#/components/schemas/BlockSegment'
      discriminator:
        propertyName: type
        mapping:
          text: '#/components/schemas/TextSegment'
          code: '#/components/schemas/CodeSegment'
          block: '#/components/schemas/BlockSegment'
    Mention:
      type: object
      properties:
        handle:
          type: string
        offset:
          type: integer
          description: Character offset of the `@` in the body.
        length:
          type: integer
        kind:
          type: string
          enum:
          - user
          - organization
      required:
      - handle
      - offset
      - length
    LinkPreview:
      type: object
      properties:
        url:
          type: string
          format: uri
        title:
          type:
          - string
          - 'null'
        description:
          type:
          - string
          - 'null'
        image_url:
          type:
          - string
          - 'null'
          format: uri
        site_name:
          type:
          - string
          - 'null'
        is_pending:
          type: boolean
          description: True until the card has been fetched; ask again later.
        embed:
          anyOf:
          - type: object
            properties:
              provider:
                type: string
              kind:
                type: string
              src:
                type: string
                format: uri
              aspect_ratio:
                type:
                - number
                - 'null'
              height:
                type:
                - integer
                - 'null'
              poster:
                type:
                - string
                - 'null'
          - type: 'null'
          description: A playable embed (e.g. video) when the link supports one.
    CommitImage:
      type: object
      properties:
        id:
          type: string
          format: uuid
        width:
          type: integer
        height:
          type: integer
        description:
          type:
          - string
          - 'null'
          description: Alt text.
        url:
          type: string
          format: uri
          description: Signed and temporary while the commit is pending review.
      required:
      - id
      - width
      - height
      - url
    Poll:
      type: object
      properties:
        id:
          type: string
          format: uuid
        closes_at:
          type:
          - string
          - 'null'
          format: date-time
        is_closed:
          type: boolean
        has_voted:
          type: boolean
        total_votes:
          type:
          - integer
          - 'null'
          description: Null until you voted, wrote the poll, or it closed.
        options:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                format: uuid
              label:
                type: string
              votes_count:
                type:
                - integer
                - 'null'
              voted:
                type: boolean
              percentage:
                type:
                - integer
                - 'null'
    LiveNow:
      type: object
      properties:
        platform:
          type: string
          enum:
          - youtube
          - twitch
        url:
          type: string
          format: uri
        thumbnail_url:
          type: string
          format: uri
        ends_at:
          type: string
          format: date-time
    Lane:
      description: 'The profile color: a lane index (0-5) or a custom `#rrggbb` color.'
      oneOf:
      - type: integer
        minimum: 0
        maximum: 5
      - type: string
        pattern: ^#[0-9a-f]{6}$
    User:
      type: object
      properties:
        id:
          type: string
          format: uuid
        handle:
          type: string
          description: GitHub login.
          example: nunomaduro
        name:
          type:
          - string
          - 'null'
        avatar_url:
          type:
          - string
          - 'null'
          format: uri
        bio:
          type:
          - string
          - 'null'
        company:
          type:
          - string
          - 'null'
        location:
          type:
          - string
          - 'null'
        website:
          type:
          - string
          - 'null'
        github_url:
          type: string
          format: uri
        html_url:
          type: string
          format: uri
          example: https://dev-null.sh/@nunomaduro
        feed_url:
          type: string
          format: uri
          description: Atom feed of their commits.
        created_at:
          type: string
          format: date-time
        live:
          anyOf:
          - $ref: '#/components/schemas/LiveNow'
          - type: 'null'
          description: The stream they're on right now, if any.
        commits_count:
          type: integer
          description: When counted (profile pages).
        followers_count:
          type: integer
          description: When counted (profile pages).
        following_count:
          type: integer
          description: When counted (profile pages).
        lane:
          $ref: '#/components/schemas/Lane'
          description: Only in responses to signed requests.
        is_followed:
          type: boolean
          description: 'In lists for signed requests: whether you follow them.'
        follows_you:
          type: boolean
          description: 'In lists for signed requests: whether they follow you.'
        followed_by_following_count:
          type: integer
          description: 'In some lists: how many people you follow follow them.'
      required:
      - id
      - handle
      - name
      - avatar_url
      - github_url
      - html_url
      - feed_url
      - created_at
      description: A developer, as their public profile shows them.
    Organization:
      type: object
      properties:
        handle:
          type: string
          example: laravel
        name:
          type:
          - string
          - 'null'
        avatar_url:
          type:
          - string
          - 'null'
          format: uri
        bio:
          type:
          - string
          - 'null'
        location:
          type:
          - string
          - 'null'
        website:
          type:
          - string
          - 'null'
        github_url:
          type: string
          format: uri
        html_url:
          type: string
          format: uri
        lane:
          anyOf:
          - $ref: '#/components/schemas/Lane'
          - type: 'null'
          description: Chosen by its admins; null for /dev/null's blue.
        is_followed:
          type: boolean
          description: In lists for signed requests.
        followers_count:
          type: integer
          description: On its own page.
        admins:
          type: array
          items:
            $ref: '#/components/schemas/User'
          description: On its own page, first admin first.
      required:
      - handle
      - name
      - avatar_url
      - github_url
      - html_url
      - lane
      description: A GitHub organization's page on /dev/null. Organizations share `@handle` URLs with users.
    UserProfile:
      description: A user as a commit author or actor.
      allOf:
      - type: object
        properties:
          type:
            type: string
            const: user
          id:
            type: string
            format: uuid
        required:
        - type
        - id
      - $ref: '#/components/schemas/User'
    OrganizationProfile:
      description: An organization as a commit author or actor.
      allOf:
      - type: object
        properties:
          type:
            type: string
            const: organization
          id:
            type: string
            format: uuid
        required:
        - type
        - id
      - $ref: '#/components/schemas/Organization'
    Profile:
      description: 'A commit author or notification actor: a user or an organization, as `type` says, with its `id` either
        way.'
      oneOf:
      - $ref: '#/components/schemas/UserProfile'
      - $ref: '#/components/schemas/OrganizationProfile'
      discriminator:
        propertyName: type
        mapping:
          user: '#/components/schemas/UserProfile'
          organization: '#/components/schemas/OrganizationProfile'
    CurrentUser:
      description: 'The signed-in user: their public profile plus what only they see in Settings.'
      allOf:
      - $ref: '#/components/schemas/User'
      - type: object
        properties:
          pasteis_mode:
            type: boolean
          pasteis_remaining:
            type: integer
            description: Pastéis left to give today.
          pasteis_resets_at:
            type: string
            format: date-time
          pasteis_received:
            type: integer
          preferred_lane:
            anyOf:
            - $ref: '#/components/schemas/Lane'
            - type: 'null'
            description: Null for Automatic.
          automatic_lane:
            $ref: '#/components/schemas/Lane'
          sponsors_url:
            type:
            - string
            - 'null'
            format: uri
          github_synced_at:
            type:
            - string
            - 'null'
            format: date-time
          terms_version:
            type: string
            description: The version of the terms in force.
          terms_accepted_at:
            type:
            - string
            - 'null'
            format: date-time
          terms_accepted:
            type: boolean
            description: Whether the accepted version is the current one.
          remotes:
            anyOf:
            - type: object
              properties:
                from:
                  type: string
                  enum:
                  - following
                  - everyone
                  description: Who can push to you.
                pull_receipts:
                  type: boolean
                  description: Whether you share read receipts.
                requests:
                  type: boolean
                  description: 'Site flag: message requests are enabled.'
                everyone:
                  type: boolean
                  description: 'Site flag: `from: everyone` may be chosen.'
                unread_count:
                  type: integer
            - type: 'null'
            description: Null while Remotes (DMs) are turned off.
    UserAchievements:
      type: object
      properties:
        level:
          type: integer
        rank:
          type: string
        xp:
          type: integer
        next_level_xp:
          type:
          - integer
          - 'null'
        level_progress:
          type: integer
        xp_breakdown:
          type: object
          properties: {}
          description: 'By source: commits, streak, stars_received, replies, stars_given, luddite, shell_shocked.'
          additionalProperties:
            type: object
            properties:
              count:
                type: integer
              multiplier:
                type: integer
              xp:
                type: integer
        ranks:
          type: array
          items:
            type: object
            properties:
              rank:
                type: string
              level:
                type: integer
              min_xp:
                type: integer
              description:
                type: string
              achieved:
                type: boolean
        badges:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              name:
                type: string
              description:
                type: string
              icon:
                type: string
              unlocked:
                type: boolean
              progress:
                type: integer
              target:
                type: integer
    Device:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
          example: Rob's iPhone
        app_name:
          type:
          - string
          - 'null'
        fingerprint:
          type: string
          example: SHA256:2rM1n9yS1xH3V6tJ8pQe0oZf5b4cWkLmN7aDgUuYiRs
        approved_at:
          type: string
          format: date-time
        last_used_at:
          type:
          - string
          - 'null'
          format: date-time
      description: A key approved to sign requests as the user. Never includes the key itself.
    Commit:
      type: object
      properties:
        id:
          type: string
          format: uuid
        short_hash:
          type: string
          description: Last 7 hex chars of the id, as shown on the site.
          example: cc07562
        body:
          type: string
          description: Markdown-ish text, up to 4,000 characters.
        parent_id:
          type:
          - string
          - 'null'
          format: uuid
          description: The commit this replies to. Unsigned requests only see it when the parent is public.
        html_url:
          type: string
          format: uri
        created_at:
          type: string
          format: date-time
        stars_count:
          type: integer
        replies_count:
          type: integer
        link_preview:
          anyOf:
          - $ref: '#/components/schemas/LinkPreview'
          - type: 'null'
        images:
          type: array
          items:
            $ref: '#/components/schemas/CommitImage'
          maxItems: 3
        author:
          $ref: '#/components/schemas/Profile'
        body_segments:
          type: array
          items:
            $ref: '#/components/schemas/Segment'
          description: Only in responses to signed requests.
        preview_segments:
          type:
          - array
          - 'null'
          items:
            $ref: '#/components/schemas/Segment'
          description: Only in responses to signed requests. The excerpt a list shows of a long commit, or null when it fits.
        mentions:
          type: array
          items:
            $ref: '#/components/schemas/Mention'
          description: Only in responses to signed requests.
        status:
          type: string
          description: Only in responses to signed requests. Moderation status; others only ever see approved commits.
          enum:
          - pending
          - approved
          - rejected
        is_pinned:
          type: boolean
          description: Only in responses to signed requests.
        starred:
          type: boolean
          description: Only in responses to signed requests. Whether you starred it.
        pasteis_count:
          type: integer
          description: Only in responses to signed requests.
        deleted_at:
          type: 'null'
          description: Only in responses to signed requests.
        parent:
          anyOf:
          - $ref: '#/components/schemas/CommitOrTombstone'
          - type: 'null'
          description: Only in responses to signed requests. When loaded; null when you may not see the parent.
        quoted_commit_id:
          type:
          - string
          - 'null'
          format: uuid
          description: Only in responses to signed requests.
        quoted_commit:
          anyOf:
          - $ref: '#/components/schemas/CommitOrTombstone'
          - type: 'null'
          description: Only in responses to signed requests. Null once you can no longer see the quoted commit; a tombstone
            if it was deleted.
        poll:
          anyOf:
          - $ref: '#/components/schemas/Poll'
          - type: 'null'
          description: Only in responses to signed requests.
        reply_preview:
          type: object
          properties:
            data:
              type: array
              items:
                $ref: '#/components/schemas/CommitOrTombstone'
            next_cursor:
              type:
              - string
              - 'null'
          description: 'Only in responses to signed requests. In lists: the newest replies the site shows under the card.'
      required:
      - id
      - short_hash
      - body
      - parent_id
      - html_url
      - created_at
      - author
      description: A post ("commit") on the log. Counts, `link_preview`, `images` and relations are only present when loaded.
    DeletedCommit:
      type: object
      properties:
        id:
          type: string
          format: uuid
        parent_id:
          type:
          - string
          - 'null'
          format: uuid
        deleted_at:
          type: string
          format: date-time
        replies_count:
          type: integer
      required:
      - id
      - parent_id
      - deleted_at
      description: 'A tombstone: a deleted commit that still has replies stays in its thread without author or body. Signed
        requests only.'
    CommitOrTombstone:
      description: A commit, or (signed requests only) a tombstone where a deleted commit with replies stood. Tell them apart
        by `deleted_at` being set, or `author` missing.
      anyOf:
      - $ref: '#/components/schemas/Commit'
      - $ref: '#/components/schemas/DeletedCommit'
    ScheduledCommit:
      type: object
      properties:
        id:
          type: string
          format: uuid
        author:
          anyOf:
          - $ref: '#/components/schemas/Profile'
          - type: 'null'
          description: The organization it goes out as, or null for yourself.
        body:
          type:
          - string
          - 'null'
          description: Null once submitted (it lives on the commit then).
        body_segments:
          type: array
          items:
            $ref: '#/components/schemas/Segment'
        preview_segments:
          type:
          - array
          - 'null'
          items:
            $ref: '#/components/schemas/Segment'
        poll_options:
          type:
          - array
          - 'null'
          items:
            type: string
        image_count:
          type: integer
        scheduled_at:
          type: string
          format: date-time
        submitted_at:
          type:
          - string
          - 'null'
          format: date-time
        status:
          type: string
          enum:
          - scheduled
          - pending
          - approved
          - rejected
          - deleted
    CommitTranslation:
      type: object
      properties:
        language:
          type: string
          example: es
        source_language:
          type:
          - string
          - 'null'
        source_name:
          type:
          - string
          - 'null'
          example: English
        available:
          type: boolean
          description: Whether translating makes sense (source differs and is known).
        translated:
          anyOf:
          - type: object
            properties:
              body_segments:
                type: array
                items:
                  $ref: '#/components/schemas/Segment'
              preview_segments:
                type:
                - array
                - 'null'
                items:
                  $ref: '#/components/schemas/Segment'
          - type: 'null'
    NewPoll:
      type: object
      properties:
        options:
          type: array
          items:
            type: string
            maxLength: 50
          description: 2-4 distinct options.
          minItems: 2
          maxItems: 4
        duration:
          type: integer
          description: Minutes the poll stays open.
          enum:
          - 60
          - 1440
          - 4320
          - 10080
      required:
      - options
      - duration
    Notification:
      type: object
      properties:
        id:
          type: string
          format: uuid
        type:
          type: string
          enum:
          - followed
          - replied
          - mentioned
          - approved
          - rejected
          - quoted
          - starred
          - leveled_up
          - first_commit
        subject_id:
          type:
          - string
          - 'null'
        reason:
          type:
          - string
          - 'null'
          description: 'For `rejected`: the moderator''s reason.'
        read_at:
          type:
          - string
          - 'null'
          format: date-time
        created_at:
          type: string
          format: date-time
        actor:
          $ref: '#/components/schemas/Profile'
        actors:
          type: array
          items:
            $ref: '#/components/schemas/Profile'
          description: 'In lists: the first few actors of the group.'
        organization:
          anyOf:
          - $ref: '#/components/schemas/Organization'
          - type: 'null'
          description: Set when a member hears about an organization's commits or mentions.
        group_id:
          type:
          - string
          - 'null'
        event_count:
          type:
          - integer
          - 'null'
        actors_count:
          type:
          - integer
          - 'null'
        unread_count:
          type:
          - integer
          - 'null'
        commit:
          anyOf:
          - $ref: '#/components/schemas/Commit'
          - type: 'null'
      description: A group of notifications, represented by its newest one.
    Reaction:
      type: object
      properties:
        user_id:
          type: string
          format: uuid
        emoji:
          type: string
          example: 🔥
    Message:
      type: object
      properties:
        id:
          type: integer
        user_id:
          type:
          - string
          - 'null'
          format: uuid
        client_id:
          type:
          - string
          - 'null'
          format: uuid
          description: The id the sender's client generated (idempotency key).
        body:
          type:
          - string
          - 'null'
        body_segments:
          type: array
          items:
            $ref: '#/components/schemas/Segment'
        mentions:
          type: array
          items:
            $ref: '#/components/schemas/Mention'
        reply_to_id:
          type:
          - integer
          - 'null'
        reply_to:
          type: object
          properties:
            id:
              type: integer
            user_id:
              type:
              - string
              - 'null'
            body:
              type:
              - string
              - 'null'
            images_count:
              type: integer
            has_voice:
              type: boolean
        link_preview:
          anyOf:
          - $ref: '#/components/schemas/LinkPreview'
          - type: 'null'
        images:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                format: uuid
              width:
                type: integer
              height:
                type: integer
              description:
                type:
                - string
                - 'null'
              url:
                type: string
                format: uri
                description: Signed for you; see `GET /v1/remotes/images/{image}`.
        voice:
          anyOf:
          - type: object
            properties:
              id:
                type: string
                format: uuid
              duration_ms:
                type: integer
              waveform:
                type: array
                items:
                  type: integer
              url:
                type: string
                format: uri
                description: Signed for you; see `GET /v1/remotes/voices/{voice}`.
          - type: 'null'
        reactions:
          type: array
          items:
            $ref: '#/components/schemas/Reaction'
        event:
          type:
          - string
          - 'null'
          description: 'In orgs: the event this message records.'
          enum:
          - created
          - added
          - removed
          - left
          - renamed
          - promoted
          - demoted
          - inherited
          - ping
          - call_started
          - call_answered
          - call_cancelled
          - call_declined
          - call_missed
          - call_failed
          - null
        subject_id:
          type:
          - string
          - 'null'
          description: 'In orgs: who an event is about.'
        user:
          $ref: '#/components/schemas/User'
        subject:
          $ref: '#/components/schemas/User'
        pinned_at:
          type:
          - string
          - 'null'
          format: date-time
        created_at:
          type: string
          format: date-time
    OrgRole:
      type: string
      enum:
      - maintainer
      - contributor
    PushAccess:
      type: string
      description: 'What the composer can do: `open` push freely; `request` the first message becomes a request; `waiting`
        your request hasn''t been merged; `restricted`/`closed` you can''t push.'
      enum:
      - open
      - request
      - waiting
      - restricted
      - closed
    Conversation:
      type: object
      properties:
        id:
          type: string
          format: uuid
        kind:
          type: string
          enum:
          - direct
          - org
        name:
          type:
          - string
          - 'null'
          description: Orgs only.
        partner:
          anyOf:
          - $ref: '#/components/schemas/User'
          - type: 'null'
          description: Direct conversations only.
        members:
          type:
          - array
          - 'null'
          items:
            type: object
            properties:
              user:
                $ref: '#/components/schemas/User'
              role:
                anyOf:
                - $ref: '#/components/schemas/OrgRole'
                - type: 'null'
          description: Orgs only.
        last_message:
          anyOf:
          - $ref: '#/components/schemas/Message'
          - type: 'null'
        last_message_at:
          type:
          - string
          - 'null'
          format: date-time
        ahead:
          type: integer
          description: Messages from others you haven't pulled (read) yet.
        last_incoming_message_id:
          type:
          - integer
          - 'null'
        last_incoming_sender:
          type:
          - string
          - 'null'
        partner_read_through_id:
          type: integer
        partner_read_at:
          type:
          - string
          - 'null'
          format: date-time
        is_archived:
          type: boolean
          description: Stashed.
        pinned_at:
          type:
          - string
          - 'null'
          format: date-time
        muted_until_at:
          type:
          - string
          - 'null'
          format: date-time
      description: A row of the Remotes inbox.
    DirectThread:
      type: object
      properties:
        partner:
          $ref: '#/components/schemas/User'
        messages:
          type: array
          items:
            $ref: '#/components/schemas/Message'
        has_older:
          type: boolean
        reactions_version:
          type: integer
          description: Pass back as `reactions_after` when polling.
        reaction_changes:
          type: array
          items:
            type: object
            properties:
              id:
                type: integer
              reactions:
                type: array
                items:
                  $ref: '#/components/schemas/Reaction'
          description: Reactions changed since `reactions_after`.
        read_through_id:
          type: integer
        partner_read_through_id:
          type: integer
        partner_read_at:
          type:
          - string
          - 'null'
          format: date-time
        partner_typing:
          type: boolean
        is_archived:
          type: boolean
        pinned_at:
          type:
          - string
          - 'null'
          format: date-time
        muted_until_at:
          type:
          - string
          - 'null'
          format: date-time
        access:
          $ref: '#/components/schemas/PushAccess'
    OrgThread:
      type: object
      properties:
        org:
          type: object
          properties:
            id:
              type: string
              format: uuid
            name:
              type:
              - string
              - 'null'
        messages:
          type: array
          items:
            $ref: '#/components/schemas/Message'
        has_older:
          type: boolean
        reactions_version:
          type: integer
        reaction_changes:
          type: array
          items:
            type: object
            properties:
              id:
                type: integer
              reactions:
                type: array
                items:
                  $ref: '#/components/schemas/Reaction'
          description: Reactions changed since `reactions_after`.
        pinned:
          type:
          - array
          - 'null'
          items:
            $ref: '#/components/schemas/Message'
          description: Null when unchanged since `reactions_after`.
        mentions:
          type: array
          items:
            $ref: '#/components/schemas/Message'
          description: Messages that mention you, until you clear them.
        mentions_count:
          type: integer
        read_through_id:
          type: integer
        members:
          type: array
          items:
            type: object
            properties:
              role:
                anyOf:
                - $ref: '#/components/schemas/OrgRole'
                - type: 'null'
              read_through_id:
                type: integer
              user:
                $ref: '#/components/schemas/User'
        typing:
          type: array
          items:
            type: string
          description: Handles of members typing now.
        is_archived:
          type: boolean
        pinned_at:
          type:
          - string
          - 'null'
          format: date-time
        muted_until_at:
          type:
          - string
          - 'null'
          format: date-time
        role:
          anyOf:
          - $ref: '#/components/schemas/OrgRole'
          - type: 'null'
          description: Your role.
        access:
          $ref: '#/components/schemas/PushAccess'
    CallMember:
      type: object
      properties:
        user:
          $ref: '#/components/schemas/User'
        joined_at:
          type: integer
          description: Unix timestamp.
    CallSignal:
      type: object
      properties:
        id:
          type: string
          maxLength: 64
        type:
          type: string
          enum:
          - offer
          - answer
        sdp:
          type: string
          maxLength: 10000
      required:
      - id
      - type
      - sdp
    OrgCall:
      type: object
      properties:
        started_at:
          type: integer
          description: Unix timestamp.
        is_ringing:
          type: boolean
        members:
          type: array
          items:
            $ref: '#/components/schemas/CallMember'
          maxItems: 8
        signals:
          type: object
          properties: {}
          description: WebRTC signals addressed to you, by sender.
          additionalProperties:
            $ref: '#/components/schemas/CallSignal'
    IceServers:
      type: object
      properties:
        ice_servers:
          type: array
          items:
            type: object
            properties:
              urls:
                type: array
                items:
                  type: string
              username:
                type: string
              credential:
                type: string
          description: Short-lived TURN credentials for one call.
        is_relay_only:
          type: boolean
    PushPreferences:
      type: object
      properties:
        follows:
          type: boolean
        replies:
          type: boolean
        mentions:
          type: boolean
        direct_remotes:
          type: boolean
        org_remotes:
          type: boolean
      required:
      - follows
      - replies
      - mentions
      - direct_remotes
      - org_remotes
    Settings:
      type: object
      properties:
        timezone:
          type:
          - string
          - 'null'
          example: America/Mexico_City
        show_local_time:
          type: boolean
        translation_language:
          type:
          - string
          - 'null'
          description: Null to follow the device.
        automatic_translation:
          type: boolean
        translation_languages:
          type: array
          items:
            type: object
            properties:
              code:
                type: string
              name:
                type: string
              native_name:
                type: string
        is_admin:
          type: boolean
        push:
          $ref: '#/components/schemas/PushPreferences'
    MacAppRelease:
      type: object
      properties:
        version:
          type: string
          example: 0.4.0
        build:
          type: integer
        revision:
          type: string
        released_at:
          type: string
        minimum_system_version:
          type: string
          example: '14.0'
        notarized:
          type: boolean
        size:
          type: integer
          description: Bytes.
        sha256:
          type: string
        download_url:
          type: string
          format: uri
        url:
          type: string
          format: uri
    CommitResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Commit'
      required:
      - data
    CommitPage:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/CommitOrTombstone'
        links:
          $ref: '#/components/schemas/CursorLinks'
        meta:
          $ref: '#/components/schemas/CursorMeta'
      required:
      - data
      - links
      - meta
    UserPage:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/User'
        links:
          $ref: '#/components/schemas/CursorLinks'
        meta:
          $ref: '#/components/schemas/CursorMeta'
      required:
      - data
      - links
      - meta
    CurrentUserResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/CurrentUser'
        unread_notifications_count:
          type: integer
      required:
      - data
      - unread_notifications_count
    MessageResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Message'
      required:
      - data
