# Copyright 2020 The Merlin Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. swagger: "2.0" info: title: "Merlin" description: "API Guide for accessing Merlin's model deployment functionalities" version: "0.6.0" host: "localhost:3000" basePath: "/v1" tags: - name: "project" description: "Project Management API. Project is used to namespace model, secret, and user access" - name: "models" description: "Model Management API. API to manage ML model in Merlin." - name: "version" description: "Model Version Management API. Model version represents the iteration of an ML model" - name: "endpoint" description: "Deployment Management API. Endpoint represent a deployment of a specific model version" - name: "model_endpoints" description: "Serving Traffic Management API. API to manage traffic routing to a running endpoint." - name: "secret" description: "Secret Management API. Secret is stored securely inside merlin and can be used to run prediction job" - name: "alert" description: "Alert Management API." - name: "environment" description: "Environment is the infrastructure on which model deployments / batch predictions are running" - name: "prediction_jobs" description: "Batch prediction job API. Run a prediction as a batch job using model in Merlin" - name: "log" description: "Log API for accessing log in the container running a model deployment" schemes: - "http" paths: "/environments": get: tags: ["environment"] summary: "List available environment" description: "Environment can be filtered by optional `name` parameter" parameters: - in: "query" name: "name" required: false type: "string" responses: 200: description: "OK" schema: type: "array" items: $ref: "#/definitions/Environment" "/projects": get: tags: ["project"] summary: "List existing projects" description: "Projects can be filtered by optional `name` parameter" parameters: - in: "query" name: "name" required: false type: "string" responses: 200: description: "OK" schema: type: "array" items: $ref: "#/definitions/Project" post: tags: ["project"] summary: "Create new project" parameters: - in: "body" name: "body" description: "Project object that has to be added" required: true schema: $ref: "#/definitions/Project" responses: 201: description: "Created" schema: $ref: "#/definitions/Project" 400: description: "Invalid request format" 409: description: "Project with the same name already exists" "/projects/{project_id}": get: tags: ["project"] summary: "Get project" parameters: - in: "path" name: "project_id" description: "project id of the project to be retrieved" type: "integer" required: true responses: 200: description: "Ok" schema: $ref: "#/definitions/Project" 404: description: "Project Not Found" put: tags: ["project"] summary: "Update project" parameters: - in: "path" name: "project_id" description: "project id of the project to be updated" type: "integer" required: true - in: "body" name: "body" description: "Project object that has to be updated" required: true schema: $ref: "#/definitions/Project" responses: 200: description: "Ok" schema: $ref: "#/definitions/Project" 400: description: "Invalid request format" "/projects/{project_id}/models/{model_id}": get: tags: ["models"] summary: "Get model" parameters: - in: "path" name: "project_id" description: "project id of the project to be retrieved" type: "integer" required: true - in: "path" name: "model_id" description: "model id of the model to be retrieved" type: "integer" required: true responses: 200: description: "OK" schema: type: "array" items: $ref: "#/definitions/Model" 404: description: "Project/Model with given id not found" "/projects/{project_id}/models": get: tags: ["models"] summary: "List existing models" parameters: - in: "path" name: "project_id" description: "Filter list of models by specific `project_id`" type: "integer" required: true - in: "query" name: "name" description: "Filter list of models by specific models `name`" type: "string" required: false responses: 200: description: "OK" schema: type: "array" items: $ref: "#/definitions/Model" 404: description: "Project with given `project_id` not found" post: tags: ["models"] summary: "Register a new models" parameters: - in: "path" name: "project_id" description: "Create new model in a specific `project_id`" type: "integer" required: true - in: "body" name: "body" schema: $ref: "#/definitions/Model" responses: 201: description: "Created" schema: $ref: "#/definitions/Model" 400: description: "Invalid request format" 404: description: "Project with given `project_id` not found" "/projects/{project_id}/jobs": get: tags: ["prediction_jobs"] summary: "List all prediction jobs created using the model" parameters: - in: "path" name: "project_id" type: "integer" required: true - in: "query" name: "id" type: "integer" - in: "query" name: "name" type: "string" - in: "query" name: "model_id" type: "integer" - in: "query" name: "version_id" type: "integer" - in: "query" name: "status" type: "string" - in: "query" name: "error" type: "string" responses: 200: description: "OK" schema: type: "array" items: $ref: "#/definitions/PredictionJob" 404: description: "Project with given `project_id` not found" "/models/{model_id}/versions": get: tags: ["version"] summary: "List versions of the models" parameters: - in: "path" name: "model_id" type: "integer" required: true responses: 200: description: "OK" schema: type: "array" items: $ref: "#/definitions/Version" 404: description: "Model with given `model_id` not found" post: tags: ["version"] summary: "Log a new version of the models" parameters: - in: "path" name: "model_id" type: "integer" required: true responses: 200: description: "Created" schema: $ref: "#/definitions/Version" "/models/{model_id}/versions/{version_id}": patch: tags: ["version"] summary: "Patch the version " parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "path" name: "version_id" type: "integer" required: true - in: "body" name: "body" schema: $ref: "#/definitions/Version" responses: 200: description: "OK" 400: description: "Invalid request format" 404: description: "Version with given `version_id` not found" "/models/{model_id}/versions/{version_id}/endpoint": get: tags: ["endpoint"] summary: "List all endpoint of a model version" parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "path" name: "version_id" type: "integer" required: true responses: 200: description: "OK" schema: type: "array" items: $ref: "#/definitions/VersionEndpoint" 404: description: "Version with given `version_id` not found" post: tags: ["endpoint"] summary: "Deploy specific version of the models" parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "path" name: "version_id" type: "integer" required: true - in: "body" name: "body" schema: $ref: "#/definitions/VersionEndpoint" responses: 201: description: "Created" schema: $ref: "#/definitions/VersionEndpoint" 404: description: "Version with given `version_id` not found" "/models/{model_id}/versions/{version_id}/endpoint/{endpoint_id}": get: tags: ["endpoint"] summary: "Get version endpoint resource" parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "path" name: "version_id" type: "integer" required: true - in: "path" name: "endpoint_id" type: "string" required: true responses: 200: description: "OK" schema: $ref: "#/definitions/VersionEndpoint" 404: description: "Version endpoint with given `endpoint_id` not found" put: tags: ["endpoint"] summary: "Modify version endpoint, this API will redeploy the associated deployment" parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "path" name: "version_id" type: "integer" required: true - in: "path" name: "endpoint_id" type: "string" required: true - in: "body" name: "body" schema: $ref: "#/definitions/VersionEndpoint" responses: 200: description: "OK" schema: $ref: "#/definitions/VersionEndpoint" 404: description: "Version endpoint with given `endpoint_id` not found" delete: tags: ["endpoint"] summary: "Undeploy the specified model version deployment" parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "path" name: "version_id" type: "integer" required: true - in: "path" name: "endpoint_id" type: "string" required: true responses: 200: description: "OK" 404: description: "Version endpoint with given `endpoint_id` not found" "/models/{model_id}/versions/{version_id}/endpoint/{endpoint_id}/containers": get: tags: ["endpoint"] summary: "Get all container belong to a version endpoint" parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "path" name: "version_id" type: "integer" required: true - in: "path" name: "endpoint_id" type: "string" required: true responses: 200: description: "OK" schema: $ref: "#/definitions/Container" 404: description: "Version endpoint with given `endpoint_id` not found" "/projects/{project_id}/model_endpoints": get: tags: ["model_endpoints"] summary: "List existing model endpoints for all models in particular project" parameters: - in: "path" name: "project_id" description: "Filter list of model endpoints by specific `project_id`" type: "integer" required: true - in: "query" name: "region" description: "Filter list of model endpoints by specific environment's `region`" type: "string" required: false responses: 200: description: "OK" schema: type: "array" items: $ref: "#/definitions/ModelEndpoint" "/models/{model_id}/endpoints": get: tags: ["model_endpoints"] summary: "List model endpoint" parameters: - in: "path" name: "model_id" type: "integer" required: true responses: 200: description: "OK" schema: type: "array" items: $ref: "#/definitions/ModelEndpoint" post: tags: ["model_endpoints"] summary: "Create a model endpoint" parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "body" name: "body" description: "Model endpoint object that has to be added" required: true schema: $ref: "#/definitions/ModelEndpoint" responses: 200: description: "OK" schema: $ref: "#/definitions/ModelEndpoint" "/models/{model_id}/endpoints/{model_endpoint_id}": get: tags: ["model_endpoints"] summary: "Get a model endpoint" parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "path" name: "model_endpoint_id" type: "string" required: true responses: 200: description: "OK" schema: $ref: "#/definitions/ModelEndpoint" put: tags: ["model_endpoints"] summary: "Update model endpoint data. Mainly used to update its rule." parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "path" name: "model_endpoint_id" type: "string" required: true - in: "body" name: "body" schema: $ref: "#/definitions/ModelEndpoint" responses: 200: description: "OK" schema: $ref: "#/definitions/ModelEndpoint" delete: tags: ["model_endpoints"] summary: "Stop serving traffic to the model endpoint, then delete it." parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "path" name: "model_endpoint_id" type: "string" required: true responses: 200: description: "OK" "/alerts/teams": get: tags: ["models", "alert"] summary: "Lists teams for alert notification channel." responses: 200: description: "OK" schema: type: "array" items: type: "string" "/models/{model_id}/alerts": get: tags: ["models", "alert"] summary: "Lists alerts for given model." parameters: - in: "path" name: "model_id" type: "integer" required: true responses: 200: description: "OK" schema: type: "array" items: $ref: "#/definitions/ModelEndpointAlert" "/models/{model_id}/endpoints/{model_endpoint_id}/alert": get: tags: ["models", "alert"] summary: "Gets alert for given model endpoint." parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "path" name: "model_endpoint_id" type: "string" required: true responses: 200: description: "OK" schema: $ref: "#/definitions/ModelEndpointAlert" post: tags: ["models", "alert"] summary: "Creates alert for given model endpoint." parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "path" name: "model_endpoint_id" type: "string" required: true - in: "body" name: "body" schema: $ref: "#/definitions/ModelEndpointAlert" responses: 201: description: "Created" put: tags: ["models", "alert"] summary: "Creates alert for given model endpoint." parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "path" name: "model_endpoint_id" type: "string" required: true - in: "body" name: "body" schema: $ref: "#/definitions/ModelEndpointAlert" responses: 200: description: "Ok" "/logs": get: tags: ["log"] summary: "Retrieve log from a container" parameters: - in: "query" name: "name" type: "string" required: true - in: "query" name: "pod_name" type: "string" required: true - in: "query" name: "namespace" type: "string" required: true - in: "query" name: "cluster" type: "string" required: true - in: "query" name: "follow" type: "string" required: false - in: "query" name: "limit_bytes" type: "string" required: false - in: "query" name: "pretty" type: "string" required: false - in: "query" name: "previous" type: "string" required: false - in: "query" name: "since_seconds" type: "string" required: false - in: "query" name: "since_time" type: "string" required: false - in: "query" name: "tail_lines" type: "string" required: false - in: "query" name: "timestamps" type: "string" required: false responses: 200: description: "OK" content: text/plain: schema: type: "string" "/projects/{project_id}/secrets": post: tags: ["secret"] summary: "Create secret" parameters: - in: "path" name: "project_id" type: "integer" required: true - in: "body" name: "body" schema: $ref: "#/definitions/Secret" responses: 201: description: "Created" schema: $ref: "#/definitions/Secret" get: tags: ["secret"] summary: "List secret" parameters: - in: "path" name: "project_id" type: "integer" required: true responses: 201: description: "Ok" schema: type: "array" items: $ref: "#/definitions/Secret" "/projects/{project_id}/secrets/{secret_id}": patch: tags: ["secret"] summary: "Update secret" parameters: - in: "path" name: "project_id" type: "integer" required: true - in: "path" name: "secret_id" type: "integer" required: true - in: "body" name: "body" schema: $ref: "#/definitions/Secret" responses: 200: description: "Updated" schema: $ref: "#/definitions/Secret" delete: tags: ["secret"] summary: "Delete secret" parameters: - in: "path" name: "project_id" type: "integer" required: true - in: "path" name: "secret_id" type: "integer" required: true responses: 204: description: "No content" "/models/{model_id}/versions/{version_id}/jobs": get: tags: ["prediction_jobs"] summary: "List all prediction jobs of a model version" parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "path" name: "version_id" type: "integer" required: true responses: 200: description: "OK" schema: type: "array" items: $ref: "#/definitions/PredictionJob" 404: description: "Version with given `version_id` not found" post: tags: ["prediction_jobs"] summary: "Create a prediction job from the given model version" parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "path" name: "version_id" type: "integer" required: true - in: "body" name: "body" schema: $ref: "#/definitions/PredictionJob" responses: 201: description: "Created" schema: $ref: "#/definitions/PredictionJob" 404: description: "Version with given `version_id` not found" "/models/{model_id}/versions/{version_id}/jobs/{job_id}": get: tags: ["prediction_jobs"] summary: "Get prediction jobs with given id" parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "path" name: "version_id" type: "integer" required: true - in: "path" name: "job_id" type: "integer" required: true responses: 200: description: "OK" schema: $ref: "#/definitions/PredictionJob" 404: description: "Prediction job with given ID is not found" "/models/{model_id}/versions/{version_id}/jobs/{job_id}/stop": put: tags: ["prediction_jobs"] summary: "Stop prediction jobs with given id" parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "path" name: "version_id" type: "integer" required: true - in: "path" name: "job_id" type: "integer" required: true responses: 204: description: "No content" 404: description: "Prediction job with given ID is not found" "/models/{model_id}/versions/{version_id}/jobs/{job_id}/containers": get: tags: ["prediction_jobs"] summary: "Get all container belong to a prediction job" parameters: - in: "path" name: "model_id" type: "integer" required: true - in: "path" name: "version_id" type: "integer" required: true - in: "path" name: "job_id" type: "string" required: true responses: 200: description: "OK" schema: $ref: "#/definitions/Container" 404: description: "Version endpoint with given `endpoint_id` not found" definitions: EndpointStatus: type: "string" enum: - "pending" - "running" - "serving" - "failed" - "terminated" Environment: type: "object" required: - name properties: id: type: "integer" format: "int32" name: type: "string" cluster: type: "string" is_default: type: "boolean" region: type: "string" gcp_project: type: "string" default_resource_request: $ref: "#/definitions/ResourceRequest" created_at: type: "string" format: "date-time" updated_at: type: "string" format: "date-time" Project: type: "object" required: - name properties: id: type: "integer" format: "int32" name: type: "string" mlflow_tracking_url: type: "string" administrators: type: "array" items: type: "string" readers: type: "array" items: type: "string" team: type: "string" stream: type: "string" labels: type: "array" items: $ref: "#/definitions/Label" created_at: type: "string" format: "date-time" updated_at: type: "string" format: "date-time" Model: type: "object" properties: id: type: "integer" format: "int32" project_id: type: "integer" format: "int32" mlflow_experiment_id: type: "integer" format: "int32" name: type: "string" type: type: "string" description: "Model type" enum: - "xgboost" - "tensorflow" - "sklearn" - "h2o" - "pytorch" - "pyfunc" - "onnx" - "pyfunc_v2" - "other" mlflow_url: type: "string" endpoints: type: "array" items: $ref: "#/definitions/ModelEndpoint" created_at: type: "string" format: "date-time" updated_at: type: "string" format: "date-time" ModelEndpoint: type: "object" properties: id: type: "integer" format: "int32" model_id: type: "integer" format: "int32" model: $ref: "#/definitions/Model" status: $ref: "#/definitions/EndpointStatus" url: type: "string" format: "hostname" rule: $ref: "#/definitions/ModelEndpointRule" environment_name: type: "string" environment: $ref: "#/definitions/Environment" created_at: type: "string" format: "date-time" updated_at: type: "string" format: "date-time" ModelEndpointRule: type: "object" properties: destinations: type: "array" items: $ref: "#/definitions/ModelEndpointRuleDestination" mirror: $ref: "#/definitions/VersionEndpoint" ModelEndpointRuleDestination: type: "object" properties: version_endpoint_id: type: "string" format: "uuid" version_endpoint: $ref: "#/definitions/VersionEndpoint" weight: type: "integer" ModelEndpointAlert: type: "object" properties: model_id: type: "integer" model_endpoint_id: type: "integer" environment_name: type: "string" team_name: type: "string" alert_conditions: type: "array" items: $ref: "#/definitions/ModelEndpointAlertCondition" ModelEndpointAlertCondition: type: "object" properties: enabled: type: "boolean" metric_type: $ref: "#/definitions/AlertConditionMetricType" severity: $ref: "#/definitions/AlertConditionSeverity" target: type: "number" percentile: type: "number" unit: type: "string" AlertConditionMetricType: type: "string" enum: - "throughput" - "latency" - "error_rate" - "cpu" - "memory" AlertConditionSeverity: type: "string" enum: - "WARNING" - "CRITICAL" Version: type: "object" properties: id: type: "integer" format: "int32" model_id: type: "integer" format: "int32" mlflow_run_id: type: "string" mlflow_url: type: "string" artifact_uri: type: "string" format: "hostname" endpoints: type: "array" items: $ref: "#/definitions/VersionEndpoint" properties: type: "object" created_at: type: "string" format: "date-time" updated_at: type: "string" format: "date-time" VersionEndpoint: type: "object" properties: id: type: "string" format: "uuid" version_id: type: "integer" format: "int32" status: $ref: "#/definitions/EndpointStatus" url: type: "string" format: "hostname" service_name: type: "string" format: "hostname" environment_name: type: "string" environment: $ref: "#/definitions/Environment" monitoring_url: type: "string" format: "hostname" message: type: "string" resource_request: $ref: "#/definitions/ResourceRequest" env_vars: type: "array" items: $ref: "#/definitions/EnvVar" created_at: type: "string" format: "date-time" updated_at: type: "string" format: "date-time" Container: type: "object" properties: name: type: "string" pod_name: type: "string" namespace: type: "string" cluster: type: "string" gcp_project: type: "string" version_endpoint_id: type: "integer" format: "int32" ResourceRequest: type: "object" properties: min_replica: type: "integer" max_replica: type: "integer" cpu_request: type: "string" memory_request: type: "string" EnvVar: type: "object" properties: name: type: "string" value: type: "string" Label: type: "object" properties: key: type: "string" value: type: "string" Secret: type: "object" properties: id: type: "integer" format: "int32" name: type: "string" data: type: "string" PredictionJob: type: "object" properties: id: type: "integer" format: "int32" name: type: "string" version_id: type: "integer" format: "int32" model_id: type: "integer" format: "int32" project_id: type: "integer" format: "int32" environment_name: type: "string" environment: $ref: "#/definitions/Environment" config: $ref: "#/definitions/Config" status: type: "string" error: type: "string" created_at: type: "string" format: "date-time" updated_at: type: "string" format: "date-time" Config: type: "object" properties: job_config: $ref: "#/definitions/PredictionJobConfig" image_ref: type: "string" service_account_name: type: "string" resource_request: $ref: "#/definitions/PredictionJobResourceRequest" env_vars: type: "array" items: $ref: "#/definitions/EnvVar" PredictionJobResourceRequest: type: "object" properties: driver_cpu_request: type: "string" driver_memory_request: type: "string" executor_cpu_request: type: "string" executor_memory_request: type: "string" executor_replica: type: "integer" format: "int32" PredictionJobConfig: type: object properties: version: type: string kind: type: string name: type: string bigquery_source: type: object properties: table: type: string features: type: array items: type: string options: type: object additionalProperties: type: string gcs_source: type: object properties: format: $ref: "#/definitions/FileFormat" uri: type: string features: type: array items: type: string options: type: object additionalProperties: type: string model: type: object properties: type: type: string enum: - INVALID_MODEL_TYPE - XGBOOST - TENSORFLOW - SKLEARN - PYTORCH - ONNX - PYFUNC - PYFUNC_V2 default: INVALID_MODEL_TYPE uri: type: string result: type: object properties: type: $ref: "#/definitions/ResultType" item_type: $ref: "#/definitions/ResultType" title: only if type is array options: type: object additionalProperties: type: string bigquery_sink: type: object properties: table: type: string staging_bucket: type: string result_column: type: string save_mode: $ref: "#/definitions/SaveMode" options: type: object additionalProperties: type: string gcs_sink: type: object properties: format: $ref: "#/definitions/FileFormat" uri: type: string result_column: type: string save_mode: $ref: "#/definitions/SaveMode" options: type: object additionalProperties: type: string FileFormat: type: string enum: - INVALID_FILE_FORMAT - CSV - PARQUET - AVRO - JSON default: INVALID_FILE_FORMAT ResultType: type: string enum: - DOUBLE - FLOAT - INTEGER - LONG - STRING - ARRAY default: DOUBLE SaveMode: type: string enum: - ERRORIFEXISTS - OVERWRITE - APPEND - IGNORE - ERROR default: ERRORIFEXISTS securityDefinitions: Bearer: type: apiKey name: Authorization in: header security: - Bearer: []