{
  "swagger": "2.0",
  "info": {
    "title": "Nominal channel writer",
    "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": {
    "/storage/writer/v1": {
      "post": {
        "operationId": "NominalChannelWriterService_writeBatches",
        "summary": "Write batches",
        "tags": [
          "Nominal Channel Writer"
        ],
        "description": "Synchronously writes batches of records to a Nominal data source.\n\nIf the request is too large, either due to the number of individual batches (> 10) or the number of points across batches (> 500k), the request may be split up into multiple requests internally when writing to the Nominal data source. Generally, it's advisable to limit the number of points to 50k.",
        "parameters": [
          {
            "name": "request",
            "in": "body",
            "schema": {
              "$ref": "#/definitions/WriteBatchesRequestExternal"
            },
            "required": true,
            "x-example": {
              "dataSourceRid": "<nominal data source or dataset rid>"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No content."
          }
        }
      }
    },
    "/storage/writer/v1/columnar": {
      "post": {
        "operationId": "NominalChannelWriterService_writeColumnBatches",
        "summary": "Write column batches",
        "tags": [
          "Nominal Channel Writer"
        ],
        "description": "Synchronously writes batches of columns of data to a Nominal data source.\n\nThis is a column-major variant of writeBatches (which is row-major) to optimize serialization and compression time for client applications streaming large numbers of points from a single column at a time. This has the tradeoff of slightly larger sizes post-gzipping of requests, so should be used in the particular case where the main bottleneck is in encoding columnar data into the row-based format found in writeBatches.",
        "parameters": [
          {
            "name": "request",
            "in": "body",
            "schema": {
              "$ref": "#/definitions/WriteColumnBatchesRequest"
            },
            "required": true,
            "x-example": {
              "dataSourceRid": "<nominal data source or dataset rid>"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No content."
          }
        }
      }
    },
    "/storage/writer/v1/telegraf/{dataSourceRid}": {
      "post": {
        "operationId": "NominalChannelWriterService_writeTelegrafBatches",
        "summary": "Write Telegraf batches",
        "tags": [
          "Nominal Channel Writer"
        ],
        "description": "Synchronously writes batches of records to a Nominal data source.\n\nHas the same functionality as writeBatches, but is compatible with the Telegraf output format. Assumes that the Telegraf batch format is used. Timestamp is assumed to be in nanoseconds. The URL in the Telegraf output plugin configuration should be the fully qualified URL, including the dataSourceRid query parameter.",
        "parameters": [
          {
            "name": "dataSourceRid",
            "in": "path",
            "type": "string",
            "format": "rid",
            "x-alias": "NominalDataSourceOrDatasetRid",
            "required": true
          },
          {
            "name": "request",
            "in": "body",
            "schema": {
              "$ref": "#/definitions/WriteTelegrafBatchesRequest"
            },
            "required": true,
            "x-example": {
              "metrics": [
                {
                  "name": "<measurement name>",
                  "timestamp": {}
                }
              ]
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No content."
          }
        }
      }
    },
    "/storage/writer/v1/prometheus/{dataSourceRid}": {
      "post": {
        "operationId": "NominalChannelWriterService_writePrometheusBatches",
        "summary": "Write Prometheus batches",
        "tags": [
          "Nominal Channel Writer"
        ],
        "description": "Synchronously writes batches of records to a Nominal data source.\n\nHas the same functionality as writeBatches, but is encoded using the Prometheus remote write format. We follow the specification defined here: https://prometheus.io/docs/specs/remote_write_spec/ There are a few notable caveats:\n  1. Must be content encoded as application/x-protobuf\n  2. Must be compressed using snappy compression",
        "consumes": [
          "application/octet-stream"
        ],
        "parameters": [
          {
            "name": "dataSourceRid",
            "in": "path",
            "type": "string",
            "format": "rid",
            "x-alias": "NominalDataSourceOrDatasetRid",
            "required": true
          },
          {
            "name": "request",
            "in": "body",
            "schema": {
              "type": "string",
              "format": "binary",
              "example": "string"
            },
            "required": true,
            "x-example": "string"
          }
        ],
        "responses": {
          "204": {
            "description": "No content."
          }
        }
      },
      "get": {
        "operationId": "NominalChannelWriterService_prometheusRemoteWriteHealthCheck",
        "summary": "Prometheus remote write health check",
        "tags": [
          "Nominal Channel Writer"
        ],
        "description": "Performs a health check for prometheus remote write Vector sink. All this endpoint does is verify if the caller is authenticated and the server is online. Once Vector allows the Prometheus remote write endpoint to configure the healthcheck url, we can remove this endpoint.\n\nSee: https://github.com/vectordotdev/vector/issues/8279",
        "parameters": [
          {
            "name": "dataSourceRid",
            "in": "path",
            "type": "string",
            "format": "rid",
            "x-alias": "NominalDataSourceOrDatasetRid",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "type": "boolean"
            },
            "x-example": true
          }
        }
      }
    },
    "/storage/writer/v1/nominal/{dataSourceRid}": {
      "post": {
        "operationId": "NominalChannelWriterService_writeNominalBatches",
        "summary": "Write Nominal batches",
        "tags": [
          "Nominal Channel Writer"
        ],
        "description": "Synchronously writes a Nominal Write Request to a Nominal data source using the NominalWrite Protobuf schema. The request must be Protobuf-encoded and accompanied by the appropriate content encoding headers if compressed.\n\nThe request should follow this Protobuf schema: ```proto message WriteRequestNominal { repeated Series series = 1; }\n\nmessage Series { Channel channel = 1; map<string, string> tags = 2;   // Key-value pairs for series tags Points points = 3;              // Contains double, string, integer, array, or struct points }\n\nmessage Channel { string name = 1; } \n\nmessage Points { oneof points_type { DoublePoints double_points = 1; StringPoints string_points = 2; IntegerPoints integer_points = 3; ArrayPoints array_points = 4; StructPoints struct_points = 5; Uint64Points uint64_points = 6; } }\n\nmessage DoublePoints { repeated DoublePoint points = 1; }\n\nmessage StringPoints { repeated StringPoint points = 1; }\n\nmessage IntegerPoints { repeated IntegerPoint points = 1; }\n\nmessage Uint64Points { repeated Uint64Point points = 1; }\n\nmessage ArrayPoints { oneof array_type { DoubleArrayPoints double_array_points = 1; StringArrayPoints string_array_points = 2; } }\n\nmessage DoubleArrayPoints { repeated DoubleArrayPoint points = 1; }\n\nmessage StringArrayPoints { repeated StringArrayPoint points = 1; }\n\nmessage StructPoints { repeated StructPoint points = 1; }\n\nmessage DoublePoint { google.protobuf.Timestamp timestamp = 1; double value = 2; }\n\nmessage StringPoint { google.protobuf.Timestamp timestamp = 1; string value = 2; }\n\nmessage IntegerPoint { google.protobuf.Timestamp timestamp = 1; int64 value = 2; }\n\nmessage Uint64Point { google.protobuf.Timestamp timestamp = 1; uint64 value = 2; }\n\nmessage DoubleArrayPoint { google.protobuf.Timestamp timestamp = 1; repeated double value = 2; }\n\nmessage StringArrayPoint { google.protobuf.Timestamp timestamp = 1; repeated string value = 2; }\n\nmessage StructPoint { google.protobuf.Timestamp timestamp = 1; string jsonString = 2; } ```\n\nEach request can contain multiple series, where each series consists of:\n- A channel name\n- A map of tags (key-value pairs)\n- A collection of points, which can be double, string, integer, array (double/string), or struct (json) values\n- Each point includes a timestamp (using google.protobuf.Timestamp) and its value\n- Array points contain repeated values (array<double> or array<string>)\n- Struct points are represented using strings that contain the JSON formatted blobs, with all keys being strings\n\nThe endpoint requires the Content-Type header to be set to \"application/x-protobuf\". If the payload is compressed, the appropriate Content-Encoding header must be included.",
        "consumes": [
          "application/octet-stream"
        ],
        "parameters": [
          {
            "name": "dataSourceRid",
            "in": "path",
            "type": "string",
            "format": "rid",
            "x-alias": "NominalDataSourceOrDatasetRid",
            "required": true
          },
          {
            "name": "request",
            "in": "body",
            "schema": {
              "type": "string",
              "format": "binary",
              "example": "string"
            },
            "required": true,
            "x-example": "string"
          }
        ],
        "responses": {
          "204": {
            "description": "No content."
          }
        }
      }
    },
    "/storage/writer/v1/nominal-columnar": {
      "post": {
        "operationId": "NominalChannelWriterService_writeNominalColumnarBatches",
        "summary": "Write Nominal columnar batches",
        "tags": [
          "Nominal Channel Writer"
        ],
        "description": "Synchronously writes to a Nominal data source using the columnar WriteBatchesRequest Protobuf schema.\n\nThis is the most efficient write format. Unlike the row-oriented writeNominalBatches endpoint, this schema stores timestamps and values as separate packed arrays per channel, which enables protobuf packed encoding for value arrays and significantly better compression.\n\nThe data_source_rid field in the protobuf body identifies the target data source or dataset. The request must be Protobuf-encoded and accompanied by the appropriate content encoding headers if compressed.\n\nThe request should follow this Protobuf schema: ```proto message WriteBatchesRequest { repeated RecordsBatch batches = 1; string data_source_rid = 2; }\n\nmessage RecordsBatch { string channel = 1; map<string, string> tags = 2; Points points = 3; }\n\nmessage Points { repeated Timestamp timestamps = 1; oneof points { DoublePoints double_points = 2; StringPoints string_points = 3; IntPoints int_points = 5; ArrayPoints array_points = 6; StructPoints struct_points = 7; Uint64Points uint64_points = 8; } }\n\n// Nanosecond precision timestamp. message Timestamp { optional int64 seconds = 1; optional int64 nanos = 2; }\n\nmessage DoublePoints { repeated double points = 1; } message StringPoints { repeated string points = 1; } message IntPoints { repeated int64 points = 1; } message Uint64Points { repeated uint64 points = 1; } message StructPoints { repeated string points = 1; }\n\nmessage ArrayPoints { oneof array_type { DoubleArrayPoints double_array_points = 1; StringArrayPoints string_array_points = 2; } } message DoubleArrayPoints { repeated DoubleArrayPoint points = 1; } message DoubleArrayPoint { repeated double value = 2; } message StringArrayPoints { repeated StringArrayPoint points = 1; } message StringArrayPoint { repeated string value = 2; } ```",
        "consumes": [
          "application/octet-stream"
        ],
        "parameters": [
          {
            "name": "request",
            "in": "body",
            "schema": {
              "type": "string",
              "format": "binary",
              "example": "string"
            },
            "required": true,
            "x-example": "string"
          }
        ],
        "responses": {
          "204": {
            "description": "No content."
          }
        }
      }
    },
    "/storage/writer/v1/logs/{dataSourceRid}": {
      "post": {
        "operationId": "NominalChannelWriterService_writeLogs",
        "summary": "Write logs",
        "tags": [
          "Nominal Channel Writer"
        ],
        "description": "Synchronously writes logs to a Nominal data source.",
        "parameters": [
          {
            "name": "dataSourceRid",
            "in": "path",
            "type": "string",
            "format": "rid",
            "x-alias": "NominalDataSourceOrDatasetRid",
            "required": true
          },
          {
            "name": "request",
            "in": "body",
            "schema": {
              "$ref": "#/definitions/WriteLogsRequest"
            },
            "required": true,
            "x-example": {
              "logs": [
                {
                  "timestamp": {
                    "seconds": 1,
                    "nanos": 1
                  },
                  "value": {
                    "message": "<message>"
                  }
                }
              ],
              "channel": "<channel>"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No content."
          }
        }
      }
    }
  },
  "definitions": {
    "Timestamp": {
      "description": "Deprecated for new APIs. Use google.protobuf.Timestamp for absolute instants in proto APIs.\n\nThis legacy nanosecond precision timestamp type is represented by an epoch time in seconds and a nanosecond offset. The nanosecond offset is from the start of the epoch second, so must be less than 1 billion.",
      "type": "object",
      "properties": {
        "seconds": {
          "type": "integer",
          "format": "int64"
        },
        "nanos": {
          "type": "integer",
          "format": "int64"
        }
      },
      "required": [
        "seconds",
        "nanos"
      ]
    },
    "ArrayPoints": {
      "description": "Array points for the internal API for directly writing points which supports all points types.\n\nSet `type` to the name of one of the other fields, and set only that field.",
      "type": "object",
      "x-union": true,
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "double",
            "string"
          ]
        },
        "double": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/DoubleArrayPoint"
          }
        },
        "string": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/StringArrayPoint"
          }
        }
      },
      "required": [
        "type"
      ],
      "example": {
        "type": "double",
        "double": [
          {
            "timestamp": {
              "seconds": 1,
              "nanos": 1
            },
            "value": [
              1
            ]
          }
        ]
      }
    },
    "ArraysValues": {
      "description": "Each element within the outer list corresponds to an Array point. Subsequent inner lists contain the array values recorded for that point.\n\nSet `type` to the name of one of the other fields, and set only that field.",
      "type": "object",
      "x-union": true,
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "strings1d",
            "doubles1d"
          ]
        },
        "strings1d": {
          "type": "array",
          "items": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "doubles1d": {
          "type": "array",
          "items": {
            "type": "array",
            "items": {
              "type": "number",
              "format": "double"
            }
          }
        }
      },
      "required": [
        "type"
      ],
      "example": {
        "type": "strings1d",
        "strings1d": [
          [
            "string"
          ]
        ]
      }
    },
    "ColumnBatch": {
      "description": "Batch of data to stream for a single channel with their associated timestamps.",
      "type": "object",
      "properties": {
        "channel": {
          "type": "string",
          "x-alias": "Channel",
          "description": "Channel within nominal to stream data to."
        },
        "tags": {
          "type": "object",
          "additionalProperties": {
            "type": "string",
            "x-alias": "TagValue"
          },
          "x-map-key": "TagName",
          "description": "Mapping of key-value pairs to provide as tags to all points within the batch"
        },
        "timestamps": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/Timestamp"
          },
          "description": "List of timestamp values that correspond to the provided list of column values. The number of timestamps provided MUST match the number of columnar values provided, otherwise a 400 error will be returned."
        },
        "values": {
          "allOf": [
            {
              "$ref": "#/definitions/ColumnValues"
            }
          ],
          "description": "List of time series values that should be ingested to a single channel. The number of columnar values provided MUST match the number of timestamps provided, otherwise a 400 error will be returned."
        }
      },
      "required": [
        "channel",
        "values"
      ]
    },
    "ColumnValues": {
      "description": "List of values for a set of points to ingest from a single channel.\n\nSet `type` to the name of one of the other fields, and set only that field.",
      "type": "object",
      "x-union": true,
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "strings",
            "doubles",
            "ints",
            "uint64s",
            "arrays",
            "structs"
          ]
        },
        "strings": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "doubles": {
          "type": "array",
          "items": {
            "type": "number",
            "format": "double"
          }
        },
        "ints": {
          "type": "array",
          "items": {
            "type": "integer",
            "format": "int32"
          }
        },
        "uint64s": {
          "type": "array",
          "items": {
            "type": "integer",
            "format": "int64"
          }
        },
        "arrays": {
          "$ref": "#/definitions/ArraysValues"
        },
        "structs": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "type"
      ],
      "example": {
        "type": "strings",
        "strings": [
          "string"
        ]
      }
    },
    "DoubleArrayPoint": {
      "type": "object",
      "properties": {
        "timestamp": {
          "$ref": "#/definitions/Timestamp"
        },
        "value": {
          "type": "array",
          "items": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "required": [
        "timestamp"
      ]
    },
    "DoublePoint": {
      "type": "object",
      "properties": {
        "timestamp": {
          "$ref": "#/definitions/Timestamp"
        },
        "value": {
          "type": "number",
          "format": "double"
        }
      },
      "required": [
        "timestamp",
        "value"
      ]
    },
    "IntPoint": {
      "type": "object",
      "properties": {
        "timestamp": {
          "$ref": "#/definitions/Timestamp"
        },
        "value": {
          "type": "integer",
          "format": "int32"
        }
      },
      "required": [
        "timestamp",
        "value"
      ]
    },
    "LogPoint": {
      "type": "object",
      "properties": {
        "timestamp": {
          "$ref": "#/definitions/Timestamp"
        },
        "value": {
          "$ref": "#/definitions/LogValue"
        }
      },
      "required": [
        "timestamp",
        "value"
      ]
    },
    "LogValue": {
      "type": "object",
      "properties": {
        "message": {
          "type": "string"
        },
        "args": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        }
      },
      "required": [
        "message"
      ]
    },
    "PointsExternal": {
      "type": "object",
      "x-union": true,
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "string",
            "double",
            "int",
            "uint64",
            "array",
            "struct"
          ]
        },
        "string": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/StringPoint"
          }
        },
        "double": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/DoublePoint"
          }
        },
        "int": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/IntPoint"
          }
        },
        "uint64": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/Uint64Point"
          }
        },
        "array": {
          "$ref": "#/definitions/ArrayPoints"
        },
        "struct": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/StructPoint"
          }
        }
      },
      "required": [
        "type"
      ],
      "description": "Set `type` to the name of one of the other fields, and set only that field.",
      "example": {
        "type": "string",
        "string": [
          {
            "timestamp": {
              "seconds": 1,
              "nanos": 1
            },
            "value": "string"
          }
        ]
      }
    },
    "RecordsBatchExternal": {
      "type": "object",
      "properties": {
        "channel": {
          "type": "string",
          "x-alias": "Channel"
        },
        "tags": {
          "type": "object",
          "additionalProperties": {
            "type": "string",
            "x-alias": "TagValue"
          },
          "x-map-key": "TagName"
        },
        "points": {
          "$ref": "#/definitions/PointsExternal"
        },
        "unit": {
          "type": "string",
          "x-alias": "Unit"
        }
      },
      "required": [
        "channel",
        "points"
      ]
    },
    "StringArrayPoint": {
      "type": "object",
      "properties": {
        "timestamp": {
          "$ref": "#/definitions/Timestamp"
        },
        "value": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "timestamp"
      ]
    },
    "StringPoint": {
      "type": "object",
      "properties": {
        "timestamp": {
          "$ref": "#/definitions/Timestamp"
        },
        "value": {
          "type": "string"
        }
      },
      "required": [
        "timestamp",
        "value"
      ]
    },
    "StructPoint": {
      "type": "object",
      "properties": {
        "timestamp": {
          "$ref": "#/definitions/Timestamp"
        },
        "jsonString": {
          "type": "string"
        }
      },
      "required": [
        "timestamp",
        "jsonString"
      ]
    },
    "TelegrafMetric": {
      "type": "object",
      "properties": {
        "fields": {
          "type": "object",
          "additionalProperties": {},
          "x-map-key": "Field",
          "description": "The values are expected to be either numeric or string values"
        },
        "name": {
          "type": "string",
          "x-alias": "MeasurementName",
          "description": "The measurement name. Measurement name and field are concatenated when creating the Nominal channel name."
        },
        "tags": {
          "type": "object",
          "additionalProperties": {
            "type": "string",
            "x-alias": "TagValue"
          },
          "x-map-key": "TagName"
        },
        "timestamp": {}
      },
      "required": [
        "name",
        "timestamp"
      ]
    },
    "Uint64Point": {
      "type": "object",
      "properties": {
        "timestamp": {
          "$ref": "#/definitions/Timestamp"
        },
        "value": {
          "type": "integer",
          "format": "int64"
        }
      },
      "required": [
        "timestamp",
        "value"
      ]
    },
    "WriteBatchesRequestExternal": {
      "type": "object",
      "properties": {
        "batches": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/RecordsBatchExternal"
          }
        },
        "dataSourceRid": {
          "type": "string",
          "format": "rid",
          "x-alias": "NominalDataSourceOrDatasetRid"
        },
        "asynchronousInsert": {
          "type": "boolean",
          "description": "Is always true - setting this to false will do nothing.",
          "x-deprecated": "Should not be used."
        },
        "sessionName": {
          "type": "string",
          "description": "Optional client-provided session name identifier for tracing the origin of a write request."
        }
      },
      "required": [
        "dataSourceRid"
      ],
      "example": {
        "dataSourceRid": "<nominal data source or dataset rid>"
      }
    },
    "WriteColumnBatchesRequest": {
      "type": "object",
      "properties": {
        "batches": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/ColumnBatch"
          },
          "description": "Batches of columnar data to stream to Nominal. Each channel's data are provided as a column batch."
        },
        "dataSourceRid": {
          "type": "string",
          "format": "rid",
          "x-alias": "NominalDataSourceOrDatasetRid",
          "description": "RID of the datasource (e.g., for a Connection) or dataset to stream data into."
        },
        "sessionName": {
          "type": "string",
          "description": "Optional client-provided session name identifier for tracing the origin of a write request."
        }
      },
      "required": [
        "dataSourceRid"
      ],
      "example": {
        "dataSourceRid": "<nominal data source or dataset rid>"
      }
    },
    "WriteLogsRequest": {
      "type": "object",
      "properties": {
        "logs": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/LogPoint"
          }
        },
        "channel": {
          "type": "string",
          "x-alias": "Channel",
          "description": "If provided, the channel to which to write logs. If not provided, defaults to \"logs\""
        }
      },
      "example": {
        "logs": [
          {
            "timestamp": {
              "seconds": 1,
              "nanos": 1
            },
            "value": {
              "message": "<message>"
            }
          }
        ],
        "channel": "<channel>"
      }
    },
    "WriteTelegrafBatchesRequest": {
      "type": "object",
      "properties": {
        "metrics": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/TelegrafMetric"
          }
        }
      },
      "example": {
        "metrics": [
          {
            "name": "<measurement name>",
            "timestamp": {}
          }
        ]
      }
    }
  },
  "tags": [
    {
      "name": "Nominal Channel Writer",
      "x-displayName": "Nominal channel writer",
      "description": "Write data points to Nominal data sources.",
      "x-errors": [
        {
          "status": 400,
          "errorCode": "INVALID_ARGUMENT",
          "errorName": "NominalChannelWriter:InvalidTimestamp"
        },
        {
          "status": 400,
          "errorCode": "INVALID_ARGUMENT",
          "errorName": "NominalChannelWriter:InvalidTelegrafTimestamp"
        },
        {
          "status": 400,
          "errorCode": "INVALID_ARGUMENT",
          "errorName": "NominalChannelWriter:ConflictingDataTypes",
          "description": "Found two different data types for the same series in the request."
        },
        {
          "status": 400,
          "errorCode": "INVALID_ARGUMENT",
          "errorName": "NominalChannelWriter:ConflictingUnits",
          "description": "Found two different units for the same channel in the request."
        },
        {
          "status": 400,
          "errorCode": "INVALID_ARGUMENT",
          "errorName": "NominalChannelWriter:InvalidDataSource",
          "description": "The nominal data source or dataset provided is invalid."
        },
        {
          "status": 400,
          "errorCode": "INVALID_ARGUMENT",
          "errorName": "NominalChannelWriter:StreamingDisabledOnDataset",
          "description": "Unsupported dataset for streaming."
        },
        {
          "status": 400,
          "errorCode": "INVALID_ARGUMENT",
          "errorName": "NominalChannelWriter:MismatchedTimestampsAndValues",
          "description": "Columnar streaming request contains different numbers of timestamps and values"
        },
        {
          "status": 400,
          "errorCode": "INVALID_ARGUMENT",
          "errorName": "NominalChannelWriter:ArrayTooLarge",
          "description": "Array size exceeds maximum allowed length."
        },
        {
          "status": 413,
          "errorCode": "REQUEST_ENTITY_TOO_LARGE",
          "errorName": "NominalChannelWriter:PointsTooLarge",
          "description": "The size of the points being written exceeds the maximum allowed size."
        },
        {
          "status": 400,
          "errorCode": "INVALID_ARGUMENT",
          "errorName": "NominalChannelWriter:InvalidStruct",
          "description": "Ingested Struct is not a valid JSON struct"
        },
        {
          "status": 400,
          "errorCode": "INVALID_ARGUMENT",
          "errorName": "NominalChannelWriter:StructTooLarge",
          "description": "Struct value exceeds maximum allowed UTF-8 byte size."
        },
        {
          "status": 400,
          "errorCode": "INVALID_ARGUMENT",
          "errorName": "NominalChannelWriter:InvalidChannelName",
          "description": "The channel name is invalid."
        },
        {
          "status": 400,
          "errorCode": "INVALID_ARGUMENT",
          "errorName": "NominalChannelWriter:TooManySessionSources",
          "description": "The dataset has exceeded the maximum number of distinct active session sources allowed per hour. This is a best-effort limit enforced per channel-writer instance."
        },
        {
          "status": 400,
          "errorCode": "INVALID_ARGUMENT",
          "errorName": "NominalChannelWriter:TooManyChannelNameOverrides",
          "description": "The request specifies more channel name overrides than the maximum allowed."
        },
        {
          "status": 400,
          "errorCode": "INVALID_ARGUMENT",
          "errorName": "NominalChannelWriter:ReservedTagName",
          "description": "The request uses a tag name that is reserved for internal use. Remove the tag from the request."
        },
        {
          "status": 400,
          "errorCode": "INVALID_ARGUMENT",
          "errorName": "NominalChannelWriter:StreamingSessionRidNotAllowed",
          "description": "The request sets a streaming session rid, which is assigned by Nominal and cannot be provided by the client."
        },
        {
          "status": 400,
          "errorCode": "INVALID_ARGUMENT",
          "errorName": "NominalChannelWriter:DuplicateResolvedChannelName",
          "description": "Multiple ingested columns resolve to the same channel name after applying channelPrefix and channelNameOverrides. Resolved channel names must be unique within a single ingest."
        }
      ]
    }
  ]
}
