openapi: 3.1.0
info:
  title: CreatorNode Audio API — Merge Fast
  description: |
    Lossless concatenation of audio files (MP3/AAC).
    Near-instant merge with no re-encoding.
  version: 1.0.0
  contact:
    name: CreatorNode Support
    url: https://creatornode.io/support
  license:
    name: Proprietary
    url: https://creatornode.io/legal
servers:
  - url: https://api.creatornode.io/audio
    description: Production
tags:
  - name: Audio
    description: Audio processing endpoints
paths:
  /v1/merge-fast:
    post:
      operationId: mergeAudioFast
      tags:
        - Audio
      summary: Lossless concatenation of audio files (no re-encoding)
      description: Merge MP3 or AAC files via lossless concatenation. Inputs must
        share codec, sample rate, and channel count. Default success is raw
        audio with X-Audio-* headers. `responseFormat=json` returns a base64
        JSON wrapper for smaller payloads; larger outputs should use
        `responseFormat=file`.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              $ref: "#/components/schemas/MergeAudioMultipartRequest"
            examples:
              basic:
                summary: Merge two MP3 files
                value:
                  metadata: '{"responseFormat": "file", "format": "auto"}'
                  files:
                    - (binary audio file 1)
                    - (binary audio file 2)
              jsonSuccess:
                summary: Merge two MP3 files and return JSON wrapper
                value:
                  metadata: '{"responseFormat": "json", "format": "auto"}'
                  files:
                    - (binary audio file 1)
                    - (binary audio file 2)
              withSpacing:
                summary: Merge three files with silence gaps
                value:
                  metadata: '{"responseFormat": "file", "format": "mp3", "spacing": [500, 1000]}'
                  files:
                    - (intro.mp3)
                    - (episode.mp3)
                    - (outro.mp3)
      responses:
        "200":
          description: Merged audio success response (`file` by default, or JSON wrapper
            when `responseFormat=json`)
          headers:
            Content-Disposition:
              description: Suggested filename for the merged output. Present only for
                `responseFormat=file` responses.
              schema:
                type: string
                example: attachment; filename="merged-abc-123.mp3"
            X-Audio-Format:
              description: Output format (mp3 or aac)
              schema:
                type: string
                example: mp3
            X-Audio-Codec:
              description: Audio codec name
              schema:
                type: string
                example: mp3
            X-Audio-Sample-Rate:
              description: Sample rate in Hz
              schema:
                type: integer
                example: 44100
            X-Audio-Channels:
              description: Channel count (1 = mono, 2 = stereo)
              schema:
                type: integer
                example: 2
            X-Audio-Duration-Ms:
              description: Total duration of merged output in milliseconds
              schema:
                type: integer
                example: 183520
            X-Audio-File-Count:
              description: Number of input files merged
              schema:
                type: integer
                example: 3
            X-Audio-Spacing-Count:
              description: Number of silence gaps inserted
              schema:
                type: integer
                example: 0
            X-Output-Size-Bytes:
              description: Size of output file in bytes
              schema:
                type: integer
                example: 2941952
            X-Processing-Time-Ms:
              description: Server-side processing time in milliseconds
              schema:
                type: integer
                example: 120
            X-Request-Id:
              description: Unique request identifier
              schema:
                type: string
                example: abc-123-def
          content:
            application/json:
              schema:
                type: object
                required:
                  - success
                  - data
                  - meta
                properties:
                  success:
                    type: boolean
                    enum:
                      - true
                  data:
                    type: object
                    required:
                      - contentType
                      - fileName
                      - dataBase64
                    properties:
                      contentType:
                        type: string
                        example: audio/mpeg
                      fileName:
                        type: string
                        example: merged-abc-123.mp3
                      dataBase64:
                        type: string
                        description: Base64-encoded merged audio body. Available only when the JSON
                          wrapper stays within the 50 MiB JSON artifact payload
                          limit.
                  meta:
                    type: object
                    required:
                      - requestId
                      - processingTimeMs
                    properties:
                      requestId:
                        type: string
                      processingTimeMs:
                        type: integer
                      format:
                        type: string
                        example: mp3
                      codec:
                        type: string
                        example: mp3
                      sampleRate:
                        type: integer
                        example: 44100
                      channels:
                        type: integer
                        example: 2
                      durationMs:
                        type: integer
                        example: 183520
                      fileCount:
                        type: integer
                        example: 3
                      spacingCount:
                        type: integer
                        example: 0
                      sizeBytes:
                        type: integer
                        example: 2941952
                      contentType:
                        type: string
                        example: audio/mpeg
                      filename:
                        type: string
                        example: merged-abc-123.mp3
                  recommendations:
                    type: array
                    items:
                      $ref: "#/components/schemas/Recommendation"
              examples:
                json:
                  summary: JSON success wrapper
                  value:
                    success: true
                    data:
                      contentType: audio/mpeg
                      fileName: merged-abc-123.mp3
                      dataBase64: SUQzBAAAAAAAF1RTU0UAAAAPAAADTGF2ZjU4LjI5LjEwMAAAAAAAAAAAAAAA//uQxAADBzQ...
                    meta:
                      requestId: abc-123-def
                      processingTimeMs: 120
                      format: mp3
                      codec: mp3
                      sampleRate: 44100
                      channels: 2
                      durationMs: 183520
                      fileCount: 3
                      spacingCount: 0
                      sizeBytes: 2941952
                      contentType: audio/mpeg
                      filename: merged-abc-123.mp3
            audio/mpeg:
              schema:
                type: string
                format: binary
                description: Raw MP3 audio data
            audio/aac:
              schema:
                type: string
                format: binary
                description: Raw AAC audio data
        "400":
          description: >
            Request validation error. Possible error codes:

            `VALIDATION_ERROR`, `AUDIO_INCOMPATIBLE_STREAMS`,
            `AUDIO_UNSUPPORTED_FORMAT`,

            `AUDIO_PROBE_FAILED`, `AUDIO_FORMAT_MIX`.

            Errors are always JSON regardless of `responseFormat`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                incompatibleStreams:
                  summary: Mismatched sample rates
                  value:
                    success: false
                    error:
                      code: AUDIO_INCOMPATIBLE_STREAMS
                      message: "Stream parameter mismatch: sampleRate"
                      details:
                        fileIndex: 1
                        expected:
                          sampleRate: 44100
                        actual:
                          sampleRate: 48000
                        mismatchField: sampleRate
                    meta:
                      requestId: abc-123-def
                    recommendations:
                      - type: fix
                        title: Re-encode to match
                        message: All files must have the same sample rate (44100 Hz expected). Re-encode
                          file at index 1 before merging.
                        priority: high
                formatMix:
                  summary: Mixed MP3 and AAC files
                  value:
                    success: false
                    error:
                      code: AUDIO_FORMAT_MIX
                      message: All files must use the same codec for lossless merge
                      details:
                        fileIndex: 2
                        expected:
                          codec: mp3
                        actual:
                          codec: aac
                        mismatchField: codec
                    meta:
                      requestId: abc-123-def
                tooFewFiles:
                  summary: Only one file provided
                  value:
                    success: false
                    error:
                      code: VALIDATION_ERROR
                      message: At least 2 audio files are required for merging
                      details:
                        fileCount: 1
                        minimum: 2
                    meta:
                      requestId: abc-123-def
        "401":
          description: Unauthorized — invalid or missing API key
        "413":
          description: JSON wrapper payload would be too large; retry with
            `responseFormat=file`
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                success: false
                error:
                  code: ARTIFACT_TOO_LARGE
                  message: JSON response mode supports only smaller artifacts. Use
                    responseFormat=file for larger outputs.
                  details:
                    responseFormat: json
                    outputSizeBytes: 41943040
                    estimatedBase64Bytes: 55924056
                    maxJsonPayloadBytes: 52428800
                    suggestedResponseFormat: file
                meta:
                  requestId: abc-123-def
        "429":
          description: Rate limited — too many requests
        "500":
          description: Server error during audio processing
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                success: false
                error:
                  code: AUDIO_PROCESSING_FAILED
                  message: Audio processing failed during merge
                meta:
                  requestId: abc-123-def
        "504":
          description: Processing timeout
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                success: false
                error:
                  code: PROCESSING_TIMEOUT
                  message: Audio processing exceeded the time limit
                meta:
                  requestId: abc-123-def
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: APIM subscription key for authenticated access. Without a key,
        requests use free tier limits.
  schemas:
    Recommendation:
      type: object
      required:
        - type
        - title
        - message
      properties:
        type:
          type: string
          enum:
            - upgrade
            - top_up
            - feature
            - tip
            - warning
            - fix
        title:
          type: string
        message:
          type: string
        action:
          type: object
          required:
            - label
            - url
          properties:
            label:
              type: string
            url:
              type: string
              format: uri
        priority:
          type: string
          enum:
            - low
            - medium
            - high
          default: low
    ErrorResponse:
      type: object
      required:
        - success
        - error
      properties:
        success:
          type: boolean
          enum:
            - false
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: >
                Error code. Possible values:

                VALIDATION_ERROR, AUDIO_INCOMPATIBLE_STREAMS,
                AUDIO_UNSUPPORTED_FORMAT,

                AUDIO_PROBE_FAILED, AUDIO_FORMAT_MIX, AUDIO_PROCESSING_FAILED,

                PROCESSING_TIMEOUT, PROCESSING_ERROR, UPLOAD_SIZE_EXCEEDED,
                TOO_MANY_FILES
            message:
              type: string
            details:
              type: object
              additionalProperties: true
        meta:
          type: object
          properties:
            requestId:
              type: string
        recommendations:
          type: array
          items:
            $ref: "#/components/schemas/Recommendation"
    MergeAudioMetadata:
      type: object
      description: Optional JSON metadata field in the multipart request body.
      properties:
        responseFormat:
          type: string
          enum:
            - json
            - file
          default: file
          description: |
            Success response transport.
            - `file` (default): raw audio body with metadata in headers.
            - `json`: JSON wrapper with base64-encoded audio data and metadata.
        format:
          type: string
          enum:
            - mp3
            - aac
            - auto
          default: auto
          description: |
            Output audio format. `auto` detects from the first file's codec.
            Explicit format must match the actual codec of all input files.
        spacing:
          type: array
          description: >
            Silence durations in milliseconds to insert between tracks.

            `spacing[0]` = silence between file 0 and file 1, etc.

            Missing entries default to 0 (no silence). Extra entries are
            ignored.
          items:
            type: integer
            minimum: 0
            maximum: 10000
          maxItems: 19
          example:
            - 500
            - 1000
    MergeAudioMultipartRequest:
      type: object
      description: |
        Multipart form data with audio files and optional JSON metadata.
        Files are concatenated in the order they appear in the request.
      required:
        - files
      properties:
        metadata:
          type: string
          description: JSON string containing MergeAudioMetadata. Optional.
          example: '{"responseFormat":"file","format":"auto","spacing":[500,1000]}'
        files:
          type: array
          description: "Audio files to merge (min 2). Accepted types: audio/mpeg,
            audio/aac, audio/mp4, audio/x-m4a."
          items:
            type: string
            format: binary
          minItems: 2
          maxItems: 20
    MergeAudioDemoRequest:
      type: object
      description: >
        Demo endpoint accepts the same shape as the real `/v1/merge-fast`
        metadata.


        The demo response is deterministic and does **not** depend on your
        input.

        The request is shown here purely to demonstrate how to call the API.
      properties:
        responseFormat:
          type: string
          enum:
            - json
            - file
          default: file
          description: Success response transport (ignored by demo).
        format:
          type: string
          enum:
            - mp3
            - aac
            - auto
          default: auto
          description: Output audio format (ignored by demo).
        spacing:
          type: array
          description: >
            Silence durations in milliseconds to insert between tracks (ignored
            by demo).
          items:
            type: integer
            minimum: 0
            maximum: 10000
          maxItems: 19
          example:
            - 500
            - 1000
      example:
        responseFormat: file
        format: mp3
        spacing:
          - 500
          - 1000
