While implementing a Codec for my custom data type I was surprised that a Codec[String, MyType, CodecFormat.TextPlain] could not be used for query input.
This way the same Codec that can be used for path segments would be useable for query parameters, which makes sense to me. I am not even sure how the List[String] codec should behave. Can it be passed Nil if query parameter wasn’t provided in the URI, or is it guaranteed to always have at least 1 item? (Something like cats NonEmptyList would be useful here then).
it means that the codec needs to handle decoding of a list of values of the query parameter (as query parameters can be repeated). The codec might return errors if there are multiple, or not enough occurrences of the query parameter. That’s all handled via the DecodeResult value, which is used in Codec.map. More on codecs: Codecs — tapir 1.x documentation
In your case, if you have val myCodec: Codec[String, MyType, CodecFormat.TextPlain], you can use Codec.listHead(myCodec), which will give you a Codec[List[String], MyType, CodecFormat.TextPlain]. This will be applied automatically, if the myCodec value is available in the implicit scope, and you simply create the query parameter description as query[MyType].
You can also use a NonEmptyList, if required, using the cats integration: Datatypes integrations — tapir 1.x documentation. If you provide a Codec[String, MyType, TextPlain] in the implicit scope, you’ll also be able to create a query[NonEmptyList[MyType]], provided that the integration is in scope (imported).