{
  "swagger": "2.0",
  "info": {
    "title": "Ingest automation service",
    "version": "0.1507.0",
    "description": "Send your API key as a bearer token: `Authorization: Bearer <api key>`."
  },
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "securityDefinitions": {
    "ApiKey": {
      "type": "apiKey",
      "in": "header",
      "name": "Authorization",
      "description": "Your API key as a bearer token: `Authorization: Bearer <api key>`."
    }
  },
  "security": [
    {
      "ApiKey": []
    }
  ],
  "paths": {
    "/ingest/v1/ingest-automations": {
      "post": {
        "operationId": "IngestAutomationService_createIngestAutomation",
        "summary": "Create ingest automation",
        "tags": [
          "Ingest Automation Service"
        ],
        "description": "Creates the automation and starts its workflow, returning immediately. Poll getIngestAutomation for progress. Throws WorkspaceNotSandbox outside the sandbox workspace while the feature is gated.",
        "parameters": [
          {
            "name": "request",
            "in": "body",
            "schema": {
              "$ref": "#/definitions/CreateIngestAutomationRequest"
            },
            "required": true,
            "x-example": {
              "workspaceRid": "<workspace rid>",
              "timestampMetadata": {
                "seriesName": "<series name>",
                "timestampType": {
                  "type": "relative",
                  "relative": {
                    "timeUnit": "DAYS"
                  }
                }
              },
              "assetTitle": "<asset title>",
              "datasetTitle": "<dataset title>",
              "runTitle": "<run title>",
              "refName": "<ref name>"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/IngestAutomation"
            },
            "x-example": {
              "rid": "<ingest automation rid>",
              "status": "CREATING_RESOURCES",
              "workspaceRid": "<workspace rid>",
              "createdByRid": "<user rid>",
              "createdAt": "2026-01-01T00:00:00Z",
              "updatedAt": "2026-01-01T00:00:00Z",
              "assetRid": "<asset rid>",
              "datasetRid": "<dataset rid>",
              "runRid": "<run rid>",
              "ingestJobRid": "<ingest job rid>",
              "failedStep": "CREATE_RESOURCES",
              "errorMessage": "<error message>"
            }
          }
        }
      }
    },
    "/ingest/v1/ingest-automations/{rid}": {
      "get": {
        "operationId": "IngestAutomationService_getIngestAutomation",
        "summary": "Get ingest automation",
        "tags": [
          "Ingest Automation Service"
        ],
        "description": "Returns the automation's current status and the RIDs of every resource created so far.",
        "parameters": [
          {
            "name": "rid",
            "in": "path",
            "type": "string",
            "format": "rid",
            "x-alias": "IngestAutomationRid",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/IngestAutomation"
            },
            "x-example": {
              "rid": "<ingest automation rid>",
              "status": "CREATING_RESOURCES",
              "workspaceRid": "<workspace rid>",
              "createdByRid": "<user rid>",
              "createdAt": "2026-01-01T00:00:00Z",
              "updatedAt": "2026-01-01T00:00:00Z",
              "assetRid": "<asset rid>",
              "datasetRid": "<dataset rid>",
              "runRid": "<run rid>",
              "ingestJobRid": "<ingest job rid>",
              "failedStep": "CREATE_RESOURCES",
              "errorMessage": "<error message>"
            }
          }
        }
      }
    }
  },
  "definitions": {
    "TimeUnit": {
      "type": "string",
      "enum": [
        "DAYS",
        "HOURS",
        "MINUTES",
        "SECONDS",
        "MILLISECONDS",
        "MICROSECONDS",
        "NANOSECONDS"
      ]
    },
    "AbsoluteTimestamp": {
      "type": "object",
      "x-union": true,
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "iso8601",
            "epochOfTimeUnit",
            "customFormat"
          ]
        },
        "iso8601": {
          "$ref": "#/definitions/Iso8601Timestamp"
        },
        "epochOfTimeUnit": {
          "$ref": "#/definitions/EpochTimestamp"
        },
        "customFormat": {
          "$ref": "#/definitions/CustomTimestamp"
        }
      },
      "required": [
        "type"
      ],
      "description": "Set `type` to the name of one of the other fields, and set only that field.",
      "example": {
        "type": "iso8601",
        "iso8601": {}
      }
    },
    "CreateIngestAutomationRequest": {
      "description": "Everything the workflow needs to run without the client: the uploaded files' locations and timestamp interpretation, plus the titles for the resources it creates (the client derives them from the uploaded filename before creating the automation).",
      "type": "object",
      "properties": {
        "workspaceRid": {
          "type": "string",
          "format": "rid",
          "x-alias": "WorkspaceRid"
        },
        "sources": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/IngestSource"
          },
          "description": "Locations of the already-uploaded files, all ingested into the same dataset. At least one; at most 20 (enforced by the handler). Only s3 sources are supported today."
        },
        "timestampMetadata": {
          "allOf": [
            {
              "$ref": "#/definitions/TimestampMetadata"
            }
          ],
          "description": "The timestamp column and interpretation the user confirmed in the wizard, applied to every file."
        },
        "fileType": {
          "allOf": [
            {
              "$ref": "#/definitions/IngestAutomationFileType"
            }
          ],
          "description": "The format of every file in sources, ingested as wide-format data. Defaults to CSV when absent."
        },
        "assetTitle": {
          "type": "string",
          "description": "Maximum length 500 characters (enforced by the handler, like the other titles)."
        },
        "datasetTitle": {
          "type": "string",
          "description": "Maximum length 500 characters."
        },
        "runTitle": {
          "type": "string",
          "description": "Maximum length 500 characters."
        },
        "refName": {
          "type": "string",
          "description": "Data scope name linking the created asset and dataset (typically \"default\"). Maximum length 100 characters."
        }
      },
      "required": [
        "workspaceRid",
        "timestampMetadata",
        "assetTitle",
        "datasetTitle",
        "runTitle",
        "refName"
      ],
      "example": {
        "workspaceRid": "<workspace rid>",
        "timestampMetadata": {
          "seriesName": "<series name>",
          "timestampType": {
            "type": "relative",
            "relative": {
              "timeUnit": "DAYS"
            }
          }
        },
        "assetTitle": "<asset title>",
        "datasetTitle": "<dataset title>",
        "runTitle": "<run title>",
        "refName": "<ref name>"
      }
    },
    "CustomTimestamp": {
      "type": "object",
      "properties": {
        "format": {
          "type": "string",
          "description": "The format string should be in the format of the `DateTimeFormatter` class in Java."
        },
        "defaultYear": {
          "type": "integer",
          "format": "int32",
          "description": "Default year is accepted as an optional field for cases like IRIG time format and will be overridden by year in time format."
        },
        "defaultDayOfYear": {
          "type": "integer",
          "format": "int32",
          "description": "Default day of year is accepted as an optional field for cases like IRIG time format and will be overridden by day of year in time format."
        }
      },
      "required": [
        "format"
      ]
    },
    "EpochTimestamp": {
      "type": "object",
      "properties": {
        "timeUnit": {
          "$ref": "#/definitions/TimeUnit"
        }
      },
      "required": [
        "timeUnit"
      ]
    },
    "FileStoreIngestSource": {
      "description": "A resolved File Store revision to ingest, whose bytes are read in place from File Store storage.",
      "type": "object",
      "properties": {
        "fileRevisionRid": {
          "type": "string",
          "format": "rid",
          "x-alias": "DriveFileRevisionRid"
        }
      },
      "required": [
        "fileRevisionRid"
      ]
    },
    "GcsIngestSource": {
      "type": "object",
      "properties": {
        "path": {
          "type": "string"
        }
      },
      "required": [
        "path"
      ]
    },
    "IngestAutomation": {
      "description": "A server-side workflow that carries one upload (one or more CSV or Parquet files) through resource creation, ingest, and channel availability. Started by the upload wizard's \"Quick look\" mode; the client polls getIngestAutomation to drive its progress checklist, and the frontend creates the accompanying workbook itself (workbook semantics live in the frontend server — this service deliberately has no notion of workbooks). The workflow keeps running if the client disconnects — every created resource RID is recorded here so a returning client can pick up where it left off.",
      "type": "object",
      "properties": {
        "rid": {
          "type": "string",
          "format": "rid",
          "x-alias": "IngestAutomationRid"
        },
        "status": {
          "$ref": "#/definitions/IngestAutomationStatus"
        },
        "workspaceRid": {
          "type": "string",
          "format": "rid",
          "x-alias": "WorkspaceRid"
        },
        "createdByRid": {
          "type": "string",
          "format": "rid",
          "x-alias": "UserRid"
        },
        "createdAt": {
          "type": "string",
          "format": "date-time"
        },
        "updatedAt": {
          "type": "string",
          "format": "date-time"
        },
        "assetRid": {
          "type": "string",
          "format": "rid",
          "x-alias": "AssetRid",
          "description": "Present once CREATING_RESOURCES has created the asset."
        },
        "datasetRid": {
          "type": "string",
          "format": "rid",
          "x-alias": "DatasetRid",
          "description": "Present once CREATING_RESOURCES has created the dataset."
        },
        "runRid": {
          "type": "string",
          "format": "rid",
          "x-alias": "RunRid",
          "description": "Present once CREATING_RESOURCES has created the run."
        },
        "ingestJobRid": {
          "type": "string",
          "format": "rid",
          "x-alias": "IngestJobRid",
          "description": "Present once INGESTING has submitted the ingest job."
        },
        "failedStep": {
          "allOf": [
            {
              "$ref": "#/definitions/IngestAutomationStep"
            }
          ],
          "description": "The step that terminated the automation. Present only for FAILED automations."
        },
        "errorMessage": {
          "type": "string",
          "description": "The failure detail recorded when the automation terminated. Present only for FAILED automations. May contain customer-derived content and is therefore not safe to log."
        }
      },
      "required": [
        "rid",
        "status",
        "workspaceRid",
        "createdByRid",
        "createdAt",
        "updatedAt"
      ]
    },
    "IngestAutomationFileType": {
      "description": "The format of the uploaded files. Every file in one automation shares it.",
      "type": "string",
      "enum": [
        "CSV",
        "PARQUET"
      ]
    },
    "IngestAutomationStatus": {
      "description": "Progress of an ingest automation, in execution order. Statuses map one-to-one onto the client's progress checklist. Resources created before a FAILED terminal state persist (the flow is intentionally non-atomic, matching the existing ingest flow).",
      "type": "string",
      "enum": [
        "CREATING_RESOURCES",
        "INGESTING",
        "AWAITING_CHANNELS",
        "COMPLETED",
        "FAILED"
      ]
    },
    "IngestAutomationStep": {
      "description": "The individual workflow steps, used to report where a FAILED automation stopped.",
      "type": "string",
      "enum": [
        "CREATE_RESOURCES",
        "SUBMIT_INGEST",
        "AWAIT_INGEST",
        "AWAIT_CHANNELS"
      ]
    },
    "IngestSource": {
      "type": "object",
      "x-union": true,
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "s3",
            "gcs",
            "presignedFile",
            "fileStore"
          ]
        },
        "s3": {
          "$ref": "#/definitions/S3IngestSource"
        },
        "gcs": {
          "$ref": "#/definitions/GcsIngestSource"
        },
        "presignedFile": {
          "$ref": "#/definitions/PresignedFileIngestSource"
        },
        "fileStore": {
          "$ref": "#/definitions/FileStoreIngestSource"
        }
      },
      "required": [
        "type"
      ],
      "description": "Set `type` to the name of one of the other fields, and set only that field.",
      "example": {
        "type": "s3",
        "s3": {
          "path": "string"
        }
      }
    },
    "Iso8601Timestamp": {
      "type": "object",
      "properties": {}
    },
    "PresignedFileIngestSource": {
      "type": "object",
      "properties": {
        "url": {
          "type": "string"
        }
      },
      "required": [
        "url"
      ]
    },
    "RelativeTimestamp": {
      "type": "object",
      "properties": {
        "timeUnit": {
          "$ref": "#/definitions/TimeUnit"
        },
        "offset": {
          "type": "string",
          "format": "date-time",
          "description": "Starting timestamp to use when indexing the file. This field is required when uploading a new file to an existing dataset."
        }
      },
      "required": [
        "timeUnit"
      ]
    },
    "S3IngestSource": {
      "type": "object",
      "properties": {
        "path": {
          "type": "string"
        }
      },
      "required": [
        "path"
      ]
    },
    "TimestampMetadata": {
      "type": "object",
      "properties": {
        "seriesName": {
          "type": "string"
        },
        "timestampType": {
          "$ref": "#/definitions/TimestampType"
        }
      },
      "required": [
        "seriesName",
        "timestampType"
      ]
    },
    "TimestampType": {
      "type": "object",
      "x-union": true,
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "relative",
            "absolute"
          ]
        },
        "relative": {
          "$ref": "#/definitions/RelativeTimestamp"
        },
        "absolute": {
          "$ref": "#/definitions/AbsoluteTimestamp"
        }
      },
      "required": [
        "type"
      ],
      "description": "Set `type` to the name of one of the other fields, and set only that field.",
      "example": {
        "type": "relative",
        "relative": {
          "timeUnit": "DAYS",
          "offset": "2026-01-01T00:00:00Z"
        }
      }
    }
  },
  "tags": [
    {
      "name": "Ingest Automation Service",
      "x-displayName": "Ingest automation service",
      "description": "Creates and reports on ingest automations: server-side workflows that take an upload (one or more files) through asset/dataset/data-scope/run creation, ingest, and channel availability. Backs the upload wizard's \"Quick look\" mode; the frontend creates the accompanying workbook. All endpoints validate that the target workspace is the sandbox workspace while the feature is gated. Resources are created as the requesting user.",
      "x-errors": [
        {
          "status": 404,
          "errorCode": "NOT_FOUND",
          "errorName": "IngestAutomation:IngestAutomationNotFound"
        },
        {
          "status": 400,
          "errorCode": "INVALID_ARGUMENT",
          "errorName": "IngestAutomation:WorkspaceNotSandbox",
          "description": "Ingest automations are temporarily restricted to the sandbox workspace while the \"Quick look\" upload mode is gated (see the Quick look upon ingest RFC). Lifting the restriction removes this validation."
        }
      ]
    }
  ]
}
