openapi: 3.0.1
info:
  title: File Import API v1
  description: |
    Sansan Data Hub にファイルを取り込むためのAPIです。
    ファイル取り込み処理は非同期で行われ、Sansan Data Hub 内部では`ファイル取り込みジョブ`として管理されます。
    
    ご利用には事前の設定(Sansan Data Hub に取り込む項目の定義)が必要です。
  version: v1
servers:
  - url: https://api.datahub.sansan.com/file/import/v1
paths:
  '/{dataSourceId}/jobs':
    post:
      tags:
        - Jobs
      summary: Sansan Data Hub にファイルを取り込みます。
      description: |
        リクエストボディに設定されたファイルを `Content-Type` ヘッダの書式に従い取り込みを行います。`charset` を指定する場合は `UTF-8` のみを受け付けます。 成功時は、ファイル取り込みジョブの情報をレスポンスとして返却します。
        
        ファイル取り込み処理は非同期で行われるので、必要に応じて `GET /{dataSourceId}/jobs/{jobId}` を用いてファイル取り込みジョブの状態を確認してください。
        
        ### API 制限
        
        * 1回のリクエストで取り込めるリクエストボディのサイズは50MB(50MiB)までです。それを超えるサイズのリクエストボディでリクエストが行われた場合はステータスコード `413` が返却されます。
      parameters:
        - name: dataSourceId
          in: path
          description: データソースID
          required: true
          schema:
            type: string
          example: 835eff75070a4351a193dfa7d8aff89c
      requestBody:
        description: Sansan Data Hub に取り込むファイル
        content:
          text/csv:
            schema:
              example: |
                firstName,lastName,mobile,companyName
                John,Doh,000-1234-1111,Some Corp
                Jane,Doh,000-1234-0000,Some Inc
          application/x-ndjson:
            schema:
              example: |
                {"firstName" : "John", "lastName" : "Doh", "mobile" : "000-1234-1111", "companyName" : "Some Corp"}
                {"firstName" : "Jane", "lastName" : "Doh", "mobile" : "000-1234-0000", "companyName" : "Some Inc"}
        required: true
      responses:
        '200':
          description: ファイル取り込み処理が開始し、ファイル取り込みジョブの作成に成功しました
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ImportJob'
        '400':
          description: リクエストパラメータが不正です
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '404':
          description: 指定されたデータソースIDに対応する構成の定義が見つかりません
        '413':
          description: リクエストボディのサイズが許容上限を超えています
        '415':
          description: 未サポートの `Content-Type`、`charset` が指定されました
        '500':
          description: 想定外のエラーが発生しました
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
      security:
        - OAuth2:
            - file/import:write
  '/{dataSourceId}/jobs/{jobId}':
    get:
      tags:
        - Jobs
      summary: ファイル取り込みジョブを取得します。
      description: |
        ファイル取り込みジョブを取得します。ジョブにはジョブの状態や、エラーの場合はエラー内容が含まれます。
      parameters:
        - name: jobId
          in: path
          description: ファイル取り込みジョブID
          required: true
          schema:
            type: string
          example: 92494fcd18154f68bc53dd4604afe72e
        - name: dataSourceId
          in: path
          description: データソースID
          required: true
          schema:
            type: string
          example: 835eff75070a4351a193dfa7d8aff89c
      responses:
        '200':
          description: ファイル取り込みジョブの取得に成功しました
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ImportJob'
        '400':
          description: リクエストパラメータが不正です
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '404':
          description: 指定されたデータソースID、ファイル取り込みジョブIDに対応するジョブが見つかりません
        '500':
          description: 想定外のエラーが発生しました
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
      security:
        - OAuth2:
            - file/import:read
components:
  schemas:
    ImportJob:
      type: object
      properties:
        tenantId:
          type: string
          description: テナントID
          example: sometenant
        dataSourceId:
          type: string
          description: データソース ID
          example: f6b104f85f1740008bd9ec87cb4bb8e3
        jobId:
          type: string
          description: ファイル取り込みジョブID
          example: 87b7ecff7ffd409ba7c85fc0d9394e29
        status:
          enum:
            - Queued
            - Running
            - Aborted
            - Failed
            - Succeeded
          type: string
          description: |
            ファイル取り込みジョブの状態を表します。
             * `Queued` - ジョブがキューに載せられました。
             * `Running` - ジョブの実行中です。
             * `Aborted` - ジョブの実行中に何らかのエラーが発生し中断しました。エラー詳細は `jobError` を参照してください。
             * `Failed` - ジョブの実行中に何らかのエラーが発生し失敗しました。エラー詳細は `rowErrors` を参照してください。
             * `Succeeded` - ジョブが成功し、ファイルの取り込みに成功しました。
        rowCount:
          type: number
          description: 取り込んだファイル行数
          example: 1234
        requestInformation:
          type: object
          properties:
            source:
              enum:
                - API
                - Manual
              type: string
              description: |
                ファイル取り込みジョブの実行元情報です。API経由のリクエストの場合は常に `API` です。
                 * `API` - File Import API経由でファイル取り込みジョブが実行されました。
                 * `Manual` - Data Hub Web画面経由でファイル取り込みジョブが実行されました。
            fileName:
              type: string
              description: 取り込みファイル名
              example: ''
            contentType:
              type: string
              description: リクエスト時の `Content-Type` です。
              example: text/csv
            contentLength:
              type: number
              description: リクエスト時の `Content-Length` です。
              example: 6789
            clientId:
              type: string
              description: リクエスト元の Oauth2.0 Client ID です。
              example: a78cef06426c414d8182ddfed87c17eb
            userId:
              type: string
              description: リクエスト元の User ID です。
              example: bdcb88aa-275b-f61c-5002-24c742546157
          description: ファイル取り込みジョブのリクエスト情報です。
        jobError:
          type: object
          properties:
            code:
              enum:
                - INVALID_CSV_FILE_FORMAT
                - INVALID_JSONL_FILE_FORMAT
                - INVALID_HEADER_NAME
                - INVALID_FIELD_NAME
                - INTERNAL_SERVER_ERROR
              type: string
              description: |
                * `INVALID_CSV_FILE_FORMAT` - `Content-Type` としてCSV(`text/csv`)が指定されているにも関わらず、ファイル内容がCSVとして不正です。`message` に書式が不正な行番号が含まれます。
                * `INVALID_JSONL_FILE_FORMAT` - `Content-Type` として改行区切りのJSON(`application/x-ndjson`)が指定されているにも関わらず、ファイル内容がJSONとして不正です。`message` に書式が不正な行番号が含まれます。
                * `INVALID_HEADER_NAME` - CSV に不正なヘッダー名が含まれています。e.g. ヘッダー名が空文字になっている。
                * `INVALID_FIELD_NAME` - 改行区切りの JSON に不正なフィールド名が含まれています。e.g. フィールド名が空文字になっている。
                * `INTERNAL_SERVER_ERROR` - 想定外のエラーが発生しました。時間を空けて再実行してください。継続して発生するようならサポートに問い合わせてください。
            message:
              type: string
              description: エラーメッセージ
              example: The CSV format on line 46 is invalid.
          description: ファイル取り込みジョブが中断された際のエラー内容です。 `status` が `Aborted` の際に設定されます。
          nullable: true
        rowErrors:
          type: array
          items:
            type: object
            properties:
              code:
                enum:
                  - TRANSFORMATION_FAILED
                  - MISSING_REQUIRED_FIELD
                  - UNIQUE_KEY_IS_TOO_LONG
                type: string
                description: |
                  * `TRANSFORMATION_FAILED` - 取り込みファイルの内容が変換できない場合に発生します。 e.g. 日時型を期待しているのに、ファイルの値が日時として変換できない。
                  エラー詳細は `message` に含まれます。
                  * `MISSING_REQUIRED_FIELD` - 必須項目が存在しない場合に発生します。 必須項目名は `message` に含まれます。
                  * `UNIQUE_KEY_IS_TOO_LONG` - ユニークキーが160文字を超えた場合に発生します。160文字を超えたユニークキーは `message` に含まれます。
              rowNumber:
                type: string
                description: エラーが発生した行番号
                example: '5'
              message:
                type: string
                description: エラーメッセージ
                example: Failed to convert 'invalid datetime string' to a DateTime.
          description: ファイル取り込みジョブが失敗した際のエラー内容です。取り込みファイルの行に対応しており、最大100件まで返却されます(100件以上エラーが発生した場合も100件までしか返却されません)。 `status` が `Failed` の際に設定されます。
        queuedAt:
          type: string
          description: ジョブがキューされた時間
          example: '2022-08-29T04:21:10.360142+00:00'
        lastUpdatedAt:
          type: string
          description: ジョブの最終更新日時
          example: '2022-08-29T04:31:40.760139+00:00'
        finishedAt:
          type: string
          description: ジョブの終了時間
          nullable: true
          example: '2022-08-29T04:31:40.760139+00:00'
      description: ファイル取り込みジョブ
    ProblemDetails:
      type: object
      properties:
        type:
          type: string
          description: 問題種別を示すRFCへの参照です。
        title:
          type: string
          description: エラー概要です。
        status:
          type: integer
          description: 'アプリケーションサーバが返却したオリジナルのHTTPステータスコード ([[RFC7231], Section 6](https://tools.ietf.org/html/rfc7231#section-6)) です。'
          nullable: true
        detail:
          type: string
          description: エラー詳細です。
          nullable: true
        traceId:
          type: string
          description: 内部的に用いるエラーを追跡するためのIDです。
          nullable: true
        requiredScope:
          type: string
          description: アクセスに必要なスコープが不足している場合に必要なスコープを示します。
          nullable: true
      description: 'エラー詳細を含む [RFC7807](https://tools.ietf.org/html/rfc7807) オブジェクトです。'
      example: |
        {
          "type": "https://tools.ietf.org/html/rfc6749#section-3.3",
          "title": "Insufficient scope"
          "status": 401
          "traceId": "2bb1bebd-6a7a-43fc-bae2-af59ed9b857c",
          "requiredScope": "file/import:write"
        } 
  securitySchemes:
    OAuth2:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: https://account.datahub.sansan.com/connect/token
          scopes:
            echo: Echo API((Example)) の呼び出し
            change-feed:read: Change Feed API の読み取り
            file/import:read: File Import API の読み取り
            file/import:write: File Import API の書き込み