openapi: 3.1.0
info:
  title: CreatorNode Science API — Chemistry Compare
  description: |
    Compare two molecules by identity (canonical SMILES match), similarity
    (Tanimoto on Morgan fingerprints), or substructure (bidirectional match).
  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/science
    description: Production
tags:
  - name: Chemistry
    description: Chemistry endpoints
paths:
  /v1/chemistry/compare:
    post:
      operationId: compareChemistry
      tags:
        - Chemistry
      summary: Compare two molecules (identity, similarity, substructure)
      description: Compare two molecules (SMILES, InChI, or MDL Molfile) by identity,
        similarity (Tanimoto/Morgan), substructure, or full mode. Parse failures
        return HTTP 200 with parseErrors.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CompareChemistryRequest"
            examples:
              identity_same_molecule_different_formats:
                summary: Identity — same molecule, different formats (SMILES vs InChI)
                value:
                  molecules:
                    - input: CC(=O)Oc1ccccc1C(=O)O
                      format: smiles
                    - input: InChI=1S/C9H8O4/c1-6(10)13-8-5-3-2-4-7(8)9(11)12/h2-5H,1H3,(H,11,12)
                      format: inchi
                  mode: identity
              similarity_aspirin_vs_ibuprofen:
                summary: Similarity — aspirin vs ibuprofen (Tanimoto)
                value:
                  molecules:
                    - input: CC(=O)Oc1ccccc1C(=O)O
                      format: smiles
                    - input: CC(C)Cc1ccc(cc1)C(C)C(=O)O
                      format: smiles
                  mode: similarity
                  options:
                    fingerprintRadius: 2
                    fingerprintBits: 2048
              substructure_phenol_in_aspirin:
                summary: Substructure — does phenol match inside aspirin?
                value:
                  molecules:
                    - input: c1ccc(cc1)O
                      format: smiles
                    - input: CC(=O)Oc1ccccc1C(=O)O
                      format: smiles
                  mode: substructure
              full_benzene_vs_phenol:
                summary: Full — identity + similarity + substructure
                value:
                  molecules:
                    - input: c1ccccc1
                      format: smiles
                    - input: c1ccc(cc1)O
                      format: smiles
                  mode: full
      responses:
        "200":
          description: Comparison result (check for data.parseErrors if present)
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/CompareChemistrySuccessResponse"
                  - $ref: "#/components/schemas/CompareChemistryParseErrorResponse"
        "400":
          description: Request-level validation error (INPUT_TOO_LARGE, MODE_NOT_AVAILABLE)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Unauthorized
        "429":
          description: Rate limited
        "503":
          description: Service temporarily saturated
          headers:
            Retry-After:
              description: Seconds before retrying the request
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                success: false
                error:
                  code: SERVICE_BUSY
                  message: Chemistry service is temporarily saturated. Retry shortly.
                meta:
                  requestId: abc123
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 (e.g. VALIDATION_ERROR, INPUT_TOO_LARGE,
                PROCESSING_TIMEOUT)
            message:
              type: string
            details:
              type: object
              additionalProperties: true
        meta:
          type: object
          properties:
            requestId:
              type: string
        recommendations:
          type: array
          items:
            $ref: "#/components/schemas/Recommendation"
    CompareChemistryMoleculeInput:
      type: object
      required:
        - input
      properties:
        input:
          type: string
          minLength: 1
          maxLength: 4000
          description: Chemical notation (SMILES, InChI, or MDL Molfile).
          example: CC(=O)Oc1ccccc1C(=O)O
        format:
          type: string
          enum:
            - auto
            - smiles
            - inchi
            - mol
          default: auto
          description: Optional format hint.
    CompareChemistryOptions:
      type: object
      description: Fingerprint configuration for similarity mode.
      properties:
        fingerprintRadius:
          type: integer
          minimum: 1
          maximum: 4
          default: 2
          description: Morgan fingerprint radius.
        fingerprintBits:
          type: integer
          enum:
            - 1024
            - 2048
          default: 2048
          description: Morgan fingerprint bit length.
    CompareChemistryRequest:
      type: object
      required:
        - molecules
        - mode
      properties:
        molecules:
          type: array
          minItems: 2
          maxItems: 2
          items:
            $ref: "#/components/schemas/CompareChemistryMoleculeInput"
          description: Exactly two molecules to compare.
        mode:
          type: string
          enum:
            - identity
            - similarity
            - substructure
            - full
          description: >
            Comparison mode. Available modes depend on the current plan and
            configuration.

            `full` runs all three modes.
        options:
          $ref: "#/components/schemas/CompareChemistryOptions"
      example:
        molecules:
          - input: CC(=O)Oc1ccccc1C(=O)O
            format: smiles
          - input: InChI=1S/C9H8O4/c1-6(10)13-8-5-3-2-4-7(8)9(11)12/h2-5H,1H3,(H,11,12)
            format: inchi
        mode: identity
    CompareChemistryMeta:
      type: object
      required:
        - requestId
        - processingTimeMs
        - rdkitVersion
        - cached
      properties:
        requestId:
          type: string
        processingTimeMs:
          type: integer
          minimum: 0
        rdkitVersion:
          type: string
          example: 2025.3.4
        cached:
          type: boolean
    CompareChemistryMoleculeOutput:
      type: object
      required:
        - canonicalSmiles
        - format
      properties:
        canonicalSmiles:
          type: string
          description: Canonical SMILES from RDKit.
        format:
          type: string
          enum:
            - smiles
            - inchi
            - mol
          description: Detected input format.
    CompareChemistryIdentity:
      type: object
      required:
        - identical
      properties:
        identical:
          type: boolean
          description: Whether canonical SMILES are equal.
    CompareChemistrySimilarity:
      type: object
      required:
        - tanimoto
        - fingerprintRadius
        - fingerprintBits
        - interpretation
      properties:
        tanimoto:
          type: number
          minimum: 0
          maximum: 1
          description: Tanimoto coefficient on Morgan fingerprints.
        fingerprintRadius:
          type: integer
        fingerprintBits:
          type: integer
        interpretation:
          type: string
          enum:
            - identical
            - very similar
            - similar
            - moderately similar
            - dissimilar
            - unrelated
    CompareChemistrySubstructure:
      type: object
      required:
        - aInB
        - bInA
        - relationship
      properties:
        aInB:
          type: boolean
          description: Whether molecule A is a substructure of molecule B.
        bInA:
          type: boolean
          description: Whether molecule B is a substructure of molecule A.
        relationship:
          type: string
          enum:
            - a_in_b
            - b_in_a
            - mutual
            - none
    CompareChemistrySuccessData:
      type: object
      required:
        - molecules
      properties:
        molecules:
          type: array
          minItems: 2
          maxItems: 2
          items:
            $ref: "#/components/schemas/CompareChemistryMoleculeOutput"
        identity:
          $ref: "#/components/schemas/CompareChemistryIdentity"
        similarity:
          $ref: "#/components/schemas/CompareChemistrySimilarity"
        substructure:
          $ref: "#/components/schemas/CompareChemistrySubstructure"
    CompareChemistryParseError:
      type: object
      required:
        - index
        - format
        - message
      properties:
        index:
          type: integer
          enum:
            - 0
            - 1
          description: Which molecule failed (0 or 1).
        format:
          type: string
          enum:
            - smiles
            - inchi
            - mol
            - unknown
        message:
          type: string
        details:
          type: string
          description: Optional debug detail. May be omitted in production.
        hintCode:
          type: string
          description: Machine-readable hint code for handling or UI messaging.
        hint:
          type: string
          description: Safe, user-facing hint to resolve the parsing failure.
    CompareChemistryParseErrorData:
      type: object
      required:
        - parseErrors
      properties:
        parseErrors:
          type: array
          minItems: 1
          maxItems: 2
          items:
            $ref: "#/components/schemas/CompareChemistryParseError"
    CompareChemistrySuccessResponse:
      type: object
      required:
        - success
        - data
        - meta
      properties:
        success:
          type: boolean
          enum:
            - true
        data:
          $ref: "#/components/schemas/CompareChemistrySuccessData"
        meta:
          $ref: "#/components/schemas/CompareChemistryMeta"
        recommendations:
          type: array
          items:
            $ref: "#/components/schemas/Recommendation"
    CompareChemistryParseErrorResponse:
      type: object
      required:
        - success
        - data
        - meta
      properties:
        success:
          type: boolean
          enum:
            - true
        data:
          $ref: "#/components/schemas/CompareChemistryParseErrorData"
        meta:
          $ref: "#/components/schemas/CompareChemistryMeta"
        recommendations:
          type: array
          items:
            $ref: "#/components/schemas/Recommendation"
    CompareChemistryDemoRequest:
      type: object
      description: >
        Demo endpoint accepts the same shape as the full `/v1/chemistry/compare`
        request.


        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:
        molecules:
          type: array
          minItems: 2
          maxItems: 2
          items:
            $ref: "#/components/schemas/CompareChemistryMoleculeInput"
          description: Exactly two molecules to compare (ignored by demo).
        mode:
          type: string
          enum:
            - identity
            - similarity
            - substructure
            - full
          description: Comparison mode (ignored by demo).
        options:
          $ref: "#/components/schemas/CompareChemistryOptions"
      example:
        molecules:
          - input: CC(=O)Oc1ccccc1C(=O)O
            format: smiles
          - input: O=C(O)c1ccccc1O
            format: smiles
        mode: full
    CompareChemistryDemoResponse:
      $ref: "#/components/schemas/CompareChemistrySuccessResponse"
