openapi: 3.0.0
info:
  title: Re:port Flow Content Service API
  description: |
    Re:port Flow Content Service provides PDF generation capabilities for your reports and documents.

    ## Authentication
    Two authentication methods are supported:

    - **API key (`appkey` header, lowercase)** — for single-workspace automation.
    - **OAuth 2.0 / OIDC (`Authorization: Bearer ...`)** — Authorization Code + PKCE for per-user
      delegation (Make.com etc.) and Client Credentials for backend-to-backend integrations. See
      the [OAuth 2.0 guide](https://doc.re-port-flow.com/docs/authentication/oauth) for details.

    ## Base URL
    `https://api.re-port-flow.com/v1`

    ## Limits
    - Maximum request body size: 50MB (after Base64 encoding, roughly 37MB of binary data).
    - Sync timeout: 120 seconds. Use the async endpoints for longer jobs.
    - Rate limit: per-workspace, 30 req/min for sync endpoints and 100 req/min for async / download endpoints. Exceeding the limit returns 429 with a `Retry-After` header (RFC 9110 §10.2.3).
  version: 1.0.0
  contact:
    name: Monepla Support
    url: https://re-port-flow.com

servers:
  - url: https://api.re-port-flow.com/v1
    description: Production server

security:
  - ApiKeyAuth: []
  - OAuth2:
      - pdf:generate
      - designs:read
      - templates:read

tags:
  - name: PDF Generation
    description: PDF file generation operations (sync and async)
  - name: File Download
    description: Download generated PDF files
  - name: Design Parameters
    description: Get design parameter structure

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: appkey
      description: |
        Authentication requires a single header:
        - `appkey`: Your application key (lowercase header name)

    OAuth2:
      type: oauth2
      description: |
        OAuth 2.0 / OpenID Connect. The OAuth flow (Authorize / Token / UserInfo) is hosted on
        `https://re-port-flow.com/api/v1` (a different host from this protected resource API).
        See the [OAuth 2.0 guide](https://doc.re-port-flow.com/docs/authentication/oauth).
      flows:
        authorizationCode:
          authorizationUrl: https://re-port-flow.com/api/v1/oauth/authorize
          tokenUrl: https://re-port-flow.com/api/v1/oauth/token
          refreshUrl: https://re-port-flow.com/api/v1/oauth/token
          scopes:
            openid: Confirm the user's id (OIDC)
            profile: Profile info (this implementation includes the email address)
            designs:read: Read designs (list and detail)
            designs:write: Create and edit designs
            templates:read: Read templates (list and detail)
            templates:write: Create and edit templates
            pdf:generate: Generate PDFs from a template
        clientCredentials:
          tokenUrl: https://re-port-flow.com/api/v1/oauth/token
          scopes:
            designs:read: Read designs (list and detail)
            designs:write: Create and edit designs
            templates:read: Read templates (list and detail)
            templates:write: Create and edit templates
            pdf:generate: Generate PDFs from a template

  schemas:
    ContentDto:
      type: object
      required:
        - fileName
        - params
      properties:
        fileName:
          type: string
          description: |
            ファイル名。`/ \\ : * ? " < > |` および制御文字以外は使用可能。
          example: invoice_2024.pdf
        shareType:
          type: string
          enum: ['01', '02', '03']
          default: '01'
          description: |
            共有タイプ（リクエスト側は数値コード）。
            - `"01"`: ワークスペース内共有（デフォルト、レスポンスでは `workspace`）
            - `"02"`: 招待者共有（レスポンスでは `invited`）
            - `"03"`: 公開URL共有（レスポンスでは `public`）
          example: '01'
        passcodeEnabled:
          type: boolean
          default: false
          description: |
            パスコード保護を有効化する。`true` の場合のみレスポンス `share.passcode` にサーバ生成パスコードが一度だけ返却される。
        passthrough:
          type: object
          additionalProperties:
            oneOf:
              - type: string
              - type: number
          description: |
            任意の文字列・数値 KV。レスポンスの `X-File-Mapping[].passthrough` または `files[].passthrough` にエコーバックされる。Webhook 追跡やバッチ処理の紐付けに活用できる。

            トップレベルの文字列・数値は帳票検索用メタデータとしても保存される（生成PDF内のXMPメタデータ、および Re:port Flow の帳票検索インデックス）。対象条件・上限・個人情報の扱いは[PDF生成ガイド](https://doc.re-port-flow.com/docs/guides/pdf-generation#passthrough-search-metadata)を参照。
          example:
            orderId: ORD-2024-001
            userId: user-abc123
        params:
          type: object
          additionalProperties: true
          description: テンプレートに埋め込むパラメータ
          example:
            customerName: "山田太郎"
            invoiceNumber: "INV-2024-001"
            items:
              - name: "商品A"
                price: 1000
                quantity: 2

    SingleReq:
      type: object
      required:
        - designId
        - version
        - content
      properties:
        designId:
          # format: uuid は付けない。本番の designId は "0eUDdgAjNXrrItA2" のような
          # 16 文字英数字で UUID ではない (本番 API の実応答で確認 / PRJ-3-1320)。
          # uuid と宣言すると、生成した検証コードや連携先が実在の ID を弾く。
          type: string
          description: デザインID
          example: "0eUDdgAjNXrrItA2"
        version:
          type: integer
          description: バージョン番号
          example: 1
        content:
          $ref: '#/components/schemas/ContentDto'

    MultipleReq:
      type: object
      required:
        - designId
        - version
        - contents
      properties:
        designId:
          # format: uuid は付けない。本番の designId は "0eUDdgAjNXrrItA2" のような
          # 16 文字英数字で UUID ではない (本番 API の実応答で確認 / PRJ-3-1320)。
          # uuid と宣言すると、生成した検証コードや連携先が実在の ID を弾く。
          type: string
          description: デザインID
          example: "0eUDdgAjNXrrItA2"
        version:
          type: integer
          description: バージョン番号
          example: 1
        contents:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/ContentDto'

    ExportRes:
      type: object
      properties:
        requestId:
          type: string
          format: uuid
          description: リクエストID（ダウンロードエンドポイントで使用）
          example: "550e8400-e29b-41d4-a716-446655440000"
        url:
          type: string
          format: uri
          description: |
            生成結果を確認できるアプリ画面（出力履歴）の URL。
            **ファイルの直接ダウンロード URL ではない**。ファイル取得には
            `/v1/file/download/{requestId}`（ZIP 一括）または
            `/v1/file/download/{requestId}/{fileId}`（個別 PDF）を使う。
          example: "https://re-port-flow.com/{workspaceId}/design/{designId}/outputs?requestId=550e8400-e29b-41d4-a716-446655440000"
        files:
          type: array
          items:
            type: object
            properties:
              fileName:
                type: string
              fileId:
                type: string
              passthrough:
                type: object
                additionalProperties:
                  oneOf:
                    - type: string
                    - type: number
                description: |
                  リクエスト時に指定した `passthrough` の値（指定時のみ）
              share:
                $ref: '#/components/schemas/ShareResponseDto'
    ShareResponseDto:
      type: object
      properties:
        shareType:
          type: string
          enum: [workspace, invited, public]
          description: |
            共有タイプ（レスポンス側は人間可読な名前）。リクエストの `01/02/03` と次のように対応する。
            - `workspace` ← `"01"`: ワークスペース内共有
            - `invited` ← `"02"`: 招待者共有
            - `public` ← `"03"`: 公開URL共有
        url:
          type: string
          format: uri
          description: |
            ファイル表示URL（全 shareType 共通: `/file/{requestId}/{fileId}`）
          example: "https://re-port-flow.com/file/550e8400-e29b-41d4-a716-446655440000/file_123456"
        passcodeEnabled:
          type: boolean
          description: パスコード有効フラグ
        passcode:
          type: string
          description: |
            サーバー生成パスコード（`passcodeEnabled=true` かつ生成直後の一度のみ返却）

    ParameterSpec:
      type: object
      required:
        - name
        - type
        - label
      properties:
        name:
          type: string
          description: PDF生成時に `params` へ渡すフィールド名
        type:
          type: string
          enum:
            - text
            - number
            - date
            - array
            - collection
            - boolean
          description: 外部連携向けのパラメータ型
        label:
          type: string
          description: 入力画面に表示するラベル
        description:
          type: string
          description: デザイン作成者が設定した任意の入力ガイド
        spec:
          type: array
          description: "`array` または `collection` の子フィールド定義"
          items:
            $ref: '#/components/schemas/ParameterSpec'

    GetDesignParametersResDto:
      type: array
      items:
        $ref: '#/components/schemas/ParameterSpec'
      example:
        - name: customerName
          type: text
          label: Customer name
        - name: amount
          type: number
          label: Amount
        - name: items
          type: array
          label: Items
          spec:
            - name: itemName
              type: text
              label: Item name
            - name: price
              type: number
              label: Price

    Error:
      type: object
      properties:
        statusCode:
          type: integer
          description: HTTPステータスコード
        message:
          type: string
          description: エラーメッセージ
        error:
          type: string
          description: エラータイプ

    DesignListItemResDto:
      type: object
      properties:
        id:
          type: string
          description: デザインID
        label:
          type: string
          description: デザイン名
        latestVersion:
          type: integer
          description: 最新バージョン番号
        thumbnail:
          type: string
          description: サムネイルURL
        updatedAt:
          type: string
          format: date-time
          description: 最終更新日時

    DesignListResDto:
      type: object
      properties:
        designs:
          type: array
          items:
            $ref: '#/components/schemas/DesignListItemResDto'
          description: デザイン一覧
        total:
          type: integer
          description: 総件数
        page:
          type: integer
          description: 現在のページ番号（1始まり）
        pageSize:
          type: integer
          description: 1ページあたりの件数（30件固定）
        totalPages:
          type: integer
          description: 総ページ数

paths:
  /file/sync/single:
    post:
      tags:
        - PDF Generation
      summary: 単一PDFの同期生成
      description: |
        指定されたデザインとパラメータから単一のPDFファイルを同期的に生成します。
        レスポンスボディとしてPDFファイルが直接返されます。

        **制限事項:**
        - リクエストサイズ上限: 50MB（Base64エンコード後、実質約37MB相当）
        - タイムアウト: 120秒（これより長い処理は非同期エンドポイントを使用）

        **Webhook通知:** PDF生成完了時、ワークスペースに設定されたWebhook URLに通知が送信されます。詳細は[Webhook通知ガイド](https://doc.re-port-flow.com/docs/guides/webhooks)を参照してください。
      operationId: syncSingle
      x-codeSamples:
        - lang: cURL
          source: |
            curl -X POST https://api.re-port-flow.com/v1/file/sync/single \
              -H "appkey: your-application-key" \
              -H "Content-Type: application/json" \
              -d '{
                "designId": "0eUDdgAjNXrrItA2",
                "version": 1,
                "content": {
                  "fileName": "invoice.pdf",
                  "params": {
                    "customerName": "山田太郎",
                    "invoiceNumber": "INV-2024-001",
                    "amount": 10000
                  }
                }
              }' \
              --output invoice.pdf
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SingleReq'
            example:
              designId: "0eUDdgAjNXrrItA2"
              version: 1
              content:
                fileName: "invoice.pdf"
                params:
                  customerName: "山田太郎"
                  invoiceNumber: "INV-2024-001"
                  amount: 10000
      responses:
        '200':
          description: PDF生成成功
          headers:
            Content-Type:
              schema:
                type: string
                example: application/pdf
            Content-Length:
              schema:
                type: integer
                example: 102400
              description: PDF ファイルサイズ (bytes)
            Content-Disposition:
              schema:
                type: string
                example: 'attachment; filename="invoice_2024.pdf"'
            File-URL:
              schema:
                type: string
                format: uri
                example: "https://re-port-flow.com/{workspaceId}/design/{designId}/outputs?requestId={requestId}"
              description: |
                生成結果を確認できるアプリ画面（出力履歴）の URL (`ExportRes.url` と同形式)。
                **ファイルの直接ダウンロード URL ではない**。開くには Re:port Flow へのログインが必要。
                プログラムからファイルを取得する場合は `/v1/file/download/{requestId}` を使う。
            Request-Id:
              schema:
                type: string
                format: uuid
                example: "550e8400-e29b-41d4-a716-446655440000"
              description: リクエスト ID。後続のファイルダウンロード API 等で使用。
            X-File-Mapping:
              schema:
                type: string
              description: |
                生成ファイルのメタデータと共有設定 (JSON 配列文字列)。
                **URL エンコード済み**で返るため、クライアントは `decodeURIComponent()` してから `JSON.parse()` すること。
                デコード後の構造は `[{ fileId, fileName, share, passthrough? }, ...]` (`share` は `ShareResponseDto`)。
          content:
            application/pdf:
              schema:
                type: string
                format: binary
        '400':
          description: リクエストが不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: 認証エラー (`appkey` ヘッダーの値が不正/失効)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '412':
          description: 認証ヘッダー欠落 (`appkey` ヘッダーが含まれていない)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: レート制限超過 (同期エンドポイントは 30 req/min)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: 内部サーバーエラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /file/async/single:
    post:
      tags:
        - PDF Generation
      summary: 単一PDFの非同期生成
      description: |
        指定されたデザインとパラメータから単一のPDFファイルを非同期的に生成します。
        即座にファイルURLとIDを返します。

        **Webhook通知:** PDF生成完了時、ワークスペースに設定されたWebhook URLに通知が送信されます。詳細は[Webhook通知ガイド](https://doc.re-port-flow.com/docs/guides/webhooks)を参照してください。
      operationId: asyncSingle
      x-codeSamples:
        - lang: cURL
          source: |
            curl -X POST https://api.re-port-flow.com/v1/file/async/single \
              -H "appkey: your-application-key" \
              -H "Content-Type: application/json" \
              -d '{
                "designId": "0eUDdgAjNXrrItA2",
                "version": 1,
                "content": {
                  "fileName": "invoice.pdf",
                  "params": {
                    "customerName": "山田太郎",
                    "invoiceNumber": "INV-2024-001",
                    "amount": 10000
                  }
                }
              }'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SingleReq'
      responses:
        '202':
          description: PDF生成を受け付けました
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExportRes'
        '400':
          description: リクエストが不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: 認証エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /file/sync/multiple:
    post:
      tags:
        - PDF Generation
      summary: 複数PDFの同期生成（ZIP）
      description: |
        指定されたデザインと複数のパラメータから複数のPDFファイルを同期的に生成し、ZIPで返します。

        **Webhook通知:** PDF生成完了時、ワークスペースに設定されたWebhook URLに通知が送信されます。詳細は[Webhook通知ガイド](https://doc.re-port-flow.com/docs/guides/webhooks)を参照してください。
      operationId: syncMultiple
      x-codeSamples:
        - lang: cURL
          source: |
            curl -X POST https://api.re-port-flow.com/v1/file/sync/multiple \
              -H "appkey: your-application-key" \
              -H "Content-Type: application/json" \
              -d '{
                "designId": "0eUDdgAjNXrrItA2",
                "version": 1,
                "contents": [
                  {
                    "fileName": "invoice_001.pdf",
                    "params": {
                      "customerName": "山田太郎",
                      "invoiceNumber": "INV-001"
                    }
                  },
                  {
                    "fileName": "invoice_002.pdf",
                    "params": {
                      "customerName": "佐藤花子",
                      "invoiceNumber": "INV-002"
                    }
                  }
                ]
              }' \
              --output invoices.zip
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MultipleReq'
            example:
              designId: "0eUDdgAjNXrrItA2"
              version: 1
              contents:
                - fileName: "invoice_001.pdf"
                  params:
                    customerName: "山田太郎"
                    invoiceNumber: "INV-001"
                - fileName: "invoice_002.pdf"
                  params:
                    customerName: "佐藤花子"
                    invoiceNumber: "INV-002"
      responses:
        '200':
          description: ZIP生成成功
          headers:
            Content-Type:
              schema:
                type: string
                example: application/zip
            Content-Length:
              schema:
                type: integer
                example: 307200
              description: ZIP ファイルサイズ (bytes)
            Content-Disposition:
              schema:
                type: string
                example: 'attachment; filename="files.zip"'
            File-URL:
              schema:
                type: string
                format: uri
                example: "https://re-port-flow.com/{workspaceId}/design/{designId}/outputs?requestId={requestId}"
              description: |
                生成結果を確認できるアプリ画面（出力履歴）の URL (`ExportRes.url` と同形式)。
                **ファイルの直接ダウンロード URL ではない**。開くには Re:port Flow へのログインが必要。
                プログラムからファイルを取得する場合は `/v1/file/download/{requestId}` を使う。
            Request-Id:
              schema:
                type: string
                format: uuid
                example: "550e8400-e29b-41d4-a716-446655440000"
              description: リクエスト ID。後続のファイルダウンロード API 等で使用。
            X-File-Mapping:
              schema:
                type: string
              description: |
                各 PDF のメタデータと共有設定 (JSON 配列文字列)。
                **URL エンコード済み**で返るため、クライアントは `decodeURIComponent()` してから `JSON.parse()` すること。
                デコード後の構造は `[{ fileId, fileName, share, passthrough? }, ...]` (`share` は `ShareResponseDto`)。
          content:
            application/zip:
              schema:
                type: string
                format: binary
        '400':
          description: リクエストが不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /file/async/multiple:
    post:
      tags:
        - PDF Generation
      summary: 複数PDFの非同期生成（ZIP）
      description: |
        指定されたデザインと複数のパラメータから複数のPDFファイルを非同期的に生成し、ZIPで保存します。

        **Webhook通知:** PDF生成完了時、ワークスペースに設定されたWebhook URLに通知が送信されます。詳細は[Webhook通知ガイド](https://doc.re-port-flow.com/docs/guides/webhooks)を参照してください。
      operationId: asyncMultiple
      x-codeSamples:
        - lang: cURL
          source: |
            curl -X POST https://api.re-port-flow.com/v1/file/async/multiple \
              -H "appkey: your-application-key" \
              -H "Content-Type: application/json" \
              -d '{
                "designId": "0eUDdgAjNXrrItA2",
                "version": 1,
                "contents": [
                  {
                    "fileName": "invoice_001.pdf",
                    "params": {
                      "customerName": "山田太郎",
                      "invoiceNumber": "INV-001"
                    }
                  },
                  {
                    "fileName": "invoice_002.pdf",
                    "params": {
                      "customerName": "佐藤花子",
                      "invoiceNumber": "INV-002"
                    }
                  }
                ]
              }'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MultipleReq'
      responses:
        '202':
          description: ZIP生成を受け付けました
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExportRes'

  /file/download/{uuid}:
    get:
      tags:
        - File Download
      summary: ZIP一括ダウンロード
      description: |
        指定されたUUIDのZIPファイルをダウンロードします。
      operationId: downloadZip
      x-codeSamples:
        - lang: cURL
          source: |
            curl -X GET https://api.re-port-flow.com/v1/file/download/550e8400-e29b-41d4-a716-446655440000 \
              -H "appkey: your-application-key" \
              --output files.zip
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: ファイルUUID
      responses:
        '200':
          description: ZIPダウンロード成功
          content:
            application/zip:
              schema:
                type: string
                format: binary
        '404':
          description: ファイルが見つかりません
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /file/download/{uuid}/{fileId}:
    get:
      tags:
        - File Download
      summary: 個別ファイルダウンロード
      description: |
        指定されたUUIDとファイルIDの個別ファイルをダウンロードします。
      operationId: downloadSingleFile
      x-codeSamples:
        - lang: cURL
          source: |
            curl -X GET https://api.re-port-flow.com/v1/file/download/550e8400-e29b-41d4-a716-446655440000/file_123456 \
              -H "appkey: your-application-key" \
              --output invoice.pdf
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: ファイルUUID
        - name: fileId
          in: path
          required: true
          schema:
            type: string
          description: ファイルID
      responses:
        '200':
          description: ファイルダウンロード成功
          headers:
            File-ID:
              schema:
                type: string
          content:
            application/pdf:
              schema:
                type: string
                format: binary
        '404':
          description: ファイルが見つかりません

  /file/design/parameter/{designId}:
    get:
      tags:
        - Design Parameters
      summary: デザインパラメータ構造を取得
      description: |
        指定されたデザインIDのパラメータ構造を取得します。
        PDFやサムネイル生成時に必要なパラメータのスキーマを確認できます。
      operationId: getDesignParameters
      x-codeSamples:
        - lang: cURL
          source: |
            curl -X GET https://api.re-port-flow.com/v1/file/design/parameter/0eUDdgAjNXrrItA2 \
              -H "appkey: your-application-key"
        - lang: cURL (with version)
          source: |
            curl -X GET "https://api.re-port-flow.com/v1/file/design/parameter/0eUDdgAjNXrrItA2?version=1" \
              -H "appkey: your-application-key"
      parameters:
        - name: designId
          in: path
          required: true
          schema:
            # 上記と同じ理由で format: uuid は付けない。
            type: string
          description: デザインID
        - name: version
          in: query
          required: false
          schema:
            type: integer
          description: デザインのバージョン番号（省略時は最新バージョン）
      responses:
        '200':
          description: パラメータ構造の取得成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetDesignParametersResDto'
        '404':
          description: デザインが見つかりません
        '500':
          description: 内部サーバーエラー
  /file/designs:
    get:
      tags:
        - Design Parameters
      summary: デザイン一覧を取得
      description: |
        ワークスペース内のデザイン一覧を取得（30件固定のページネーション付き）。
        MCPサーバー向けにデザインID・名称・最新バージョン・サムネイル・更新日時を返す。
        レート制限: 100 req/min
      operationId: listDesigns
      x-codeSamples:
        - lang: cURL
          source: |
            curl -X GET https://api.re-port-flow.com/v1/file/designs \
              -H "appkey: your-application-key"
        - lang: cURL (with page)
          source: |
            curl -X GET "https://api.re-port-flow.com/v1/file/designs?page=2" \
              -H "appkey: your-application-key"
      parameters:
        - name: page
          in: query
          required: false
          schema:
            type: integer
            default: 1
            minimum: 1
          description: ページ番号（1始まり）。省略時は1ページ目。1ページあたり30件固定。
      responses:
        '200':
          description: デザイン一覧の取得成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DesignListResDto'
        '500':
          description: 内部サーバーエラー
