---

swagger: "2.0"

info:
  description: "API specification for the EMF Experiments Service."
  version: "1.4.0"
  title: "omlet_experiments_api"
  contact:
    name: "Infra"
    email: "infrateam@zoox.com"
    url: "https://git.zooxlabs.com/zooxco/driving"

basePath: "/v0"

tags:
  - name: "comparison_plugins"
    description: "Plugins for external comparison tools."
  - name: "experiments"
    description: "Experiments."
  - name: "latest_metrics"
    description: "The latest metrics that have been reported for an experiment."
  - name: "links"
    description: "Links related to an experiment."
  - name: "metric_types"
    description: "The types of metrics."
  - name: "projects"
    description: "Projects into which experiments are grouped."
  - name: "tags"
    description: "Tags which are used to annotate experiments."

schemes:
  - "http"

paths:
  "/comparison-plugins":
    get:
      tags:
        - "comparison_plugins"
      summary: "List comparison plugins."
      description: ""
      operationId: "comparisonPluginGet"
      produces:
        - "application/json"
      responses:
        "200":
          description: "Successful operation."
          schema:
            $ref: "#/definitions/ComparisonPluginList"
        "404":
          description: "Not found."
          schema:
            $ref: "#/definitions/ErrorResponse"
        "500":
          description: "Internal server error."
          schema:
            $ref: "#/definitions/ErrorResponse"

  "/experimentsGet":
    post:
      tags:
        - "experiments"
      summary: "List experiments by query."
      description: ""
      operationId: "experimentsGet"
      produces:
        - "application/json"
      parameters:
        - name: "requestBody"
          in: "body"
          description: "The request body."
          required: true
          schema:
            $ref: "#/definitions/ExperimentsGetRequestBody"
      responses:
        "200":
          description: "Successful operation."
          schema:
            $ref: "#/definitions/PaginatedExperimentsList"
          examples:
            application/json:
              data:
                - command: "train badass network"
                  docker_image_digest: "sha256:49414f826ff99061c6526cfc5c435c3f26f6263dd1fbe64f4bd35599a480fb6a"
                  docker_image_tag: "driving:13"
                  description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
                  completionTime: 1507074465000
                  environment: "ZOOX_WORKSPACE=why"
                  gitSha: "9eaed2cba5c2f7bbfede687eeb8fd2452827793"
                  gitDirty: false
                  id: "abcd-efgh-ijkl"
                  name: "experiment1"
                  owner: "andres"
                  project:
                    name: "project1"
                    description: "project1 description"
                  repository: "driving"
                  creationTime: 1507073465000
                  state: "Succeeded"
                  links:
                    - url: "http://www.google.com"
                      description: "Really?"
                    - url: "http://www.yahoo.com"
                      description: ":("
                  params:
                    - parameterType:
                        name: "Learning Rate"
                        type: "float"
                      valBool: null
                      valFloat: 0.1
                      valInt: null
                      valStr: null
                    - parameterType:
                        name: "Learning Rate Schedule"
                        type: "string"
                      valBool: null
                      valFloat: null
                      valInt: null
                      valStr: "Exponential Decay"
                  tags:
                    - name: "tag1"
                    - name: "tag2"
                - command: "train meh network"
                  docker_image_digest: "sha256:49414f826ff99061c6526cfc5c435c3f26f6263dd1fbe64f4bd35599a480fb6a"
                  docker_image_tag: "driving:12"
                  description: "asdfasdfasdasdf"
                  completionTime: 1507074465000
                  environment: "ZOOX_WORKSPACE=whynot"
                  gitSha: "1010101010"
                  gitDirty: false
                  id: "an-id-for-u"
                  name: "experiment10"
                  owner: "andres"
                  project:
                    name: "project1"
                    description: "project1 description"
                  repository: "driving"
                  creationTime: 1507073465000
                  state: "Running"
                  links:
                    - url: "http://www.gweegle.com"
                      description: "Really?"
                  params:
                    - parameterType:
                        name: "Learning Rate"
                        type: "float"
                      valBool: null
                      valFloat: 0.3
                      valInt: null
                      valStr: null
                  tags:
                    - name: "tag3"
                    - name: "tag2"
              totalResults: 2
        "400":
          description: "Invalid parameter."
          schema:
            $ref: "#/definitions/ErrorResponse"
        "500":
          description: "Internal server error."
          schema:
            $ref: "#/definitions/ErrorResponse"

  "/experiments":
    post:
      tags:
        - "experiments"
      summary: "Create an experiment."
      description: ""
      operationId: "createExperiments"
      consumes:
        - "application/json"
      produces:
        - "application/json"
      parameters:
        - in: "body"
          name: "experiment"
          description: "Experiment to create."
          required: true
          schema:
            $ref: "#/definitions/Experiment"
      responses:
        "201":
          description: "Successfuly created experiment."
          schema:
            $ref: "#/definitions/Experiment"
        "400":
          description: "Invalid experiment specification."
          schema:
            $ref: "#/definitions/ErrorResponse"
        "500":
          description: "Internal server error."
          schema:
            $ref: "#/definitions/ErrorResponse"

  "/experiments/{id}":
    get:
      tags:
        - "experiments"
      summary: "Get an experiment."
      description: "Returns an experiment given its ID"
      operationId: "getExperimentsById"
      produces:
        - "application/json"
      parameters:
        - name: "id"
          in: "path"
          required: true
          type: "string"
      responses:
        "200":
          description: "Successful operation."
          schema:
            $ref: "#/definitions/Experiment"
          examples:
            application/json:
              command: "command"
              docker_image_digest: "sha256:49414f826ff99061c6526cfc5c435c3f26f6263dd1fbe64f4bd35599a480fb6a"
              docker_image_tag: "driving:9001"
              description: "description ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
              completionTime: 1507074465000
              environment: "ZOOX_WORKSPACE=whydoesthisvariableexist"
              gitSha: "999ed2cba5c2f7bbfede687eeb8fd2452827799"
              gitDirty: true
              id: "zxyj-efgh-ijkl"
              name: "Experiment from an ID"
              owner: "mickey"
              project:
                name: "project1"
                description: "project1 description"
              repository: "driving"
              creationTime: 1507073465000
              state: "Running"
              links:
                - url: "http://www.zoox.com"
                  description: "Yay"
              params:
                - parameterType:
                    name: "Learning Rate"
                    type: "float"
                  valFloat: 0.2
                  valInt: null
                  valStr: null
                  valBool: null
              tags:
                - name: "tag1"
                - name: "tag2"
        "404":
          description: "Invalid experiment ID."
          schema:
            $ref: "#/definitions/ErrorResponse"
        "500":
          description: "Internal server error."
          schema:
            $ref: "#/definitions/ErrorResponse"

    put:
      tags:
        - "experiments"
      summary: "Update an experiment. Replaces each field in the database with all fields defined in the request"
      description: ""
      operationId: "updateExperimentsById"
      consumes:
        - "application/json"
      produces:
        - "application/json"
      parameters:
        - in: "path"
          name: "id"
          description: "ID of experiment to update."
          required: true
          type: "string"
        - in: "body"
          name: "experiment"
          description: "Experiment attributes to replace."
          required: true
          schema:
            $ref: "#/definitions/ExperimentPatch"
      responses:
        "200":
          description: "Successful operation."
          schema:
            $ref: "#/definitions/Experiment"
        "400":
          description: "Invalid experiment update specification."
          schema:
            $ref: "#/definitions/ErrorResponse"
        "500":
          description: "Internal server error."
          schema:
            $ref: "#/definitions/ErrorResponse"

  "/experiments/{experimentId}/comparison-plugin-metadatas/{comparisonPluginId}":
    put:
      tags:
        - "comparison_plugins"
      summary: "Add or update the metadata for a particular comparison plugin for this experiment."
      description: ""
      operationId: "comparisonPluginMetadataPut"
      consumes:
        - "application/json"
      produces:
        - "application/json"
      parameters:
        - in: "path"
          name: "experimentId"
          description: "Experiment ID."
          type: "string"
          required: true
        - in: "path"
          name: "comparisonPluginId"
          description: "ID of the comparison plugin whose metadata should be added/updated."
          type: "string"
          required: true
        - in: "body"
          name: "comparisonPluginMetadata"
          description: "Metada object to write."
          required: true
          schema:
            $ref: "#/definitions/ComparisonPluginMetadataPayload"
      responses:
        "200":
          description: "Successful operation."
          schema:
            $ref: "#/definitions/ComparisonPluginMetadata"
        "400":
          description: "Bad request."
          schema:
            $ref: "#/definitions/ErrorResponse"
        "404":
          description: "Not found."
          schema:
            $ref: "#/definitions/ErrorResponse"
        "500":
          description: "Internal server error."
          schema:
            $ref: "#/definitions/ErrorResponse"

  "/experiments/{experimentId}/links":
    post:
      tags:
        - "links"
      summary: "Append a link to an experiment."
      description: ""
      operationId: "linksCreateByExperimentId"
      consumes:
        - "application/json"
      produces:
        - "application/json"
      parameters:
        - in: "path"
          name: "experimentId"
          description: "Experiment ID."
          type: "string"
          required: true
        - in: "body"
          name: "link"
          description: "Link to create."
          required: true
          schema:
            $ref: "#/definitions/Link"
      responses:
        "201":
          description: "Successful operation."
          schema:
            $ref: "#/definitions/Link"
        "400":
          description: "Invalid Link specification."
          schema:
            $ref: "#/definitions/ErrorResponse"
        "409":
          description: "Duplicate Link."
          schema:
            $ref: "#/definitions/ErrorResponse"
        "500":
          description: "Internal server error."
          schema:
            $ref: "#/definitions/ErrorResponse"

  "/latest-metrics":
    get:
      tags:
        - "latest_metrics"
      summary: "Bulk get the latest metrics."
      operationId: "latestMetricsGet"
      consumes:
        - "application/json"
      parameters:
        - in: "body"
          name: "experimentIds"
          description: "Experiment IDs for which to retrieve latest metrics."
          required: true
          schema:
            type: "array"
            items:
              type: "string"
      responses:
        "200":
          description: "Successful operation."
          schema:
            $ref: "#/definitions/PaginatedMetricsList"
        "400":
          description: "Client error."
          schema:
            $ref: "#/definitions/ErrorResponse"
        "500":
          description: "Internal server error."
          schema:
            $ref: "#/definitions/ErrorResponse"

    post:
      tags:
        - "latest_metrics"
      summary: "Update the latest metrics for an experiment."
      operationId: "latestMetricsPost"
      consumes:
        - "application/json"
      parameters:
        - in: "body"
          name: "latestMetrics"
          description: "Metrics to update with."
          required: true
          schema:
            type: "array"
            items:
              $ref: "#/definitions/Metric"
      responses:
        "204":
          description: "Successful operation."
        "400":
          description: "Client error."
          schema:
            $ref: "#/definitions/ErrorResponse"
        "500":
          description: "Internal server error."
          schema:
            $ref: "#/definitions/ErrorResponse"

  "/metric-types":
    get:
      tags:
        - "metric_types"
      summary: "Bulk get MetricType objects by name or id."
      operationId: "metricTypesGet"
      consumes:
        - "application/json"
      parameters:
        - in: "body"
          name: "selector"
          description: "Which MetricType ids or names to retrieve. Either ids or names should be provide, not both."
          schema:
            type: "object"
            properties:
              ids:
                type: "array"
                items:
                  type: "string"
              names:
                type: "array"
                items:
                  type: "string"
      responses:
        "200":
          description: "Successful operation."
          schema:
            type: "array"
            items:
              $ref: "#/definitions/MetricType"
        "400":
          description: "Client error."
          schema:
            $ref: "#/definitions/ErrorResponse"
        "500":
          description: "Internal server error."
          schema:
            $ref: "#/definitions/ErrorResponse"

    put:
      tags:
        - "metric_types"
      summary: "Bulk insert a MetricType. If a MetricType already exists will not overwrite."
      operationId: "metricTypesPut"
      consumes:
        - "application/json"
      parameters:
        - in: "body"
          name: "metricTypes"
          description: "MetricTypes to insert."
          required: true
          schema:
            type: "array"
            items:
              $ref: "#/definitions/MetricType"
      responses:
        "200":
          description: "Successful operation."
          schema:
            type: "array"
            items:
              $ref: "#/definitions/MetricType"
        "400":
          description: "Client error."
          schema:
            $ref: "#/definitions/ErrorResponse"
        "500":
          description: "Internal server error."
          schema:
            $ref: "#/definitions/ErrorResponse"

  "/projects":
    get:
      tags:
        - "projects"
      summary: "List all projects."
      description: ""
      operationId: "getProjects"
      produces:
        - "application/json"
      responses:
        "200":
          description: "Successful operation."
          schema:
            $ref: "#/definitions/PaginatedProjectsList"
          examples:
            application/json:
              data:
                - name: "project1"
                  description: "My first project."
                - name: "project2"
                  description: "Another project."
              totalResults: 2
        "400":
          description: "Invalid parameter."
          schema:
            $ref: "#/definitions/ErrorResponse"
        "500":
          description: "Internal server error."
          schema:
            $ref: "#/definitions/ErrorResponse"

  "/tags":
    get:
      tags:
        - "tags"
      summary: "List all tags."
      description: ""
      operationId: "getTags"
      produces:
        - "application/json"
      responses:
        "200":
          description: "Successful operation."
          schema:
            $ref: "#/definitions/PaginatedTagsList"
          examples:
            application/json:
              data:
                - name: "tag1"
                - name: "tag2"
                - name: "tag3"
                - name: "yet another tag"
              totalResults: 4
        "400":
          description: "Invalid parameter."
          schema:
            $ref: "#/definitions/ErrorResponse"
        "500":
          description: "Internal server error."
          schema:
            $ref: "#/definitions/ErrorResponse"

definitions:
  ComparisonPlugin:
    type: "object"
    properties:
      color:
        description: "UI hint for what color to associate with this plugin. A hex color value."
        type: "string"
      id:
        description: "The unique id of this plugin."
        type: "string"
      name:
        description: "The human readable name of this plugin."
        type: "string"
      nMaxComparable:
        description: "The maximum number of metadatas this plugin can compare."
        type: "integer"
      nMinComparable:
        description: "The minimum number of metadatas this plugin can compare."
        type: "integer"
    required:
      - "color"
      - "name"
      - "nMaxComparable"
      - "nMinComparable"

  ComparisonPluginList:
    type: "object"
    properties:
      data:
        description: "The actual list of ComparisonPlugins."
        type: "array"
        items:
          $ref: "#/definitions/ComparisonPlugin"
    required:
      - "data"

  ComparisonPluginMetadata:
    type: "object"
    properties:
      experimentId:
        description: "The experiment to which this belongs."
        type: "string"
      comparisonPluginId:
        description: "The id of the comparison plugin that this metadata corresponds to."
        type: "string"
      metadata:
        description: "JSON blob of metadata. Must satisfy the schema of the associated comparison plugin."
        $ref: "#/definitions/ComparisonPluginMetadataPayload"
    required:
      - "experimentId"
      - "comparisonPluginId"
      - "metadata"

  ComparisonPluginMetadataPayload:
    type: "object"
    additionalProperties:
      type: "string"

  ErrorResponse:
    type: "object"
    properties:
      message:
        description: "A message describing the error"
        type: "string"

  ExperimentSchema: &EXPERIMENT_SCHEMA
    type: "object"
    properties:
      id:
        description: "The identifier for this experiment, set by the server"
        type: "string"
        readOnly: True
      projectId:
        description: "The identifier for this experiment's project"
        type: "string"
        readOnly: True
      project:
        $ref: "#/definitions/Project"
      name:
        description: "Name of this experiment."
        type: "string"
      description:
        description: "Experiment description."
        type: "string"
      creationTime:
        description: "Epoch job creation time."
        format: "int64"
        type: "integer"
      comparisonPluginMetadatas:
        description: "Metadata objects for any comparison tools that this experiment can be compared with."
        type: "array"
        items:
          $ref: "#/definitions/ComparisonPluginMetadata"
      completionTime:
        description: "Epoch job completion time."
        format: "int64"
        type: "integer"
      owner:
        description: "The AD user to whom this experiment belongs."
        type: "string"
      state:
        $ref: "#/definitions/ExperimentState"
      command:
        description: "The command used to run this experiment."
        type: "string"
      environment:
        description: "The environment used to run this experiment."
        type: "string"
      docker_image_digest:
        description: "The digest of the docker image used to run this experiment."
        type: "string"
      docker_image_tag:
        description: "The tag of the docker image used to run this experiment."
        type: "string"
      repository:
        description: "The repository used to run this experiment."
        type: "string"
      gitSha:
        description: "The git SHA at which the experiment was run."
        type: "string"
      gitDirty:
        description: "Whether or not there were uncommitted changes when the experiment was run."
        type: "boolean"
      links:
        description: "The links associated with this Experiment."
        type: "array"
        items:
          $ref: "#/definitions/Link"
      params:
        description: "The parameters associated with this Experiment."
        type: "array"
        items:
          $ref: "#/definitions/Parameter"
      tags:
        description: "The tags associated with this Experiment."
        type: "array"
        items:
          $ref: "#/definitions/Tag"

  Experiment:
    <<: *EXPERIMENT_SCHEMA
    required:
      - "project"
      - "name"
      - "owner"
      - "state"
      - "command"
      - "creationTime"

  ExperimentPatch:
    <<: *EXPERIMENT_SCHEMA

  ExperimentState:
    description: "The current state of this experiment"
    type: "string"
    enum:
      - "Queued"
      - "Running"
      - "Succeeded"
      - "Failed"
      - "Cancelled"

  ExperimentsGetRequestBody:
    description: "Request body for getExperiments API call."
    type: "object"
    properties:
      owner:
        description: "The owner of returned experiments."
        type: "string"
      project:
        description: "The name of the project by which to filter results."
        type: "string"
      state:
        $ref: "#/definitions/ExperimentState"
      tags:
        description: "Comma-separated list of tags, one of which must apply to returned experiments."
        type: "string"

      offset:
        description: "The offset at which to return the results"
        type: "integer"
      limit:
        description: "The max number of results to return"
        type: "integer"

      orderBy:
        description: "What to order by."
        type: "object"
        properties:
          what:
            description: "What to order by."
            type: "string"
            enum:
              - "metric"
              - "parameter"
              - "creation_time"
          order:
            description: "Which order to use."
            type: "string"
            enum:
              - "asc"
              - "desc"
          name:
            description: "The name of the parameter or metric to order by."
            type: "string"
        required:
          - "what"

  Link:
    type: "object"
    properties:
      url:
        description: "The URL for this link"
        type: "string"
      description:
        description: "The human-readable description of this link"
        type: "string"

  # NOTE: This should be synchronized with `//omlet/api/metrics/omlet_metrics_api/v2.yml`.
  MetricType:
    type: "object"
    properties:
      id:
        type: "string"
        description: "The ID of this metric type."
      name:
        type: "string"
        description: "The metric's name."
      type:
        type: "string"
        enum:
          - "integer"
          - "bool"
          - "float"
          - "object"

  # NOTE: This should be synchronized with `//omlet/api/metrics/omlet_metrics_api/v2.yml`.
  MetricSchema: &METRIC_SCHEMA
    type: "object"
    properties:
      id:
        description: "Metric's unique identifier."
        type: "string"
      metricType:
        $ref: "#/definitions/MetricType"
      valFloat:
        description: "The metric's float value."
        type: "number"
        format: "float"
      valBool:
        description: "The metric's boolean value."
        type: "boolean"
      valInt:
        description: "The metric's boolean value."
        type: "integer"
        format: "int64"
      iteration:
        description: "The iteration after which this metric was reported. Set client side."
        type: "integer"
        format: "int64"
      timestamp:
        description: "Epoch metric timestamp in milliseconds."
        type: "integer"
        format: "int64"
      experimentId:
        description: "The experiment to which this metric belongs."
        type: "string"

  # NOTE: This should be synchronized with `//omlet/api/metrics/omlet_metrics_api/v2.yml`.
  Metric:
    <<: *METRIC_SCHEMA
    required:
      - "experimentId"
      - "iteration"
      - "metricType"
      - "timestamp"

  PaginatedExperimentsList:
    type: "object"
    properties:
      data:
        description: "The list of experiments."
        type: "array"
        items:
          $ref: "#/definitions/Experiment"
      totalResults:
        description: "The total number of results this query will return"
        type: "integer"

  PaginatedMetricsList:
    type: "object"
    properties:
      data:
        description: "The list of metrics."
        type: "array"
        items:
          $ref: "#/definitions/Metric"
      totalResults:
        description: "The total number of results this query will return"
        type: "integer"

  PaginatedProjectsList:
    type: "object"
    properties:
      data:
        description: "A list of projects."
        type: "array"
        items:
          $ref: "#/definitions/Project"
      totalResults:
        description: "The total number of results this query will return"
        type: "integer"

  PaginatedTagsList:
    type: "object"
    properties:
      data:
        description: "A list of tags."
        type: "array"
        items:
          $ref: "#/definitions/Tag"
      totalResults:
        description: "The total number of results this query will return"
        type: "integer"

  Parameter:
    type: "object"
    properties:
      id:
        description: "The identifier for this parameter, set by the server"
        type: "string"
        readOnly: True
      typeId:
        description: "The identifier for this parameter's type, set by the server"
        type: "string"
        readOnly: True
      experimentId:
        description: "The identifier for this parameter's experiment, set by the server"
        type: "string"
        readOnly: True
      parameterType:
        $ref: "#/definitions/ParameterType"
      valInt:
        description: "The integer value for this parameter."
        type: "integer"
        format: "int64"
      valStr:
        description: "The string value for this parameter."
        type: "string"
      valFloat:
        description: "The float value for this parameter."
        type: "number"
        format: "float"
      valBool:
        description: "The boolean value for this parameter."
        type: "boolean"

  ParameterType:
    type: "object"
    properties:
      name:
        description: "Human readable identifier for a parameter"
        type: "string"
      type:
        description: "The parameter data type"
        type: "string"
        enum:
          - "integer"
          - "string"
          - "float"
          - "bool"

  Project:
    type: "object"
    properties:
      name:
        description: "The name of this project."
        type: "string"
      description:
        description: "The human-readable description of this project"
        type: "string"

  Tag:
    type: "object"
    properties:
      name:
        description: "The name of this tag"
        type: "string"
