diff --git a/src/ReC.Client/ReCClientHelpers.cs b/src/ReC.Client/ReCClientHelpers.cs
new file mode 100644
index 0000000..0102710
--- /dev/null
+++ b/src/ReC.Client/ReCClientHelpers.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Globalization;
+using System.Linq;
+using System.Net.Http.Json;
+
+#if NETFRAMEWORK
+using System.Net.Http;
+#endif
+
+namespace ReC.Client
+{
+ ///
+ /// Provides shared helpers for composing requests.
+ ///
+ internal static class ReCClientHelpers
+ {
+#if NETFRAMEWORK
+ ///
+ /// Builds a query string from the provided key/value pairs, skipping null values.
+ ///
+ /// The key/value pairs to include in the query string.
+ /// A query string beginning with '?', or an empty string if no values are provided.
+ public static string BuildQuery(params (string Key, object Value)[] parameters)
+#else
+ ///
+ /// Builds a query string from the provided key/value pairs, skipping null values.
+ ///
+ /// The key/value pairs to include in the query string.
+ /// A query string beginning with '?', or an empty string if no values are provided.
+ public static string BuildQuery(params (string Key, object? Value)[] parameters)
+#endif
+ {
+ var parts = parameters
+ .Where(p => p.Value != null)
+ .Select(p => $"{Uri.EscapeDataString(p.Key)}={Uri.EscapeDataString(Convert.ToString(p.Value, CultureInfo.InvariantCulture) ?? string.Empty)}");
+
+ var query = string.Join("&", parts);
+ return string.IsNullOrWhiteSpace(query) ? string.Empty : $"?{query}";
+ }
+
+ ///
+ /// Creates a JSON content payload from the provided object.
+ ///
+ /// The type of the payload.
+ /// The payload to serialize.
+ /// A instance ready for HTTP requests.
+ public static JsonContent ToJsonContent(T payload) => JsonContent.Create(payload);
+ }
+}