diff --git a/CHANGELOG.md b/CHANGELOG.md
index df88cf192583e6d97f67a6997f0de246b9d6101b..3e0eff992547c16600537456c3fff71a0441ace1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,36 @@
 
 All notable changes to this project will be documented in this file.
 
+## [0.4.0] - 2023-12-26
+
+### Documentation
+
+- Updates and fixes
+
+### Features
+
+- Initial functions support in the query builder API
+- Initial impl of promql validation macro
+
+### Refactor
+
+- Remove an error variant that is never used
+
+### Miscellaneous Tasks
+
+- Generate changelog for v0.4.0
+- Bump version to 0.4.0
+
+## [0.3.1] - 2023-12-20
+
+### Bug Fixes
+
+- Correct Sealed trait's visibility
+
+### Miscellaneous Tasks
+
+- Bump version to 0.3.1
+
 ## [0.3.0] - 2023-12-19
 
 ### Bug Fixes
diff --git a/Cargo.toml b/Cargo.toml
index cf218369aa13f2b1097f1aa24d75836ae8b91161..18d90aa13522d4f25b3560caca8a5bb096089d44 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "mquery"
-version = "0.3.1"
+version = "0.4.0"
 edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
diff --git a/README.md b/README.md
index aabe2340cb131147ead0fb8305a815dbde7f1d63..0248e873bd51696cebe8fa483cce0c22b1b3ca9d 100644
--- a/README.md
+++ b/README.md
@@ -36,16 +36,15 @@ Requires a local Victoria Metrics server running at `http://127.0.0.1:8428/` for
 
 # Roadmap
 - [x] Basic raw queries (Instant and Ranged)
-- [ ] Query Builder
+- [x] Query Builder
   - [x] Basic queries
-  - [ ] Operators
+  - [x] Operators
     - [x] Binary Operators
     - [x] Vector matching
-    - [ ] Aggregation operators
-  - [ ] Functions
-- [ ] Runtime syntax checking
-- [ ] Compile time syntax checking
+    - [x] Aggregation operators (implemented as functions)
+  - [x] Functions (initial support for most important fns)
+- [ ] Runtime syntax checking (?)
+- [x] Compile time syntax checking
 - [x] ~~Deserialize~~ Convert to custom data types
 - [ ] ORM-like API to build queries using user defined types (derive macro)
-- [ ] Encapsulated raw queries with methods for constructing interpolated versions
 - [ ] Processing multiple queries at once
diff --git a/src/result.rs b/src/result.rs
index 949d5ad80b4413991409e39c6e3157dbb064d6bd..56b25ea21c9f0c3e27267662f479d57723760e26 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -23,7 +23,7 @@ impl IntoQryResult for Result<response::PromqlResult, error::Error> {
     }
 }
 
-/// A wrapper for possible result types of expression queries ([`Client::query`](crate::Client::query) and [`Client::query_range`](crate::Client::query_range)).
+/// A wrapper for possible result types of expression queries
 #[derive(Clone, Debug, EnumAsInner)]
 pub enum Data {
     Vector(Vec<response::InstantVector>),
@@ -43,7 +43,7 @@ impl From<response::PromqlResult> for Data {
 }
 
 impl Data {
-    /// This is a shortcut to check if the query returned any data at all regardless of the exact type.
+    /// A shortcut to check if the query returned any data at all regardless of the exact type.
     pub fn is_empty(&self) -> bool {
         match self {
             Data::Vector(v) => v.is_empty(),
@@ -66,10 +66,6 @@ pub enum Error {
     /// Occurs when Prometheus responds with e.g. HTTP 4xx (e.g. due to a syntax error in a PromQL query).<br>
     /// Details on the error as reported by Prometheus are included in [`PrometheusError`].
     Prometheus(PrometheusError),
-    /// Occurs when the [`Client::series`](crate::Client::series) method is called with an empty set of
-    /// series [`Selector`](crate::selector::Selector)s. According to the Prometheus API description at least one
-    /// [`Selector`](crate::selector::Selector) must be provided.
-    EmptySeriesSelector,
 }
 
 impl Display for Error {
@@ -77,7 +73,6 @@ impl Display for Error {
         match self {
             Self::Client(e) => e.fmt(f),
             Self::Prometheus(e) => e.fmt(f),
-            Self::EmptySeriesSelector => f.write_str("at least one series selector must be provided in order to query the series endpoint"),
         }
     }
 }
@@ -87,7 +82,6 @@ impl std::error::Error for Error {
         match self {
             Self::Client(e) => e.source(),
             Self::Prometheus(p) => p.source(),
-            Self::EmptySeriesSelector => None,
         }
     }
 }
@@ -97,7 +91,6 @@ impl From<prometheus_http_query::Error> for Error {
         match value {
             prometheus_http_query::Error::Client(c) => Self::Client(c.into()),
             prometheus_http_query::Error::Prometheus(p) => Self::Prometheus(p.into()),
-            prometheus_http_query::Error::EmptySeriesSelector => Self::EmptySeriesSelector,
             _ => unreachable!(),
         }
     }
@@ -212,8 +205,7 @@ impl fmt::Display for PrometheusErrorType {
     }
 }
 
-/// Is thrown when the [`Client`](crate::Client) or the underlying
-/// [`reqwest::Error`] fail to build or execute a request.
+/// Is thrown when the [`reqwest::Error`] fails to build or execute a request.
 #[derive(Debug, Clone)]
 pub struct ClientError(String);