diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElmClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElmClientCodegen.java
index 54be2fc33b112ef30fbd6166fc8aff11e003d84a..f10792fe1f3cb393ebc570c1b6e0c259c6be1530 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElmClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElmClientCodegen.java
@@ -88,7 +88,6 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
         super();
         outputFolder = "generated-code/elm";
         modelTemplateFiles.put("model.mustache", ".elm");
-        apiTemplateFiles.put("api.mustache", ".elm");
         templateDir = "elm";
 
         supportsInheritance = true;
@@ -198,6 +197,7 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
             case ELM_018:
                 LOGGER.info("Elm version: 0.18");
                 additionalProperties.put("isElm018", true);
+                apiTemplateFiles.put("api018.mustache", ".elm");
                 supportingFiles.add(new SupportingFile("DateOnly018.mustache", "src", "DateOnly.elm"));
                 supportingFiles.add(new SupportingFile("DateTime018.mustache", "src", "DateTime.elm"));
                 supportingFiles.add(new SupportingFile("elm-package018.mustache", "", "elm-package.json"));
@@ -206,6 +206,7 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
             case ELM_019:
                 LOGGER.info("Elm version: 0.19");
                 additionalProperties.put("isElm019", true);
+                apiTemplateFiles.put("api.mustache", ".elm");
                 supportingFiles.add(new SupportingFile("DateOnly.mustache", "src", "DateOnly.elm"));
                 supportingFiles.add(new SupportingFile("DateTime.mustache", "src", "DateTime.elm"));
                 supportingFiles.add(new SupportingFile("elm.mustache", "", "elm.json"));
@@ -423,14 +424,33 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
         final Map<String, Set<String>> dependencies = new HashMap<>();
 
         for (CodegenOperation op : ops) {
-            String path = op.path;
-            for (CodegenParameter param : op.pathParams) {
-                final String var = paramToString(param);
-                path = path.replace("{" + param.paramName + "}", "\" ++ " + var + " ++ \"");
-                hasDateTime = hasDateTime || param.isDateTime;
-                hasDate = hasDate || param.isDate;
+            if (ElmVersion.ELM_018.equals(elmVersion)) {
+                String path = op.path;
+                for (CodegenParameter param : op.pathParams) {
+                    final String var = paramToString(param, false, null);
+                    path = path.replace("{" + param.paramName + "}", "\" ++ " + var + " ++ \"");
+                    hasDateTime = hasDateTime || param.isDateTime;
+                    hasDate = hasDate || param.isDate;
+                }
+                op.path = ("\"" + path + "\"").replaceAll(" \\+\\+ \"\"", "");
+            } else {
+                final List<String> paths = Arrays.asList(op.path.substring(1).split("/"));
+                String path = paths.stream().map(str -> str.charAt(0) == '{' ? str : "\"" + str + "\"").collect(Collectors.joining(", "));
+                for (CodegenParameter param : op.pathParams) {
+                    String str = paramToString(param, false, null);
+                    path = path.replace("{" + param.paramName + "}", str);
+                    hasDateTime = hasDateTime || param.isDateTime;
+                    hasDate = hasDate || param.isDate;
+                }
+                op.path = path;
+
+                final String query = op.queryParams.stream()
+                    .map(param -> paramToString(param, true, "Url.string \"" + param.paramName + "\""))
+                    .collect(Collectors.joining(", "));
+                op.vendorExtensions.put("query", query);
+                // TODO headers
+                // TODO forms
             }
-            op.path = ("\"" + path + "\"").replaceAll(" \\+\\+ \"\"", "");
 
             if (op.bodyParam != null && !op.bodyParam.isPrimitiveType && !op.bodyParam.isMapContainer) {
                 final String encoder = (String) op.bodyParam.vendorExtensions.get(ENCODER);
@@ -523,26 +543,49 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
         return "(Just " + value + ")";
     }
 
-    private String paramToString(final CodegenParameter param) {
-        final String paramName = param.paramName;
+    private String paramToString(final CodegenParameter param, final boolean useMaybe, final String maybeMapResult) {
+        final String paramName = (ElmVersion.ELM_018.equals(elmVersion) ? "" : "params.") + param.paramName;
+        if (!useMaybe) {
+            param.required = true;
+        }
 
+        String mapFn = null;
         if (param.isString || param.isUuid || param.isBinary || param.isByteArray) {
-            return paramName;
+            mapFn = "";
         } else if (param.isBoolean) {
-            return "if " + paramName + " then \"true\" else \"false\"";
+            mapFn = "(\\val -> if val then \"true\" else \"false\")";
         } else if (param.isDateTime) {
-            return "DateTime.toString " + paramName;
+            mapFn = "DateTime.toString";
         } else if (param.isDate) {
-            return "DateOnly.toString " + paramName;
+            mapFn = "DateOnly.toString";
         } else if (ElmVersion.ELM_018.equals(elmVersion)) {
-            return "toString " + paramName;
+            mapFn = "toString";
         } else if (param.isInteger || param.isLong) {
-            return "String.fromInt " + paramName;
+            mapFn = "String.fromInt";
         } else if (param.isFloat || param.isDouble) {
-            return "String.fromFloat " + paramName;
+            mapFn = "String.fromFloat";
+        } else if (param.isListContainer) {
+            // TODO duplicate ALL types from parameter to property...
+            if (param.items.isString || param.items.isUuid || param.items.isBinary || param.items.isByteArray) {
+                mapFn = "String.join \",\"";
+            }
         }
-
-        throw new RuntimeException("Parameter '" + paramName + "' cannot be converted to a string. Please report the issue.");
+        if (mapFn == null) {
+            throw new RuntimeException("Parameter '" + param.paramName + "' cannot be converted to a string. Please report the issue.");
+        }
+        
+        if (param.isListContainer) {
+            if (!param.required) {
+                mapFn = "(" + mapFn + ")";
+            }
+        }
+        String mapResult = "";
+        if (maybeMapResult != null) {
+            mapResult = maybeMapResult + (param.required ? " <|" : " <<");
+        }
+        final String just = useMaybe ? "Just (" : "";
+        final String justEnd = useMaybe ? ")" : "";
+        return (param.required ? just : "Maybe.map") + mapResult + " " + mapFn + " " + paramName + (param.required ? justEnd : "");
     }
 
     @Override
diff --git a/modules/openapi-generator/src/main/resources/elm/api.mustache b/modules/openapi-generator/src/main/resources/elm/api.mustache
index ebe53eeac9301fc26b163655448184ba7f58d341..63d1f780695886ae0bd404bbef5b889f3010a134 100644
--- a/modules/openapi-generator/src/main/resources/elm/api.mustache
+++ b/modules/openapi-generator/src/main/resources/elm/api.mustache
@@ -5,6 +5,7 @@ module Request.{{classname}} exposing ({{#operations}}{{#operation}}{{^-first}},
 {{>imports}}import Dict
 import Http
 import Json.Decode as Decode
+import Url.Builder as Url
 
 
 basePath : String
@@ -18,16 +19,24 @@ basePath =
 {-| {{{notes}}}
 -}
 {{/notes}}
-{{operationId}} : {{#pathParams}}{{dataType}} -> {{/pathParams}}{{#bodyParam}}{{dataType}} -> {{/bodyParam}}Http.Request {{^responses}}(){{/responses}}{{#responses}}{{#-first}}{{^dataType}}(){{/dataType}}{{#isMapContainer}}(Dict.Dict String {{/isMapContainer}}{{#isListContainer}}(List {{/isListContainer}}{{dataType}}{{#isListContainer}}){{/isListContainer}}{{#isMapContainer}}){{/isMapContainer}}{{/-first}}{{/responses}}
-{{operationId}} {{#pathParams}}{{paramName}} {{/pathParams}}{{#bodyParam}}model {{/bodyParam}}=
-    { method = "{{httpMethod}}"
-    , url = basePath ++ {{{path}}}
-    , headers = []
-    , body = {{#bodyParam}}Http.jsonBody <| {{vendorExtensions.elmEncoder}} model{{/bodyParam}}{{^bodyParam}}Http.emptyBody{{/bodyParam}}
-    , expect = {{^responses}}Http.expectStringResponse (\_ -> Ok ()){{/responses}}{{#responses}}{{#-first}}{{^dataType}}Http.expectStringResponse (\_ -> Ok ()){{/dataType}}{{#dataType}}Http.expectJson {{#isMapContainer}}(Decode.dict {{/isMapContainer}}{{#isListContainer}}(Decode.list {{/isListContainer}}{{#vendorExtensions}}{{elmDecoder}}{{/vendorExtensions}}{{#isListContainer}}){{/isListContainer}}{{#isMapContainer}}){{/isMapContainer}}{{/dataType}}{{/-first}}{{/responses}}
-    , timeout = Just 30000
-    , withCredentials = False
+{{operationId}} :
+    { onSend : Result Http.Error {{^responses}}(){{/responses}}{{#responses}}{{#-first}}{{^dataType}}(){{/dataType}}{{#isMapContainer}}(Dict.Dict String {{/isMapContainer}}{{#isListContainer}}(List {{/isListContainer}}{{dataType}}{{#isListContainer}}){{/isListContainer}}{{#isMapContainer}}){{/isMapContainer}}{{/-first}}{{/responses}} -> msg
+{{#bodyParam}}    , body : {{^required}}Maybe {{/required}}{{dataType}}{{/bodyParam}}
+{{#pathParams}}    , {{paramName}} : {{#isListContainer}}List {{/isListContainer}}{{dataType}}{{/pathParams}}
+{{#queryParams}}    , {{paramName}} : {{^required}}Maybe ({{/required}}{{#isListContainer}}List {{/isListContainer}}{{dataType}}{{^required}}){{/required}}{{/queryParams}}
     }
-        |> Http.request
+    -> Cmd msg
+{{operationId}} params =
+    Http.request
+        { method = "{{httpMethod}}"
+        , headers = []
+        , url = Url.crossOrigin basePath
+            [{{{path}}}]
+            (List.filterMap identity [{{{vendorExtensions.query}}}])
+        , body = {{#bodyParam}}{{^required}}Maybe.withDefault Http.emptyBody <| Maybe.map ({{/required}}Http.jsonBody {{#required}}<|{{/required}}{{^required}}<<{{/required}} {{vendorExtensions.elmEncoder}}{{^required}}){{/required}} params.body{{/bodyParam}}{{^bodyParam}}Http.emptyBody{{/bodyParam}}
+        , expect = {{^responses}}Http.expectWhatever params.onSend{{/responses}}{{#responses}}{{#-first}}{{^dataType}}Http.expectWhatever params.onSend{{/dataType}}{{#dataType}}Http.expectJson params.onSend {{#isMapContainer}}(Decode.dict {{/isMapContainer}}{{#isListContainer}}(Decode.list {{/isListContainer}}{{#vendorExtensions}}{{elmDecoder}}{{/vendorExtensions}}{{#isListContainer}}){{/isListContainer}}{{#isMapContainer}}){{/isMapContainer}}{{/dataType}}{{/-first}}{{/responses}}
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
   {{/operation}}
 {{/operations}}
diff --git a/modules/openapi-generator/src/main/resources/elm/api018.mustache b/modules/openapi-generator/src/main/resources/elm/api018.mustache
new file mode 100644
index 0000000000000000000000000000000000000000..ebe53eeac9301fc26b163655448184ba7f58d341
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/elm/api018.mustache
@@ -0,0 +1,33 @@
+{{>licenseInfo}}
+
+module Request.{{classname}} exposing ({{#operations}}{{#operation}}{{^-first}}, {{/-first}}{{operationId}}{{/operation}}{{/operations}})
+
+{{>imports}}import Dict
+import Http
+import Json.Decode as Decode
+
+
+basePath : String
+basePath =
+    "{{basePath}}"
+{{#operations}}
+  {{#operation}}
+
+
+{{#notes}}
+{-| {{{notes}}}
+-}
+{{/notes}}
+{{operationId}} : {{#pathParams}}{{dataType}} -> {{/pathParams}}{{#bodyParam}}{{dataType}} -> {{/bodyParam}}Http.Request {{^responses}}(){{/responses}}{{#responses}}{{#-first}}{{^dataType}}(){{/dataType}}{{#isMapContainer}}(Dict.Dict String {{/isMapContainer}}{{#isListContainer}}(List {{/isListContainer}}{{dataType}}{{#isListContainer}}){{/isListContainer}}{{#isMapContainer}}){{/isMapContainer}}{{/-first}}{{/responses}}
+{{operationId}} {{#pathParams}}{{paramName}} {{/pathParams}}{{#bodyParam}}model {{/bodyParam}}=
+    { method = "{{httpMethod}}"
+    , url = basePath ++ {{{path}}}
+    , headers = []
+    , body = {{#bodyParam}}Http.jsonBody <| {{vendorExtensions.elmEncoder}} model{{/bodyParam}}{{^bodyParam}}Http.emptyBody{{/bodyParam}}
+    , expect = {{^responses}}Http.expectStringResponse (\_ -> Ok ()){{/responses}}{{#responses}}{{#-first}}{{^dataType}}Http.expectStringResponse (\_ -> Ok ()){{/dataType}}{{#dataType}}Http.expectJson {{#isMapContainer}}(Decode.dict {{/isMapContainer}}{{#isListContainer}}(Decode.list {{/isListContainer}}{{#vendorExtensions}}{{elmDecoder}}{{/vendorExtensions}}{{#isListContainer}}){{/isListContainer}}{{#isMapContainer}}){{/isMapContainer}}{{/dataType}}{{/-first}}{{/responses}}
+    , timeout = Just 30000
+    , withCredentials = False
+    }
+        |> Http.request
+  {{/operation}}
+{{/operations}}
diff --git a/modules/openapi-generator/src/main/resources/elm/elm.mustache b/modules/openapi-generator/src/main/resources/elm/elm.mustache
index 6028a740feb88bcaaa59139f400a3e4920257910..b8a06a11c1706ab0ac9a45099cbc4df5db87a657 100644
--- a/modules/openapi-generator/src/main/resources/elm/elm.mustache
+++ b/modules/openapi-generator/src/main/resources/elm/elm.mustache
@@ -7,18 +7,20 @@
     "dependencies": {
         "direct": {
             "NoRedInk/elm-json-decode-pipeline": "1.0.0",
-            "elm/browser": "1.0.0",
-            "elm/core": "1.0.0",
+            "elm/browser": "1.0.1",
+            "elm/core": "1.0.2",
             "elm/html": "1.0.0",
-            "elm/http": "1.0.0",
-            "elm/json": "1.0.0",
+            "elm/http": "2.0.0",
+            "elm/json": "1.1.2",
             "elm/time": "1.0.0",
-            "rtfeldman/elm-iso8601-date-strings": "1.0.0"
+            "elm/url": "1.0.0",
+            "rtfeldman/elm-iso8601-date-strings": "1.1.2"
         },
         "indirect": {
-            "elm/parser": "1.0.0",
-            "elm/url": "1.0.0",
-            "elm/virtual-dom": "1.0.0"
+            "elm/bytes": "1.0.5",
+            "elm/file": "1.0.1",
+            "elm/parser": "1.1.0",
+            "elm/virtual-dom": "1.0.2"
         }
     },
     "test-dependencies": {
diff --git a/samples/client/petstore/elm-0.18/.openapi-generator/VERSION b/samples/client/petstore/elm-0.18/.openapi-generator/VERSION
index a65271290834788af127bf37a18e53ad80d514c6..afa6365606414bf56f925745712166af5b4a2be0 100644
--- a/samples/client/petstore/elm-0.18/.openapi-generator/VERSION
+++ b/samples/client/petstore/elm-0.18/.openapi-generator/VERSION
@@ -1 +1 @@
-3.3.2-SNAPSHOT
\ No newline at end of file
+4.0.0-SNAPSHOT
\ No newline at end of file
diff --git a/samples/client/petstore/elm/.openapi-generator/VERSION b/samples/client/petstore/elm/.openapi-generator/VERSION
index a65271290834788af127bf37a18e53ad80d514c6..afa6365606414bf56f925745712166af5b4a2be0 100644
--- a/samples/client/petstore/elm/.openapi-generator/VERSION
+++ b/samples/client/petstore/elm/.openapi-generator/VERSION
@@ -1 +1 @@
-3.3.2-SNAPSHOT
\ No newline at end of file
+4.0.0-SNAPSHOT
\ No newline at end of file
diff --git a/samples/client/petstore/elm/elm.json b/samples/client/petstore/elm/elm.json
index 6028a740feb88bcaaa59139f400a3e4920257910..b8a06a11c1706ab0ac9a45099cbc4df5db87a657 100644
--- a/samples/client/petstore/elm/elm.json
+++ b/samples/client/petstore/elm/elm.json
@@ -7,18 +7,20 @@
     "dependencies": {
         "direct": {
             "NoRedInk/elm-json-decode-pipeline": "1.0.0",
-            "elm/browser": "1.0.0",
-            "elm/core": "1.0.0",
+            "elm/browser": "1.0.1",
+            "elm/core": "1.0.2",
             "elm/html": "1.0.0",
-            "elm/http": "1.0.0",
-            "elm/json": "1.0.0",
+            "elm/http": "2.0.0",
+            "elm/json": "1.1.2",
             "elm/time": "1.0.0",
-            "rtfeldman/elm-iso8601-date-strings": "1.0.0"
+            "elm/url": "1.0.0",
+            "rtfeldman/elm-iso8601-date-strings": "1.1.2"
         },
         "indirect": {
-            "elm/parser": "1.0.0",
-            "elm/url": "1.0.0",
-            "elm/virtual-dom": "1.0.0"
+            "elm/bytes": "1.0.5",
+            "elm/file": "1.0.1",
+            "elm/parser": "1.1.0",
+            "elm/virtual-dom": "1.0.2"
         }
     },
     "test-dependencies": {
diff --git a/samples/client/petstore/elm/src/Request/Pet.elm b/samples/client/petstore/elm/src/Request/Pet.elm
index aa46bd8df6925e663ccb0c87f981b422b311482c..7fe501237bd21fd136ffa32fa0b7dd1f638c1f85 100644
--- a/samples/client/petstore/elm/src/Request/Pet.elm
+++ b/samples/client/petstore/elm/src/Request/Pet.elm
@@ -17,6 +17,7 @@ import Data.Pet as Pet exposing (Pet)
 import Dict
 import Http
 import Json.Decode as Decode
+import Url.Builder as Url
 
 
 basePath : String
@@ -24,111 +25,167 @@ basePath =
     "http://petstore.swagger.io/v2"
 
 
-addPet : Pet -> Http.Request ()
-addPet model =
-    { method = "POST"
-    , url = basePath ++ "/pet"
-    , headers = []
-    , body = Http.jsonBody <| Pet.encoder model
-    , expect = Http.expectStringResponse (\_ -> Ok ())
-    , timeout = Just 30000
-    , withCredentials = False
+addPet :
+    { onSend : Result Http.Error () -> msg
+    , body : Pet
     }
-        |> Http.request
-
-
-deletePet : Int -> Http.Request ()
-deletePet petId =
-    { method = "DELETE"
-    , url = basePath ++ "/pet/" ++ String.fromInt petId
-    , headers = []
-    , body = Http.emptyBody
-    , expect = Http.expectStringResponse (\_ -> Ok ())
-    , timeout = Just 30000
-    , withCredentials = False
+    -> Cmd msg
+addPet params =
+    Http.request
+        { method = "POST"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "pet" ]
+                (List.filterMap identity [])
+        , body = Http.jsonBody <| Pet.encoder params.body
+        , expect = Http.expectWhatever params.onSend
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
+
+
+deletePet :
+    { onSend : Result Http.Error () -> msg
+    , petId : Int
     }
-        |> Http.request
+    -> Cmd msg
+deletePet params =
+    Http.request
+        { method = "DELETE"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "pet", String.fromInt params.petId ]
+                (List.filterMap identity [])
+        , body = Http.emptyBody
+        , expect = Http.expectWhatever params.onSend
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
 
 
 {-| Multiple status values can be provided with comma separated strings
 -}
-findPetsByStatus : Http.Request (List Pet)
-findPetsByStatus =
-    { method = "GET"
-    , url = basePath ++ "/pet/findByStatus"
-    , headers = []
-    , body = Http.emptyBody
-    , expect = Http.expectJson (Decode.list Pet.decoder)
-    , timeout = Just 30000
-    , withCredentials = False
+findPetsByStatus :
+    { onSend : Result Http.Error (List Pet) -> msg
+    , status : List String
     }
-        |> Http.request
+    -> Cmd msg
+findPetsByStatus params =
+    Http.request
+        { method = "GET"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "pet", "findByStatus" ]
+                (List.filterMap identity [ Just (Url.string "status" <| String.join "," params.status) ])
+        , body = Http.emptyBody
+        , expect = Http.expectJson params.onSend (Decode.list Pet.decoder)
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
 
 
 {-| Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
 -}
-findPetsByTags : Http.Request (List Pet)
-findPetsByTags =
-    { method = "GET"
-    , url = basePath ++ "/pet/findByTags"
-    , headers = []
-    , body = Http.emptyBody
-    , expect = Http.expectJson (Decode.list Pet.decoder)
-    , timeout = Just 30000
-    , withCredentials = False
+findPetsByTags :
+    { onSend : Result Http.Error (List Pet) -> msg
+    , tags : List String
     }
-        |> Http.request
+    -> Cmd msg
+findPetsByTags params =
+    Http.request
+        { method = "GET"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "pet", "findByTags" ]
+                (List.filterMap identity [ Just (Url.string "tags" <| String.join "," params.tags) ])
+        , body = Http.emptyBody
+        , expect = Http.expectJson params.onSend (Decode.list Pet.decoder)
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
 
 
 {-| Returns a single pet
 -}
-getPetById : Int -> Http.Request Pet
-getPetById petId =
-    { method = "GET"
-    , url = basePath ++ "/pet/" ++ String.fromInt petId
-    , headers = []
-    , body = Http.emptyBody
-    , expect = Http.expectJson Pet.decoder
-    , timeout = Just 30000
-    , withCredentials = False
+getPetById :
+    { onSend : Result Http.Error Pet -> msg
+    , petId : Int
     }
-        |> Http.request
-
-
-updatePet : Pet -> Http.Request ()
-updatePet model =
-    { method = "PUT"
-    , url = basePath ++ "/pet"
-    , headers = []
-    , body = Http.jsonBody <| Pet.encoder model
-    , expect = Http.expectStringResponse (\_ -> Ok ())
-    , timeout = Just 30000
-    , withCredentials = False
+    -> Cmd msg
+getPetById params =
+    Http.request
+        { method = "GET"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "pet", String.fromInt params.petId ]
+                (List.filterMap identity [])
+        , body = Http.emptyBody
+        , expect = Http.expectJson params.onSend Pet.decoder
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
+
+
+updatePet :
+    { onSend : Result Http.Error () -> msg
+    , body : Pet
     }
-        |> Http.request
-
-
-updatePetWithForm : Int -> Http.Request ()
-updatePetWithForm petId =
-    { method = "POST"
-    , url = basePath ++ "/pet/" ++ String.fromInt petId
-    , headers = []
-    , body = Http.emptyBody
-    , expect = Http.expectStringResponse (\_ -> Ok ())
-    , timeout = Just 30000
-    , withCredentials = False
+    -> Cmd msg
+updatePet params =
+    Http.request
+        { method = "PUT"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "pet" ]
+                (List.filterMap identity [])
+        , body = Http.jsonBody <| Pet.encoder params.body
+        , expect = Http.expectWhatever params.onSend
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
+
+
+updatePetWithForm :
+    { onSend : Result Http.Error () -> msg
+    , petId : Int
     }
-        |> Http.request
-
-
-uploadFile : Int -> Http.Request ApiResponse
-uploadFile petId =
-    { method = "POST"
-    , url = basePath ++ "/pet/" ++ String.fromInt petId ++ "/uploadImage"
-    , headers = []
-    , body = Http.emptyBody
-    , expect = Http.expectJson ApiResponse.decoder
-    , timeout = Just 30000
-    , withCredentials = False
+    -> Cmd msg
+updatePetWithForm params =
+    Http.request
+        { method = "POST"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "pet", String.fromInt params.petId ]
+                (List.filterMap identity [])
+        , body = Http.emptyBody
+        , expect = Http.expectWhatever params.onSend
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
+
+
+uploadFile :
+    { onSend : Result Http.Error ApiResponse -> msg
+    , petId : Int
     }
-        |> Http.request
+    -> Cmd msg
+uploadFile params =
+    Http.request
+        { method = "POST"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "pet", String.fromInt params.petId, "uploadImage" ]
+                (List.filterMap identity [])
+        , body = Http.emptyBody
+        , expect = Http.expectJson params.onSend ApiResponse.decoder
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
diff --git a/samples/client/petstore/elm/src/Request/Store.elm b/samples/client/petstore/elm/src/Request/Store.elm
index d0192277a9bb533f67c2ef26633d1394f3324181..6bc60e9ac436010d056dcbb0dc78c1d88217570c 100644
--- a/samples/client/petstore/elm/src/Request/Store.elm
+++ b/samples/client/petstore/elm/src/Request/Store.elm
@@ -16,6 +16,7 @@ import Data.Order_ as Order_ exposing (Order_)
 import Dict
 import Http
 import Json.Decode as Decode
+import Url.Builder as Url
 
 
 basePath : String
@@ -25,57 +26,84 @@ basePath =
 
 {-| For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
 -}
-deleteOrder : String -> Http.Request ()
-deleteOrder orderId =
-    { method = "DELETE"
-    , url = basePath ++ "/store/order/" ++ orderId
-    , headers = []
-    , body = Http.emptyBody
-    , expect = Http.expectStringResponse (\_ -> Ok ())
-    , timeout = Just 30000
-    , withCredentials = False
+deleteOrder :
+    { onSend : Result Http.Error () -> msg
+    , orderId : String
     }
-        |> Http.request
+    -> Cmd msg
+deleteOrder params =
+    Http.request
+        { method = "DELETE"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "store", "order", params.orderId ]
+                (List.filterMap identity [])
+        , body = Http.emptyBody
+        , expect = Http.expectWhatever params.onSend
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
 
 
 {-| Returns a map of status codes to quantities
 -}
-getInventory : Http.Request (Dict.Dict String Int)
-getInventory =
-    { method = "GET"
-    , url = basePath ++ "/store/inventory"
-    , headers = []
-    , body = Http.emptyBody
-    , expect = Http.expectJson (Decode.dict Decode.int)
-    , timeout = Just 30000
-    , withCredentials = False
+getInventory :
+    { onSend : Result Http.Error (Dict.Dict String Int) -> msg
     }
-        |> Http.request
+    -> Cmd msg
+getInventory params =
+    Http.request
+        { method = "GET"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "store", "inventory" ]
+                (List.filterMap identity [])
+        , body = Http.emptyBody
+        , expect = Http.expectJson params.onSend (Decode.dict Decode.int)
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
 
 
 {-| For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions
 -}
-getOrderById : Int -> Http.Request Order_
-getOrderById orderId =
-    { method = "GET"
-    , url = basePath ++ "/store/order/" ++ String.fromInt orderId
-    , headers = []
-    , body = Http.emptyBody
-    , expect = Http.expectJson Order_.decoder
-    , timeout = Just 30000
-    , withCredentials = False
+getOrderById :
+    { onSend : Result Http.Error Order_ -> msg
+    , orderId : Int
     }
-        |> Http.request
+    -> Cmd msg
+getOrderById params =
+    Http.request
+        { method = "GET"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "store", "order", String.fromInt params.orderId ]
+                (List.filterMap identity [])
+        , body = Http.emptyBody
+        , expect = Http.expectJson params.onSend Order_.decoder
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
 
 
-placeOrder : Order_ -> Http.Request Order_
-placeOrder model =
-    { method = "POST"
-    , url = basePath ++ "/store/order"
-    , headers = []
-    , body = Http.jsonBody <| Order_.encoder model
-    , expect = Http.expectJson Order_.decoder
-    , timeout = Just 30000
-    , withCredentials = False
+placeOrder :
+    { onSend : Result Http.Error Order_ -> msg
+    , body : Order_
     }
-        |> Http.request
+    -> Cmd msg
+placeOrder params =
+    Http.request
+        { method = "POST"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "store", "order" ]
+                (List.filterMap identity [])
+        , body = Http.jsonBody <| Order_.encoder params.body
+        , expect = Http.expectJson params.onSend Order_.decoder
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
diff --git a/samples/client/petstore/elm/src/Request/User.elm b/samples/client/petstore/elm/src/Request/User.elm
index b466fa6c51684083cd69ad8a59c7fad7bf34f058..0a8009fddce8f3954c3414ca9c39a77bf208ccdf 100644
--- a/samples/client/petstore/elm/src/Request/User.elm
+++ b/samples/client/petstore/elm/src/Request/User.elm
@@ -16,6 +16,7 @@ import Data.User as User exposing (User)
 import Dict
 import Http
 import Json.Decode as Decode
+import Url.Builder as Url
 
 
 basePath : String
@@ -25,109 +26,166 @@ basePath =
 
 {-| This can only be done by the logged in user.
 -}
-createUser : User -> Http.Request ()
-createUser model =
-    { method = "POST"
-    , url = basePath ++ "/user"
-    , headers = []
-    , body = Http.jsonBody <| User.encoder model
-    , expect = Http.expectStringResponse (\_ -> Ok ())
-    , timeout = Just 30000
-    , withCredentials = False
+createUser :
+    { onSend : Result Http.Error () -> msg
+    , body : User
     }
-        |> Http.request
-
-
-createUsersWithArrayInput : User -> Http.Request ()
-createUsersWithArrayInput model =
-    { method = "POST"
-    , url = basePath ++ "/user/createWithArray"
-    , headers = []
-    , body = Http.jsonBody <| User.encoder model
-    , expect = Http.expectStringResponse (\_ -> Ok ())
-    , timeout = Just 30000
-    , withCredentials = False
+    -> Cmd msg
+createUser params =
+    Http.request
+        { method = "POST"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "user" ]
+                (List.filterMap identity [])
+        , body = Http.jsonBody <| User.encoder params.body
+        , expect = Http.expectWhatever params.onSend
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
+
+
+createUsersWithArrayInput :
+    { onSend : Result Http.Error () -> msg
+    , body : User
     }
-        |> Http.request
-
-
-createUsersWithListInput : User -> Http.Request ()
-createUsersWithListInput model =
-    { method = "POST"
-    , url = basePath ++ "/user/createWithList"
-    , headers = []
-    , body = Http.jsonBody <| User.encoder model
-    , expect = Http.expectStringResponse (\_ -> Ok ())
-    , timeout = Just 30000
-    , withCredentials = False
+    -> Cmd msg
+createUsersWithArrayInput params =
+    Http.request
+        { method = "POST"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "user", "createWithArray" ]
+                (List.filterMap identity [])
+        , body = Http.jsonBody <| User.encoder params.body
+        , expect = Http.expectWhatever params.onSend
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
+
+
+createUsersWithListInput :
+    { onSend : Result Http.Error () -> msg
+    , body : User
     }
-        |> Http.request
+    -> Cmd msg
+createUsersWithListInput params =
+    Http.request
+        { method = "POST"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "user", "createWithList" ]
+                (List.filterMap identity [])
+        , body = Http.jsonBody <| User.encoder params.body
+        , expect = Http.expectWhatever params.onSend
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
 
 
 {-| This can only be done by the logged in user.
 -}
-deleteUser : String -> Http.Request ()
-deleteUser username =
-    { method = "DELETE"
-    , url = basePath ++ "/user/" ++ username
-    , headers = []
-    , body = Http.emptyBody
-    , expect = Http.expectStringResponse (\_ -> Ok ())
-    , timeout = Just 30000
-    , withCredentials = False
+deleteUser :
+    { onSend : Result Http.Error () -> msg
+    , username : String
     }
-        |> Http.request
-
-
-getUserByName : String -> Http.Request User
-getUserByName username =
-    { method = "GET"
-    , url = basePath ++ "/user/" ++ username
-    , headers = []
-    , body = Http.emptyBody
-    , expect = Http.expectJson User.decoder
-    , timeout = Just 30000
-    , withCredentials = False
+    -> Cmd msg
+deleteUser params =
+    Http.request
+        { method = "DELETE"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "user", params.username ]
+                (List.filterMap identity [])
+        , body = Http.emptyBody
+        , expect = Http.expectWhatever params.onSend
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
+
+
+getUserByName :
+    { onSend : Result Http.Error User -> msg
+    , username : String
     }
-        |> Http.request
-
-
-loginUser : Http.Request String
-loginUser =
-    { method = "GET"
-    , url = basePath ++ "/user/login"
-    , headers = []
-    , body = Http.emptyBody
-    , expect = Http.expectJson Decode.string
-    , timeout = Just 30000
-    , withCredentials = False
+    -> Cmd msg
+getUserByName params =
+    Http.request
+        { method = "GET"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "user", params.username ]
+                (List.filterMap identity [])
+        , body = Http.emptyBody
+        , expect = Http.expectJson params.onSend User.decoder
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
+
+
+loginUser :
+    { onSend : Result Http.Error String -> msg
+    , username : String
+    , password : String
     }
-        |> Http.request
-
-
-logoutUser : Http.Request ()
-logoutUser =
-    { method = "GET"
-    , url = basePath ++ "/user/logout"
-    , headers = []
-    , body = Http.emptyBody
-    , expect = Http.expectStringResponse (\_ -> Ok ())
-    , timeout = Just 30000
-    , withCredentials = False
+    -> Cmd msg
+loginUser params =
+    Http.request
+        { method = "GET"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "user", "login" ]
+                (List.filterMap identity [ Just (Url.string "username" <| params.username), Just (Url.string "password" <| params.password) ])
+        , body = Http.emptyBody
+        , expect = Http.expectJson params.onSend Decode.string
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
+
+
+logoutUser :
+    { onSend : Result Http.Error () -> msg
     }
-        |> Http.request
+    -> Cmd msg
+logoutUser params =
+    Http.request
+        { method = "GET"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "user", "logout" ]
+                (List.filterMap identity [])
+        , body = Http.emptyBody
+        , expect = Http.expectWhatever params.onSend
+        , timeout = Just 30000
+        , tracker = Nothing
+        }
 
 
 {-| This can only be done by the logged in user.
 -}
-updateUser : String -> User -> Http.Request ()
-updateUser username model =
-    { method = "PUT"
-    , url = basePath ++ "/user/" ++ username
-    , headers = []
-    , body = Http.jsonBody <| User.encoder model
-    , expect = Http.expectStringResponse (\_ -> Ok ())
-    , timeout = Just 30000
-    , withCredentials = False
+updateUser :
+    { onSend : Result Http.Error () -> msg
+    , body : User
+    , username : String
     }
-        |> Http.request
+    -> Cmd msg
+updateUser params =
+    Http.request
+        { method = "PUT"
+        , headers = []
+        , url =
+            Url.crossOrigin basePath
+                [ "user", params.username ]
+                (List.filterMap identity [])
+        , body = Http.jsonBody <| User.encoder params.body
+        , expect = Http.expectWhatever params.onSend
+        , timeout = Just 30000
+        , tracker = Nothing
+        }