{
  "openapi": "3.1.0",
  "info": {
    "title": "Magic Meal Kits — Plaud API",
    "version": "1.0.0",
    "description": "Read your Plaud voice-recorder library — recordings, transcripts, AI summaries, note tabs, devices, and search — through your Magic Meal Kits server. Backs the **Plaud (Magic Meal Kits)** Make.com app.\n\nYour Plaud account credentials live server-side (Secret Manager) on your deployment; callers only send the MMK API key. Every endpoint requires a **Pro** license — a Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
    "license": {
      "name": "Proprietary",
      "identifier": "LicenseRef-Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://{deployment}/api/v1",
      "description": "Your Magic Meal Kits deployment",
      "variables": {
        "deployment": {
          "default": "magic-meal-kits-xxxxx.run.app",
          "description": "Your Cloud Run host (without protocol)"
        }
      }
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "User",
      "description": "Account profile and membership."
    },
    {
      "name": "Files",
      "description": "List, inspect, and bundle recordings."
    },
    {
      "name": "Content",
      "description": "Transcripts, summaries, note tabs, and audio."
    },
    {
      "name": "Search",
      "description": "Full-text search across transcripts."
    },
    {
      "name": "Devices",
      "description": "Bound Plaud hardware."
    },
    {
      "name": "Webhooks",
      "description": "Polling source for new-recording triggers."
    },
    {
      "name": "Folders",
      "description": "Tags (used as folders): list, create, assign/clear, and one-call organize."
    },
    {
      "name": "AI",
      "description": "Auto transcribe + summarize, task status, transcription quota, and summary models."
    },
    {
      "name": "System",
      "description": "Diagnostics, membership, config, and background-task status."
    }
  ],
  "paths": {
    "/plaud/user/me": {
      "get": {
        "operationId": "getPlaudUserMe",
        "tags": [
          "User"
        ],
        "summary": "Get current user",
        "description": "Returns the current Plaud user's profile, membership tier, and remaining transcription seconds. **Pro license required.**",
        "x-mmk-tier": "pro",
        "responses": {
          "200": {
            "description": "User profile + membership state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserMeResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          }
        }
      }
    },
    "/plaud/files": {
      "get": {
        "operationId": "listPlaudFiles",
        "tags": [
          "Files"
        ],
        "summary": "List recordings",
        "description": "Lists your Plaud recordings, newest first by default. **Pro license required.**",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20
            },
            "description": "Max files to return."
          },
          {
            "name": "skip",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Offset for pagination."
          },
          {
            "name": "is_trash",
            "in": "query",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1,
                2
              ],
              "default": 0
            },
            "description": "0 = active, 1 = trash, 2 = both."
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "edit_time",
                "start_time"
              ],
              "default": "edit_time"
            },
            "description": "Sort field."
          },
          {
            "name": "is_desc",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": true
            },
            "description": "Descending order."
          }
        ],
        "responses": {
          "200": {
            "description": "File listing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListFilesResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          }
        }
      }
    },
    "/plaud/files/{id}": {
      "get": {
        "operationId": "getPlaudFileDetail",
        "tags": [
          "Files"
        ],
        "summary": "Get recording metadata",
        "description": "Returns metadata for a single recording (no transcript/summary fetch). **Pro license required.**",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "$ref": "#/components/parameters/FileId"
          }
        ],
        "responses": {
          "200": {
            "description": "File detail",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileDetailResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          }
        }
      },
      "patch": {
        "operationId": "renamePlaudFile",
        "tags": [
          "Files"
        ],
        "summary": "Rename a recording",
        "description": "Renames a recording. Returns `204 No Content` on success. **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "$ref": "#/components/parameters/FileId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RenameFileRequest"
              },
              "example": {
                "filename": "Team standup — 2026-06-27"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Renamed"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          }
        }
      }
    },
    "/plaud/files/{id}/fetch": {
      "get": {
        "operationId": "getPlaudFileBundle",
        "tags": [
          "Files"
        ],
        "summary": "Get recording bundle",
        "description": "Backend-for-frontend: returns the file plus any combination of transcript, summary, share state, and audio URL in a single call. **Pro license required.**",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "$ref": "#/components/parameters/FileId"
          },
          {
            "name": "include",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "transcript,summary"
            },
            "description": "Comma-separated attachments to compose. Accepted tokens: `transcript`, `summary`, `share`, `audio_url` (alias `audio-url`). When omitted, defaults to `transcript,summary` — `share` and `audio_url` are only included when explicitly requested."
          },
          {
            "name": "transcript_format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "text",
                "markdown",
                "srt",
                "vtt",
                "json",
                "plain"
              ]
            },
            "description": "Rendering applied to the bundled transcript's `text`. Defaults to `text`."
          },
          {
            "name": "strict",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Fail-fast on any sub-fetch error instead of collecting per-attachment errors."
          }
        ],
        "responses": {
          "200": {
            "description": "Composed file bundle",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileBundle"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "409": {
            "$ref": "#/components/responses/NotReady"
          }
        }
      }
    },
    "/plaud/files/{id}/transcript": {
      "get": {
        "operationId": "getPlaudTranscript",
        "tags": [
          "Content"
        ],
        "summary": "Get transcript",
        "description": "Returns the decoded transcript with speaker labels and millisecond timestamps. Pass `format` to also get a rendered `text` string. **Pro license required.**",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "$ref": "#/components/parameters/FileId"
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "text",
                "markdown",
                "srt",
                "vtt",
                "json",
                "plain"
              ]
            },
            "description": "Optional. When provided, the response adds `text` (rendered transcript) and `format`. Omit to get the raw `{file_id, content}` shape only."
          }
        ],
        "responses": {
          "200": {
            "description": "Transcript",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Transcript"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "409": {
            "$ref": "#/components/responses/NotReady"
          }
        }
      }
    },
    "/plaud/files/{id}/summary": {
      "get": {
        "operationId": "getPlaudSummary",
        "tags": [
          "Content"
        ],
        "summary": "Get AI summary",
        "description": "Returns the AI-generated Markdown summary. Relative image paths are rewritten to pre-signed S3 URLs (~15-min TTL). **Pro license required.**",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "$ref": "#/components/parameters/FileId"
          }
        ],
        "responses": {
          "200": {
            "description": "Summary",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Summary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "409": {
            "$ref": "#/components/responses/NotReady"
          }
        }
      }
    },
    "/plaud/files/{id}/tabs": {
      "get": {
        "operationId": "listPlaudNoteTabs",
        "tags": [
          "Content"
        ],
        "summary": "List note tabs",
        "description": "Lists the named AI note tabs for a recording (Summary, Key Points, Highlights, template outputs). **Pro license required.**",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "$ref": "#/components/parameters/FileId"
          },
          {
            "name": "include_source",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Include raw-source rows (transcript transaction, outline) that are hidden by default as picker noise."
          }
        ],
        "responses": {
          "200": {
            "description": "Note tabs",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NoteTabsResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          }
        }
      }
    },
    "/plaud/files/{id}/tabs/content": {
      "get": {
        "operationId": "getPlaudNoteTab",
        "tags": [
          "Content"
        ],
        "summary": "Get note tab content",
        "description": "Fetches the content of one note tab, selected by exactly one of `tab_id` or `template`. **Pro license required.**",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "$ref": "#/components/parameters/FileId"
          },
          {
            "name": "tab_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Per-note tab identifier from the list-tabs response. Provide this or `template`."
          },
          {
            "name": "template",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Stable template selector (e.g. `SUMMARY`, `Key Points`, `AI-CHOICE`), matched across notes. Provide this or `tab_id`."
          }
        ],
        "responses": {
          "200": {
            "description": "Tab content",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NoteTabContent"
                }
              }
            }
          },
          "400": {
            "description": "Neither `tab_id` nor `template` provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "409": {
            "$ref": "#/components/responses/NotReady"
          }
        }
      }
    },
    "/plaud/files/{id}/audio-url": {
      "get": {
        "operationId": "getPlaudAudioUrl",
        "tags": [
          "Content"
        ],
        "summary": "Get audio URL",
        "description": "Returns a pre-signed S3 URL for the original audio file. **Pro license required.**",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "$ref": "#/components/parameters/FileId"
          }
        ],
        "responses": {
          "200": {
            "description": "Audio URL",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "file_id": {
                      "type": "string"
                    },
                    "audio_url": {
                      "type": "string",
                      "description": "Pre-signed S3 URL."
                    }
                  }
                },
                "example": {
                  "file_id": "ceb63f88",
                  "audio_url": "https://plaud-s3.amazonaws.com/…?X-Amz-Signature=…"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          }
        }
      }
    },
    "/plaud/devices": {
      "get": {
        "operationId": "listPlaudDevices",
        "tags": [
          "Devices"
        ],
        "summary": "List devices",
        "description": "Lists the Plaud hardware devices bound to the account (Note, Note Pro, etc.). **Pro license required.**",
        "x-mmk-tier": "pro",
        "responses": {
          "200": {
            "description": "Bound devices",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeviceListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          }
        }
      }
    },
    "/plaud/search": {
      "get": {
        "operationId": "searchPlaudTranscripts",
        "tags": [
          "Search"
        ],
        "summary": "Search transcripts",
        "description": "Full-text search across all your transcripts. Returns matching files with hit context. **Pro license required.**",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Search text."
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Result source/context selector passed through to Plaud."
          },
          {
            "name": "date_from",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int64"
            },
            "description": "Lower bound on recording start time (epoch ms)."
          },
          {
            "name": "date_to",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int64"
            },
            "description": "Upper bound on recording start time (epoch ms)."
          }
        ],
        "responses": {
          "200": {
            "description": "Search results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Missing `query` parameter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          }
        }
      }
    },
    "/plaud/search/history": {
      "get": {
        "operationId": "getPlaudSearchHistory",
        "tags": [
          "Search"
        ],
        "summary": "Get search history",
        "description": "Returns recent search queries with counts. **Pro license required.**",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 10
            },
            "description": "Max history entries."
          }
        ],
        "responses": {
          "200": {
            "description": "Search history",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchHistoryResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          }
        }
      }
    },
    "/plaud/files/webhook-candidates": {
      "get": {
        "operationId": "getPlaudWebhookCandidates",
        "tags": [
          "Webhooks"
        ],
        "summary": "Poll new-recording candidates",
        "description": "Returns the most-recently-edited recordings that are READY to ship (not trashed, transcribed, and summarized), newest first. This is the polling source behind the **Watch New Recordings** Make trigger. **Pro license required.**",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 5,
              "minimum": 1,
              "maximum": 20
            },
            "description": "Number of candidates (clamped to 1–20)."
          }
        ],
        "responses": {
          "200": {
            "description": "Ready-to-ship candidates",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookCandidatesResponse"
                },
                "example": {
                  "files": [
                    {
                      "id": "ceb63f88",
                      "filename": "Team standup",
                      "version_ms": 1719460000000,
                      "edit_time": 1719460000000,
                      "edit_from": "web"
                    }
                  ],
                  "fetched_at": "2026-06-27T09:00:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          }
        }
      }
    },
    "/plaud/doctor": {
      "get": {
        "operationId": "getPlaudDoctor",
        "tags": [
          "System"
        ],
        "summary": "Health check",
        "description": "Runs a live connectivity probe against Plaud (user profile + device list in parallel) and reports whether the stored credentials work. Returns `200` when both checks pass, `401` when Plaud rejected the token (reconnect), `502` on other upstream failures. **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "responses": {
          "200": {
            "description": "Doctor report",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DoctorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Plaud rejected the stored token — reconnect your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DoctorResponse"
                }
              }
            }
          },
          "502": {
            "description": "An upstream check failed (non-auth).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DoctorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/plaud/membership/status": {
      "get": {
        "operationId": "getPlaudMembershipStatus",
        "tags": [
          "System"
        ],
        "summary": "Get membership status",
        "description": "Returns the account's free-trial / membership state as a loose upstream envelope. **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "responses": {
          "200": {
            "description": "Membership status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LooseEnvelope"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          }
        }
      }
    },
    "/plaud/config": {
      "get": {
        "operationId": "getPlaudConfig",
        "tags": [
          "System"
        ],
        "summary": "Get client config",
        "description": "Returns Plaud's `config/init` payload (feature toggles and client configuration) as a loose upstream envelope. **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "responses": {
          "200": {
            "description": "Config payload",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LooseEnvelope"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          }
        }
      }
    },
    "/plaud/combine/running-tasks": {
      "get": {
        "operationId": "getPlaudRunningCombineTasks",
        "tags": [
          "System"
        ],
        "summary": "List running combine tasks",
        "description": "Returns the currently in-flight combine (merge-audio) tasks. The web app polls this to drive a progress indicator; the list is usually empty. **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "responses": {
          "200": {
            "description": "Running combine tasks",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunningCombineTasksResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          }
        }
      }
    },
    "/plaud/user/feature-access": {
      "get": {
        "operationId": "getPlaudFeatureAccess",
        "tags": [
          "User"
        ],
        "summary": "Get feature access",
        "description": "Returns the account's feature-flag payload as a loose upstream envelope (the flag set changes over time, so it is passed through verbatim). **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "responses": {
          "200": {
            "description": "Feature-access flags",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LooseEnvelope"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          }
        }
      }
    },
    "/plaud/files/{id}/share": {
      "get": {
        "operationId": "getPlaudShareStates",
        "tags": [
          "Files"
        ],
        "summary": "Get share states",
        "description": "Returns the private and public share state for a recording. Each side is a loose upstream envelope (shape varies depending on whether a share exists). **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "$ref": "#/components/parameters/FileId"
          }
        ],
        "responses": {
          "200": {
            "description": "Share states",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShareStatesResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          }
        }
      }
    },
    "/plaud/sync": {
      "get": {
        "operationId": "syncPlaudFiles",
        "tags": [
          "Files"
        ],
        "summary": "Bundle multiple recordings",
        "description": "Backend-for-frontend aggregator: lists recordings and composes each one's requested attachments (transcript/summary/share/audio) in a single call. Backs `mmk plaud file list --with transcripts,summaries`. **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 10,
              "minimum": 1,
              "maximum": 20
            },
            "description": "Max files (clamped to 1–20)."
          },
          {
            "name": "skip",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Offset for pagination."
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int64"
            },
            "description": "Only include files with `start_time` >= this epoch-ms value."
          },
          {
            "name": "include",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "transcript,summary"
            },
            "description": "Comma-separated attachments to compose: `transcript`, `summary`, `share`, `audio_url`."
          },
          {
            "name": "transcript_format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "text",
                "markdown",
                "srt",
                "vtt",
                "json",
                "plain"
              ]
            },
            "description": "Rendering applied to each bundled transcript's `text`."
          },
          {
            "name": "strict",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Fail-fast on any sub-fetch error."
          },
          {
            "name": "concurrency",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 4,
              "minimum": 1,
              "maximum": 8
            },
            "description": "Max in-flight files (clamped to 1–8)."
          }
        ],
        "responses": {
          "200": {
            "description": "Aggregated bundles",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SyncResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          }
        }
      }
    },
    "/plaud/files/{id}/ack-pull": {
      "post": {
        "operationId": "ackPullPlaudFile",
        "tags": [
          "Files"
        ],
        "summary": "Acknowledge device pull",
        "description": "Acknowledges that a recording was pulled from the device — decrements Plaud's `wait_pull` counter so the file stops surfacing as unread. Empty body. Returns `204 No Content` on success. **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "$ref": "#/components/parameters/FileId"
          }
        ],
        "responses": {
          "204": {
            "description": "Acknowledged"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          }
        }
      }
    },
    "/plaud/files/trash": {
      "post": {
        "operationId": "trashPlaudFiles",
        "tags": [
          "Files"
        ],
        "summary": "Trash recordings",
        "description": "Soft-deletes one or more recordings (moves them to trash with `is_trash=true`). This is recoverable — it is NOT a permanent delete. An empty `file_ids` list is rejected with `400`. Returns `204 No Content` on success. **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TrashFilesRequest"
              },
              "example": {
                "file_ids": [
                  "ceb63f88",
                  "a1b2c3d4"
                ]
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Moved to trash"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          }
        }
      }
    },
    "/plaud/tags": {
      "get": {
        "operationId": "listPlaudTags",
        "tags": [
          "Folders"
        ],
        "summary": "List tags",
        "description": "Lists the account's tags (used as folders). **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "responses": {
          "200": {
            "description": "Tag list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TagListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          }
        }
      },
      "post": {
        "operationId": "createPlaudTag",
        "tags": [
          "Folders"
        ],
        "summary": "Create a tag",
        "description": "Creates a new tag (folder). The response echoes the upstream create envelope, which includes the new tag id — pass it to `POST /files/update-tags` to assign it. **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTagRequest"
              },
              "example": {
                "name": "Interviews",
                "color": "#46cf6c",
                "icon": "e627"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created tag",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateTagResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          }
        }
      }
    },
    "/plaud/files/update-tags": {
      "post": {
        "operationId": "updatePlaudFileTags",
        "tags": [
          "Folders"
        ],
        "summary": "Assign or clear a tag",
        "description": "Assigns a tag to (or clears it from) one or more recordings. Pass an empty `filetag_id` to clear the tag from every file in `file_id_list`. An empty `file_id_list` is rejected with `400`. Returns `204 No Content` on success. **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateFileTagsRequest"
              },
              "example": {
                "file_id_list": [
                  "ceb63f88"
                ],
                "filetag_id": "tag_abc123"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Tags updated"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          }
        }
      }
    },
    "/plaud/files/organize": {
      "post": {
        "operationId": "organizePlaudFiles",
        "tags": [
          "Folders"
        ],
        "summary": "Organize into a folder",
        "description": "One-call BFF: resolve a tag by name (creating it when missing), then assign it to every listed file. The verb users and AI agents actually want — 'put these recordings into this folder'. **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrganizeFilesRequest"
              },
              "example": {
                "file_ids": [
                  "f1",
                  "f2"
                ],
                "tag_name": "Interviews",
                "color": "#46cf6c",
                "match_mode": "fold",
                "create_if_missing": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Organize result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizeFilesResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          }
        }
      }
    },
    "/plaud/files/{id}/dispatch": {
      "post": {
        "operationId": "dispatchPlaudFile",
        "tags": [
          "Webhooks"
        ],
        "summary": "Dispatch a recording to a webhook",
        "description": "Fetches the recording (with transcript + summary), flattens it into a webhook payload, and POSTs it to the caller-supplied `webhook_url`. Stateless — deduplication is the orchestrator's job. A `200` with `success=false` means the dispatch ran end-to-end but your webhook URL returned a non-2xx status. **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "$ref": "#/components/parameters/FileId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DispatchRequest"
              },
              "example": {
                "webhook_url": "https://hook.make.com/abc123",
                "delivery_id": "d-42",
                "idempotency_key": "note:ceb63f88:1719460000000"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Dispatch completed — inspect `success` and `webhook_status_code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DispatchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Malformed body or invalid `webhook_url` scheme (must be http/https); also the Basic-key gate `you are not a magic meal kits PRO user`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DispatchResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "404": {
            "description": "The recording does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DispatchResponse"
                }
              }
            }
          },
          "409": {
            "description": "The recording is not ready yet (no transcript or no summary).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DispatchResponse"
                }
              }
            }
          },
          "502": {
            "description": "Plaud upstream error while fetching the recording.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DispatchResponse"
                }
              }
            }
          }
        }
      }
    },
    "/plaud/files/{id}/transsumm": {
      "post": {
        "operationId": "startPlaudTransSumm",
        "tags": [
          "AI"
        ],
        "summary": "Start transcribe + summarize",
        "description": "Triggers Plaud's automatic transcript + summary pipeline for a recording without blocking, returning the immediate upstream response (the task runs async). All body fields are optional (zero values map to Plaud defaults: auto language, auto LLM, diarization on). When `check_quota` is `true`, insufficient transcription seconds return `402`. **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "$ref": "#/components/parameters/FileId"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransSummRequest"
              },
              "example": {
                "language": "auto",
                "diarization": true,
                "llm": "auto",
                "summ_type": "AUTO-SELECT"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Task accepted (async)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransSummResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "402": {
            "$ref": "#/components/responses/QuotaInsufficient"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          }
        }
      }
    },
    "/plaud/files/{id}/transsumm/wait": {
      "post": {
        "operationId": "waitPlaudTransSumm",
        "tags": [
          "AI"
        ],
        "summary": "Transcribe + summarize (wait)",
        "description": "Triggers transcribe + summarize, polls until the task completes, then returns the composed file bundle (transcript + summary + optional audio URL) — the same shape as `GET /files/{id}/fetch`. Pre-flight quota check is ON by default here (`{\"check_quota\": false}` to skip). Returns `402` on insufficient quota and `504` if the task does not finish within the timeout. **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "$ref": "#/components/parameters/FileId"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransSummRequest"
              },
              "example": {
                "language": "auto",
                "poll_interval_sec": 3,
                "timeout_sec": 300,
                "include": [
                  "transcript",
                  "summary"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Completed bundle",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileBundle"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "402": {
            "$ref": "#/components/responses/QuotaInsufficient"
          },
          "409": {
            "$ref": "#/components/responses/NotReady"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          },
          "504": {
            "description": "The transsumm task did not complete within the timeout.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/plaud/ai/status": {
      "get": {
        "operationId": "getPlaudAITaskStatus",
        "tags": [
          "AI"
        ],
        "summary": "Get AI task status",
        "description": "Returns the AI (transcribe/summarize) task status for the given files. `file_ids` is a required comma-separated query parameter. **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "name": "file_ids",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated recording IDs."
          }
        ],
        "responses": {
          "200": {
            "description": "Per-file task status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AITaskStatusResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          }
        }
      }
    },
    "/plaud/ai/trans-status": {
      "get": {
        "operationId": "getPlaudTransStatus",
        "tags": [
          "AI"
        ],
        "summary": "Get transcription seconds",
        "description": "Returns the account's total and remaining transcription seconds. **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "responses": {
          "200": {
            "description": "Transcription seconds",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransStatusResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          }
        }
      }
    },
    "/plaud/user/transcription-quota": {
      "get": {
        "operationId": "getPlaudTranscriptionQuota",
        "tags": [
          "AI"
        ],
        "summary": "Get transcription quota flags",
        "description": "Returns the two booleans driving the web client's out-of-quota UI: `is_starter` and `usage_reached`. **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "responses": {
          "200": {
            "description": "Quota flags",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TranscriptionQuotaResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          }
        }
      }
    },
    "/plaud/summary/models": {
      "get": {
        "operationId": "getPlaudSummaryModels",
        "tags": [
          "AI"
        ],
        "summary": "List summary models",
        "description": "Lists the LLM models Plaud offers for summary generation. `model_name` is the identifier you pass as `llm` to the transsumm endpoints. **Pro license required.** A Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "x-mmk-tier": "pro",
        "parameters": [
          {
            "name": "language",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Optional language code (e.g. `en`) to scope the model list."
          }
        ],
        "responses": {
          "200": {
            "description": "Summary models",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SummaryModelsResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/PlaudAuthError"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamError"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-KEY",
        "description": "Your deployment's API key (MMK_API_KEY). Your Plaud account credentials are stored server-side — you do not send them."
      }
    },
    "parameters": {
      "FileId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "Plaud recording (file) ID."
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid request (e.g. missing/blank required field), or the Pro-license gate: a Basic key is rejected with `400` and `you are not a magic meal kits PRO user`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "PlaudAuthError": {
        "description": "Plaud credentials rejected (revoked/expired) — reconnect your Plaud account.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotReady": {
        "description": "The requested attachment is not generated yet (e.g. transcription still running)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "UpstreamError": {
        "description": "Plaud upstream returned an error (surfaced as `502` with `upstream_status`/`upstream_msg`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "QuotaInsufficient": {
        "description": "Not enough transcription seconds remaining to transcribe this recording.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/QuotaError"
            }
          }
        }
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "UserMeResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "Plaud envelope status (0 = success)."
          },
          "data_user": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "nickname": {
                "type": "string"
              },
              "email": {
                "type": "string"
              },
              "country": {
                "type": "string"
              },
              "membership_id": {
                "type": "integer"
              },
              "seconds_left": {
                "type": "integer",
                "format": "int64",
                "description": "Remaining transcription seconds."
              },
              "seconds_total": {
                "type": "integer",
                "format": "int64"
              }
            }
          },
          "data_state": {
            "type": "object",
            "properties": {
              "is_membership": {
                "type": "integer"
              },
              "membership_type": {
                "type": "string"
              },
              "have_files": {
                "type": "boolean"
              },
              "has_transcribed": {
                "type": "boolean"
              }
            }
          }
        }
      },
      "PlaudFile": {
        "type": "object",
        "description": "A recording. Epoch-ms fields are echoed alongside pre-formatted siblings (`*_time_human`, `duration_human`, `duration_seconds`, `duration_minutes`, `duration_hours`).",
        "properties": {
          "id": {
            "type": "string"
          },
          "filename": {
            "type": "string"
          },
          "keywords": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "filesize": {
            "type": "integer",
            "format": "int64"
          },
          "filetype": {
            "type": "string"
          },
          "is_trash": {
            "type": "boolean"
          },
          "start_time": {
            "type": "integer",
            "format": "int64",
            "description": "Epoch ms."
          },
          "end_time": {
            "type": "integer",
            "format": "int64",
            "description": "Epoch ms."
          },
          "duration": {
            "type": "integer",
            "format": "int64",
            "description": "Milliseconds."
          },
          "filetag_id_list": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "is_trans": {
            "type": "boolean",
            "description": "Transcript ready."
          },
          "is_summary": {
            "type": "boolean",
            "description": "Summary ready."
          },
          "start_time_human": {
            "type": "string",
            "description": "RFC3339 UTC."
          },
          "duration_human": {
            "type": "string",
            "description": "`m:ss` or `h:mm:ss`."
          }
        }
      },
      "ListFilesResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "data_file_total": {
            "type": "integer"
          },
          "data_file_list": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlaudFile"
            }
          }
        }
      },
      "FileDetailData": {
        "type": "object",
        "description": "Inner file-detail object — the `data` of FileDetailResponse and the `file` of a bundle.",
        "properties": {
          "file_id": {
            "type": "string"
          },
          "file_name": {
            "type": "string"
          },
          "duration": {
            "type": "integer",
            "format": "int64"
          },
          "is_trash": {
            "type": "boolean"
          },
          "start_time": {
            "type": "integer",
            "format": "int64"
          },
          "filetag_id_list": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "is_trans": {
            "type": "boolean"
          },
          "is_summary": {
            "type": "boolean"
          }
        }
      },
      "FileDetailResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/FileDetailData"
          }
        }
      },
      "Transcript": {
        "type": "object",
        "properties": {
          "file_id": {
            "type": "string"
          },
          "content": {
            "description": "Decoded transcript payload (object or array of speaker-labeled segments)."
          },
          "text": {
            "type": "string",
            "description": "Rendered transcript — present only when `format` was requested."
          },
          "format": {
            "type": "string",
            "description": "Echoes the requested format."
          }
        }
      },
      "Summary": {
        "type": "object",
        "properties": {
          "file_id": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "enum": [
              "inline",
              "s3"
            ]
          },
          "markdown": {
            "type": "string",
            "description": "Summary as Markdown with image paths rewritten to pre-signed URLs."
          },
          "images": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "description": "Pre-signed S3 URL (~15-min TTL)."
                }
              }
            }
          }
        }
      },
      "NoteTabsResponse": {
        "type": "object",
        "properties": {
          "file_id": {
            "type": "string"
          },
          "tabs": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "tab_id": {
                  "type": "string"
                },
                "tab_name": {
                  "type": "string"
                },
                "type": {
                  "type": "string"
                },
                "format": {
                  "type": "string"
                },
                "template_id": {
                  "type": "string"
                },
                "template_name": {
                  "type": "string"
                },
                "ready": {
                  "type": "boolean"
                }
              }
            }
          }
        }
      },
      "NoteTabContent": {
        "type": "object",
        "properties": {
          "tab_id": {
            "type": "string"
          },
          "tab_name": {
            "type": "string"
          },
          "format": {
            "type": "string",
            "description": "`markdown` or a structured JSON type."
          },
          "source": {
            "type": "string",
            "enum": [
              "inline",
              "s3"
            ]
          },
          "content": {
            "description": "JSON string for markdown tabs; object/array for structured JSON tabs."
          }
        }
      },
      "FileBundle": {
        "type": "object",
        "description": "File detail plus opted-in attachments. `file` is the inner file-detail object (`file.file_id`, …), not a `{status,data}` envelope. `transcript`/`summary`/`share`/`audio_url` appear only when requested via `include` and the fetch succeeded.",
        "properties": {
          "file": {
            "$ref": "#/components/schemas/FileDetailData"
          },
          "transcript": {
            "$ref": "#/components/schemas/Transcript"
          },
          "summary": {
            "$ref": "#/components/schemas/Summary"
          },
          "share": {
            "type": "object",
            "description": "Private/public share state — present only when `include=share`.",
            "properties": {
              "private": {
                "type": "object",
                "additionalProperties": true
              },
              "public": {
                "type": "object",
                "additionalProperties": true
              }
            }
          },
          "audio_url": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Per-attachment failures (non-strict mode)."
          },
          "not_ready": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Requested attachments that are not generated yet."
          }
        }
      },
      "DeviceListResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "data_devices": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "sn": {
                  "type": "string",
                  "description": "Serial number."
                },
                "name": {
                  "type": "string"
                },
                "model": {
                  "type": "string"
                },
                "version_number": {
                  "type": "integer",
                  "format": "int64"
                }
              }
            }
          }
        }
      },
      "SearchResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "data": {
            "type": "object",
            "properties": {
              "size": {
                "type": "integer"
              },
              "query": {
                "type": "string"
              },
              "keywords": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "list": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "start_time": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "trans_chunks": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "content": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "SearchHistoryResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "data": {
            "type": "object",
            "properties": {
              "size": {
                "type": "integer"
              },
              "list": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "query": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "latest_t": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "WebhookCandidatesResponse": {
        "type": "object",
        "properties": {
          "files": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "filename": {
                  "type": "string"
                },
                "version_ms": {
                  "type": "integer",
                  "format": "int64"
                },
                "edit_time": {
                  "type": "integer",
                  "format": "int64"
                },
                "edit_from": {
                  "type": "string"
                }
              }
            }
          },
          "fetched_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "LooseEnvelope": {
        "type": "object",
        "description": "Loose Plaud envelope passed through verbatim. `data` shape varies and is not fixed by this API.",
        "properties": {
          "status": {
            "type": "integer",
            "description": "Plaud envelope status (0 = success)."
          },
          "msg": {
            "type": "string"
          },
          "data": {
            "type": "object",
            "additionalProperties": true,
            "description": "Upstream payload, passed through as-is."
          }
        }
      },
      "ShareStatesResponse": {
        "type": "object",
        "properties": {
          "private": {
            "$ref": "#/components/schemas/LooseEnvelope"
          },
          "public": {
            "$ref": "#/components/schemas/LooseEnvelope"
          }
        }
      },
      "RunningCombineTasksResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "msg": {
            "type": "string"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "In-flight combine tasks (element shape is loose; usually empty)."
          }
        }
      },
      "Filetag": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string",
            "description": "`#rrggbb`."
          }
        }
      },
      "TagListResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "data_filetag_total": {
            "type": "integer"
          },
          "data_filetag_list": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Filetag"
            }
          }
        }
      },
      "CreateTagResponse": {
        "type": "object",
        "description": "Upstream create envelope. `data` carries the new tag (including its id) but is loosely typed.",
        "properties": {
          "status": {
            "type": "integer"
          },
          "msg": {
            "type": "string"
          },
          "request_id": {
            "type": "string"
          },
          "data": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "AITaskStatusResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "msg": {
            "type": "string"
          },
          "data": {
            "type": "object",
            "properties": {
              "file_status_list": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": true
                },
                "description": "Per-file task status objects (loosely typed)."
              }
            }
          }
        }
      },
      "TransStatusResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "total_seconds": {
            "type": "number",
            "description": "Total transcription seconds on the plan."
          },
          "remain_total": {
            "type": "number",
            "description": "Remaining transcription seconds."
          }
        }
      },
      "TranscriptionQuotaResponse": {
        "type": "object",
        "properties": {
          "is_starter": {
            "type": "boolean"
          },
          "usage_reached": {
            "type": "boolean"
          }
        }
      },
      "SummaryModel": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Human-readable label."
          },
          "des": {
            "type": "string"
          },
          "isBeta": {
            "type": "boolean"
          },
          "is_inner": {
            "type": "boolean"
          },
          "model_name": {
            "type": "string",
            "description": "Identifier to pass as `llm` to the transsumm endpoints."
          }
        }
      },
      "SummaryModelsResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "msg": {
            "type": "string"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SummaryModel"
            }
          }
        }
      },
      "SyncResponse": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer"
          },
          "files": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FileBundle"
            }
          },
          "fetched_at": {
            "type": "string",
            "format": "date-time"
          },
          "stats": {
            "type": "object",
            "properties": {
              "bundle_errors": {
                "type": "integer",
                "description": "Files that had at least one sub-fetch error."
              },
              "elapsed_ms": {
                "type": "integer"
              }
            }
          }
        }
      },
      "DoctorResponse": {
        "type": "object",
        "description": "Live connectivity probe result.",
        "properties": {
          "ok": {
            "type": "boolean",
            "description": "True only when every check passed."
          },
          "api_domain": {
            "type": "string",
            "description": "The Plaud API host the probe used."
          },
          "checks": {
            "type": "object",
            "properties": {
              "user_me": {
                "type": "string",
                "enum": [
                  "ok",
                  "failed"
                ]
              },
              "device_list": {
                "type": "string",
                "enum": [
                  "ok",
                  "failed"
                ]
              }
            }
          },
          "user": {
            "type": "object",
            "additionalProperties": true,
            "description": "Present when the user check passed."
          },
          "devices": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "Present when the device check passed."
          },
          "user_error": {
            "type": "string"
          },
          "device_error": {
            "type": "string"
          },
          "hint": {
            "type": "string",
            "description": "Actionable hint (present on `401`)."
          }
        }
      },
      "TransSummResponse": {
        "type": "object",
        "description": "Immediate response from the async transsumm trigger. A successful call returns status=0 with msg=\"task processing\"; extra fields are captured loosely for forward-compat.",
        "properties": {
          "status": {
            "type": "integer"
          },
          "msg": {
            "type": "string"
          },
          "request_id": {
            "type": "string"
          },
          "auto_save": {
            "type": "boolean"
          },
          "ppc_status": {
            "type": "integer"
          },
          "err_code": {
            "type": "string"
          },
          "err_msg": {
            "type": "string"
          },
          "data_extra": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "QuotaError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "example": "insufficient_transcription_quota"
          },
          "message": {
            "type": "string"
          },
          "file_id": {
            "type": "string"
          },
          "remain_seconds": {
            "type": "number"
          },
          "required_seconds": {
            "type": "number"
          },
          "usage_reached": {
            "type": "boolean"
          },
          "is_starter": {
            "type": "boolean"
          }
        }
      },
      "TrashFilesRequest": {
        "type": "object",
        "required": [
          "file_ids"
        ],
        "properties": {
          "file_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "description": "Recording IDs to move to trash."
          }
        }
      },
      "CreateTagRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string",
            "description": "Optional `#rrggbb`."
          },
          "icon": {
            "type": "string",
            "description": "Optional 4-char hex glyph code (e.g. `e627`)."
          }
        }
      },
      "UpdateFileTagsRequest": {
        "type": "object",
        "required": [
          "file_id_list"
        ],
        "properties": {
          "file_id_list": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1
          },
          "filetag_id": {
            "type": "string",
            "description": "Tag id to assign. Empty string clears the tag from each file."
          }
        }
      },
      "OrganizeFilesRequest": {
        "type": "object",
        "required": [
          "file_ids",
          "tag_name"
        ],
        "properties": {
          "file_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1
          },
          "tag_name": {
            "type": "string"
          },
          "color": {
            "type": "string",
            "description": "Optional; only used when creating a new tag."
          },
          "icon": {
            "type": "string",
            "description": "Optional 4-char hex glyph code; only used when creating."
          },
          "match_mode": {
            "type": "string",
            "enum": [
              "exact",
              "fold"
            ],
            "default": "exact",
            "description": "`exact` = case-sensitive match; `fold` = case-insensitive."
          },
          "create_if_missing": {
            "type": "boolean",
            "default": true,
            "description": "Create the tag when no match exists."
          }
        }
      },
      "OrganizeFilesResponse": {
        "type": "object",
        "properties": {
          "tag": {
            "$ref": "#/components/schemas/Filetag"
          },
          "tag_created": {
            "type": "boolean",
            "description": "True if the tag was created during this call."
          },
          "files_assigned": {
            "type": "integer"
          }
        }
      },
      "RenameFileRequest": {
        "type": "object",
        "required": [
          "filename"
        ],
        "properties": {
          "filename": {
            "type": "string"
          }
        }
      },
      "DispatchRequest": {
        "type": "object",
        "required": [
          "webhook_url"
        ],
        "properties": {
          "webhook_url": {
            "type": "string",
            "description": "Destination URL (must be http:// or https://)."
          },
          "delivery_id": {
            "type": "string",
            "description": "Opaque id echoed back in the response; the handler does not dedupe on it."
          },
          "idempotency_key": {
            "type": "string",
            "description": "Opaque key logged for the orchestrator; not inspected here."
          },
          "transcript_format": {
            "type": "string",
            "enum": [
              "text",
              "markdown",
              "srt",
              "vtt",
              "json",
              "plain"
            ],
            "description": "Rendering of the outgoing `transcript` string. Omit for legacy plain text."
          },
          "include_list_metadata": {
            "type": "boolean",
            "default": false,
            "description": "Opt into note.version_ms/edit_from/md5 on the payload (costs an extra upstream list call)."
          }
        }
      },
      "DispatchResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "True only when the webhook returned a 2xx status."
          },
          "delivery_id": {
            "type": "string"
          },
          "webhook_status_code": {
            "type": "integer",
            "description": "HTTP status your webhook returned."
          },
          "webhook_response_snippet": {
            "type": "string",
            "description": "First ~1 KB of the webhook's response body."
          },
          "duration_ms": {
            "type": "integer",
            "format": "int64"
          },
          "error": {
            "type": "string",
            "description": "Set when the dispatch failed or the webhook returned non-2xx."
          }
        }
      },
      "TransSummRequest": {
        "type": "object",
        "description": "All fields optional; an empty body uses Plaud defaults.",
        "properties": {
          "language": {
            "type": "string",
            "description": "Transcript language; default `auto`."
          },
          "timezone": {
            "type": "integer",
            "description": "Signed UTC offset (hours). Default 0."
          },
          "diarization": {
            "type": "boolean",
            "description": "Speaker diarization. Default true."
          },
          "llm": {
            "type": "string",
            "description": "Summary model id (`model_name` from /summary/models). Default `auto`."
          },
          "summ_type": {
            "type": "string",
            "description": "Summary template. Default `AUTO-SELECT`."
          },
          "is_reload": {
            "type": "boolean",
            "description": "Force re-transcribe. Auto-detected when omitted (reloads if a transcript already exists)."
          },
          "check_quota": {
            "type": "boolean",
            "description": "Pre-flight quota check. Default false on `/transsumm`, true on `/transsumm/wait`. Insufficient quota returns 402."
          },
          "poll_interval_sec": {
            "type": "integer",
            "description": "(wait only) Poll interval, clamped to 1–30s."
          },
          "timeout_sec": {
            "type": "integer",
            "description": "(wait only) Max wait, clamped to 10s–30m."
          },
          "include": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "transcript",
                "summary",
                "share",
                "audio_url"
              ]
            },
            "description": "(wait only) Attachments to compose in the returned bundle."
          }
        }
      }
    }
  }
}