diff --git a/NGitLab.Mock/Clients/GroupVariableClient.cs b/NGitLab.Mock/Clients/GroupVariableClient.cs
index 1a12457c..e135f2f3 100644
--- a/NGitLab.Mock/Clients/GroupVariableClient.cs
+++ b/NGitLab.Mock/Clients/GroupVariableClient.cs
@@ -14,7 +14,9 @@ public GroupVariableClient(ClientContext context, GroupId groupId)
         _groupId = Server.AllGroups.FindGroup(groupId.ValueAsString()).Id;
     }
 
-    public Variable this[string key] => throw new NotImplementedException();
+    public Variable this[string key] => this[key, null];
+
+    public Variable this[string key, string environmentScope] => throw new NotImplementedException();
 
     public IEnumerable<Variable> All => throw new NotImplementedException();
 
@@ -23,12 +25,16 @@ public Variable Create(VariableCreate model)
         throw new NotImplementedException();
     }
 
-    public void Delete(string key)
+    public void Delete(string key) => Delete(key, null);
+
+    public void Delete(string key, string environmentScope)
     {
         throw new NotImplementedException();
     }
 
-    public Variable Update(string key, VariableUpdate model)
+    public Variable Update(string key, VariableUpdate model) => Update(key, null, model);
+
+    public Variable Update(string key, string environmentScope, VariableUpdate model)
     {
         throw new NotImplementedException();
     }
diff --git a/NGitLab.Mock/Clients/ProjectVariableClient.cs b/NGitLab.Mock/Clients/ProjectVariableClient.cs
index 137dfb03..ce88da54 100644
--- a/NGitLab.Mock/Clients/ProjectVariableClient.cs
+++ b/NGitLab.Mock/Clients/ProjectVariableClient.cs
@@ -14,7 +14,9 @@ public ProjectVariableClient(ClientContext context, ProjectId projectId)
         _projectId = Server.AllProjects.FindProject(projectId.ValueAsString()).Id;
     }
 
-    public Variable this[string key] => throw new NotImplementedException();
+    public Variable this[string key] => this[key, null];
+
+    public Variable this[string key, string environmentScope] => throw new NotImplementedException();
 
     public IEnumerable<Variable> All => throw new NotImplementedException();
 
@@ -23,12 +25,16 @@ public Variable Create(VariableCreate model)
         throw new NotImplementedException();
     }
 
-    public void Delete(string key)
+    public void Delete(string key) => Delete(key, null);
+
+    public void Delete(string key, string environmentScope)
     {
         throw new NotImplementedException();
     }
 
-    public Variable Update(string key, VariableUpdate model)
+    public Variable Update(string key, VariableUpdate model) => Update(key, null, model);
+
+    public Variable Update(string key, string environmentScope, VariableUpdate model)
     {
         throw new NotImplementedException();
     }
diff --git a/NGitLab.Tests/GroupVariableClientTests.cs b/NGitLab.Tests/GroupVariableClientTests.cs
index 067e3e2f..43e6f8ec 100644
--- a/NGitLab.Tests/GroupVariableClientTests.cs
+++ b/NGitLab.Tests/GroupVariableClientTests.cs
@@ -1,7 +1,9 @@
 using System.Linq;
+using System.Net;
 using System.Threading.Tasks;
 using NGitLab.Models;
 using NGitLab.Tests.Docker;
+using NuGet.Versioning;
 using NUnit.Framework;
 
 namespace NGitLab.Tests;
@@ -52,4 +54,67 @@ public async Task Test_group_variables()
         variables = groupVariableClient.All.ToList();
         Assert.That(variables, Has.Count.EqualTo(3));
     }
+
+    [Test]
+    [NGitLabRetry]
+    public async Task Test_group_variables_with_complete_members()
+    {
+        using var context = await GitLabTestContext.CreateAsync();
+        var group = context.CreateGroup();
+        var groupVariableClient = context.Client.GetGroupVariableClient(group.Id);
+
+        // Create
+        var variable = groupVariableClient.Create(new VariableCreate
+        {
+            Key = "My_Key",
+            Value = "My value",
+            Description = "Some important variable",
+            Protected = true,
+            Type = VariableType.Variable,
+            Masked = false,
+            Raw = false,
+        });
+
+        Assert.That(variable.Key, Is.EqualTo("My_Key"));
+        Assert.That(variable.Value, Is.EqualTo("My value"));
+
+        if (context.IsGitLabVersionInRange(VersionRange.Parse("[16.2,)"), out _))
+        {
+            Assert.That(variable.Description, Is.EqualTo("Some important variable"));
+        }
+
+        Assert.That(variable.Protected, Is.EqualTo(true));
+        Assert.That(variable.Type, Is.EqualTo(VariableType.Variable));
+        Assert.That(variable.Masked, Is.EqualTo(false));
+        Assert.That(variable.Raw, Is.EqualTo(false));
+
+        // Update
+        var newScope = "integration/*";
+        variable = groupVariableClient.Update(variable.Key, variable.EnvironmentScope, new VariableUpdate
+        {
+            Value = "My value edited",
+            Protected = false,
+            EnvironmentScope = newScope
+        });
+
+        Assert.That(variable.Key, Is.EqualTo("My_Key"));
+        Assert.That(variable.Value, Is.EqualTo("My value edited"));
+        Assert.That(variable.Protected, Is.EqualTo(false));
+
+        // Delete
+        var ex = Assert.Throws<GitLabException>(() => groupVariableClient.Delete(variable.Key, "wrongScope"));
+        Assert.That(ex!.StatusCode == HttpStatusCode.NotFound);
+
+        groupVariableClient.Delete(variable.Key);
+
+        var variables = groupVariableClient.All.ToList();
+        Assert.That(variables, Is.Empty);
+
+        // All
+        groupVariableClient.Create(new VariableCreate { Key = "Variable1", Value = "test", EnvironmentScope = "test/*" });
+        groupVariableClient.Create(new VariableCreate { Key = "Variable2", Value = "test", EnvironmentScope = "integration" });
+        groupVariableClient.Create(new VariableCreate { Key = "Variable3", Value = "test", EnvironmentScope = "*" });
+        variables = groupVariableClient.All.ToList();
+        Assert.That(variables, Has.Count.EqualTo(3));
+    }
 }
diff --git a/NGitLab.Tests/ProjectVariableClientTests.cs b/NGitLab.Tests/ProjectVariableClientTests.cs
index 87b5d673..096ea5cb 100644
--- a/NGitLab.Tests/ProjectVariableClientTests.cs
+++ b/NGitLab.Tests/ProjectVariableClientTests.cs
@@ -1,7 +1,10 @@
 using System.Linq;
+using System.Net;
 using System.Threading.Tasks;
+using NGitLab.Extensions;
 using NGitLab.Models;
 using NGitLab.Tests.Docker;
+using NuGet.Versioning;
 using NUnit.Framework;
 
 namespace NGitLab.Tests;
@@ -52,4 +55,94 @@ public async Task Test_project_variables()
         variables = projectVariableClient.All.ToList();
         Assert.That(variables, Has.Count.EqualTo(3));
     }
+
+    [Test]
+    [NGitLabRetry]
+    public async Task Test_project_variables_with_scope()
+    {
+        using var context = await GitLabTestContext.CreateAsync();
+        var project = context.CreateProject();
+        var projectVariableClient = context.Client.GetProjectVariableClient(project.Id);
+
+        // Create
+        var firstScope = "test/*";
+        var changingScopeVariable = projectVariableClient.Create(new VariableCreate
+        {
+            Key = "My_Key",
+            Value = "My value",
+            Description = "Some important variable",
+            Protected = true,
+            Type = VariableType.Variable,
+            Masked = false,
+            Raw = false,
+            EnvironmentScope = firstScope,
+        });
+
+        var integrationScope = "integration/*";
+        var integrationVariable = projectVariableClient.Create(new VariableCreate
+        {
+            Key = "My_Key",
+            Value = "My value",
+            Description = "Some important variable",
+            Protected = true,
+            Type = VariableType.Variable,
+            Masked = false,
+            Raw = false,
+            EnvironmentScope = integrationScope,
+        });
+
+        Assert.That(changingScopeVariable.Key, Is.EqualTo("My_Key"));
+        Assert.That(changingScopeVariable.Value, Is.EqualTo("My value"));
+
+        if (context.IsGitLabVersionInRange(VersionRange.Parse("[16.2,)"), out _))
+        {
+            Assert.That(changingScopeVariable.Description, Is.EqualTo("Some important variable"));
+        }
+
+        Assert.That(changingScopeVariable.Protected, Is.EqualTo(true));
+        Assert.That(changingScopeVariable.Type, Is.EqualTo(VariableType.Variable));
+        Assert.That(changingScopeVariable.Masked, Is.EqualTo(false));
+        Assert.That(changingScopeVariable.Raw, Is.EqualTo(false));
+        Assert.That(changingScopeVariable.EnvironmentScope, Is.EqualTo(firstScope));
+
+        // Check single access with scoped variables
+        Assert.That(projectVariableClient[changingScopeVariable.Key, changingScopeVariable.EnvironmentScope], Is.Not.Null);
+
+        var exMultipleVariables = Assert.Throws<GitLabException>(() =>
+        {
+            var dummy = projectVariableClient[changingScopeVariable.Key];
+        });
+        Assert.That(exMultipleVariables?.ErrorMessage, Is.EqualTo("There are multiple variables with provided parameters. Please use 'filter[environment_scope]'"));
+
+        // Update
+        var newScope = "production/*";
+        changingScopeVariable = projectVariableClient.Update(changingScopeVariable.Key, changingScopeVariable.EnvironmentScope, new VariableUpdate
+        {
+            Value = "My value edited",
+            Protected = false,
+            EnvironmentScope = newScope,
+        });
+
+        Assert.That(changingScopeVariable.Key, Is.EqualTo("My_Key"));
+        Assert.That(changingScopeVariable.Value, Is.EqualTo("My value edited"));
+        Assert.That(changingScopeVariable.Protected, Is.EqualTo(false));
+        Assert.That(changingScopeVariable.EnvironmentScope, Is.EqualTo(newScope));
+
+        // Delete
+        var ex = Assert.Throws<GitLabException>(() => projectVariableClient.Delete(changingScopeVariable.Key, "wrongScope"));
+        Assert.That(ex!.StatusCode == HttpStatusCode.NotFound);
+
+        projectVariableClient.Delete(changingScopeVariable.Key, newScope);
+        projectVariableClient.Delete(integrationVariable.Key, integrationScope);
+
+        var variables = projectVariableClient.All.ToList();
+        Assert.That(variables, Is.Empty);
+
+        // All
+        projectVariableClient.Create(new VariableCreate { Key = "Variable1", Value = "test", EnvironmentScope = "test/*" });
+        projectVariableClient.Create(new VariableCreate { Key = "Variable2", Value = "test", EnvironmentScope = "integration" });
+        projectVariableClient.Create(new VariableCreate { Key = "Variable3", Value = "test", EnvironmentScope = "*" });
+        variables = projectVariableClient.All.ToList();
+        Assert.That(variables, Has.Count.EqualTo(3));
+    }
 }
diff --git a/NGitLab/IProjectBadgeClient.cs b/NGitLab/IProjectBadgeClient.cs
index 4402fe30..17b26324 100644
--- a/NGitLab/IProjectBadgeClient.cs
+++ b/NGitLab/IProjectBadgeClient.cs
@@ -28,11 +28,17 @@ public interface IProjectVariableClient
 
     Variable this[string key] { get; }
 
+    Variable this[string key, string environmentScope] { get; }
+
     Variable Create(VariableCreate model);
 
     Variable Update(string key, VariableUpdate model);
 
+    Variable Update(string key, string environmentScope, VariableUpdate model);
+
     void Delete(string key);
+
+    void Delete(string key, string environmentScope);
 }
 
 public interface IGroupVariableClient
@@ -41,9 +47,15 @@ public interface IGroupVariableClient
 
     Variable this[string key] { get; }
 
+    Variable this[string key, string environmentScope] { get; }
+
     Variable Create(VariableCreate model);
 
     Variable Update(string key, VariableUpdate model);
 
+    Variable Update(string key, string environmentScope, VariableUpdate model);
+
     void Delete(string key);
+
+    void Delete(string key, string environmentScope);
 }
diff --git a/NGitLab/Impl/VariableClient.cs b/NGitLab/Impl/VariableClient.cs
index 12fce92a..0751c443 100644
--- a/NGitLab/Impl/VariableClient.cs
+++ b/NGitLab/Impl/VariableClient.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using NGitLab.Models;
 
 namespace NGitLab.Impl;
@@ -8,6 +9,8 @@ internal abstract class VariableClient
     private readonly string _urlPrefix;
     private readonly API _api;
 
+    private string EnvironmentScopeFilter(string environmentScope = null) => !string.IsNullOrWhiteSpace(environmentScope) ? $"?filter[environment_scope]={Uri.EscapeDataString(environmentScope)}" : string.Empty;
+
     protected VariableClient(API api, string urlPrefix)
     {
         _urlPrefix = urlPrefix;
@@ -16,11 +19,17 @@ protected VariableClient(API api, string urlPrefix)
 
     public IEnumerable<Variable> All => _api.Get().GetAll<Variable>(_urlPrefix + "/variables");
 
-    public Variable this[string key] => _api.Get().To<Variable>(_urlPrefix + "/variables/" + key);
+    public Variable this[string key] => this[key, null];
+
+    public Variable this[string key, string environmentScope] => _api.Get().To<Variable>($"{_urlPrefix}/variables/{key}{EnvironmentScopeFilter(environmentScope)}");
 
     public Variable Create(VariableCreate model) => _api.Post().With(model).To<Variable>(_urlPrefix + "/variables");
 
-    public Variable Update(string key, VariableUpdate model) => _api.Put().With(model).To<Variable>(_urlPrefix + "/variables/" + key);
+    public Variable Update(string key, VariableUpdate model) => Update(key, null, model);
+
+    public Variable Update(string key, string environmentScope, VariableUpdate model) => _api.Put().With(model).To<Variable>($"{_urlPrefix}/variables/{key}{EnvironmentScopeFilter(environmentScope)}");
+
+    public void Delete(string key) => Delete(key, null);
 
-    public void Delete(string key) => _api.Delete().Execute(_urlPrefix + "/variables/" + key);
+    public void Delete(string key, string environmentScope) => _api.Delete().Execute($"{_urlPrefix}/variables/{key}{EnvironmentScopeFilter(environmentScope)}");
 }
diff --git a/NGitLab/Models/Variable.cs b/NGitLab/Models/Variable.cs
index b459e39c..a254dbc5 100644
--- a/NGitLab/Models/Variable.cs
+++ b/NGitLab/Models/Variable.cs
@@ -1,4 +1,5 @@
-using System.Text.Json.Serialization;
+using System.ComponentModel;
+using System.Text.Json.Serialization;
 
 namespace NGitLab.Models;
 
@@ -10,6 +11,14 @@ public class Variable
     [JsonPropertyName("value")]
     public string Value { get; set; }
 
+    /// <summary>
+    /// The description of a variable
+    /// </summary>
+    /// <returns>The description of a variable</returns>
+    /// <remarks>Introduced in GitLab 16.2</remarks>
+    [JsonPropertyName("description")]
+    public string Description { get; set; }
+
     [JsonPropertyName("protected")]
     public bool Protected { get; set; }
 
@@ -19,6 +28,23 @@ public class Variable
     [JsonPropertyName("masked")]
     public bool Masked { get; set; }
 
+    [JsonPropertyName("raw")]
+    public bool Raw { get; set; }
+
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public string Scope
+    {
+        get => EnvironmentScope;
+        set => EnvironmentScope = value;
+    }
+
+    /// <summary>
+    /// The environment scope of a variable
+    /// </summary>
+    /// <remarks>
+    /// Create and Update of project variable: All tiers (Free, Premium, Ultimate).<br/>
+    /// Create and Update of group variable: Premium and Ultimate only.
+    /// </remarks>
     [JsonPropertyName("environment_scope")]
-    public string Scope { get; set; }
+    public string EnvironmentScope { get; set; }
 }
diff --git a/NGitLab/Models/VariableCreate.cs b/NGitLab/Models/VariableCreate.cs
index dbe53e1b..c264d4b1 100644
--- a/NGitLab/Models/VariableCreate.cs
+++ b/NGitLab/Models/VariableCreate.cs
@@ -1,4 +1,5 @@
-using System.Text.Json.Serialization;
+using System.ComponentModel;
+using System.Text.Json.Serialization;
 
 namespace NGitLab.Models;
 
@@ -10,6 +11,33 @@ public class VariableCreate
     [JsonPropertyName("value")]
     public string Value;
 
+    /// <summary>
+    /// The description of a variable
+    /// </summary>
+    /// <returns>The description of a variable</returns>
+    /// <remarks>Introduced in GitLab 16.2</remarks>
+    [JsonPropertyName("description")]
+    public string Description;
+
     [JsonPropertyName("protected")]
     public bool Protected;
+
+    [JsonPropertyName("variable_type")]
+    public VariableType Type;
+
+    [JsonPropertyName("masked")]
+    public bool Masked;
+
+    [JsonPropertyName("raw")]
+    public bool Raw;
+
+    /// <summary>
+    /// The environment scope of a variable
+    /// </summary>
+    /// <remarks>
+    /// Create and Update of project variable: All tiers (Free, Premium, Ultimate).<br/>
+    /// Create and Update of group variable: Premium and Ultimate only.
+    /// </remarks>
+    [JsonPropertyName("environment_scope")]
+    public string EnvironmentScope;
 }
diff --git a/NGitLab/Models/VariableUpdate.cs b/NGitLab/Models/VariableUpdate.cs
index da5cd57a..a0a473e6 100644
--- a/NGitLab/Models/VariableUpdate.cs
+++ b/NGitLab/Models/VariableUpdate.cs
@@ -7,6 +7,33 @@ public class VariableUpdate
     [JsonPropertyName("value")]
     public string Value;
 
+    /// <summary>
+    /// The description of a variable
+    /// </summary>
+    /// <returns>The description of a variable</returns>
+    /// <remarks>Introduced in GitLab 16.2</remarks>
+    [JsonPropertyName("description")]
+    public string Description;
+
     [JsonPropertyName("protected")]
     public bool Protected;
+
+    [JsonPropertyName("variable_type")]
+    public VariableType Type;
+
+    [JsonPropertyName("masked")]
+    public bool Masked;
+
+    [JsonPropertyName("raw")]
+    public bool Raw;
+
+    /// <summary>
+    /// The environment scope of a variable
+    /// </summary>
+    /// <remarks>
+    /// Create and Update of project variable: All tiers (Free, Premium, Ultimate).<br/>
+    /// Create and Update of group variable: Premium and Ultimate only.
+    /// </remarks>
+    [JsonPropertyName("environment_scope")]
+    public string EnvironmentScope;
 }
diff --git a/NGitLab/PublicAPI.Unshipped.txt b/NGitLab/PublicAPI.Unshipped.txt
index a647d2f6..6a16a65a 100644
--- a/NGitLab/PublicAPI.Unshipped.txt
+++ b/NGitLab/PublicAPI.Unshipped.txt
@@ -306,8 +306,11 @@ NGitLab.IGroupVariableClient
 NGitLab.IGroupVariableClient.All.get -> System.Collections.Generic.IEnumerable<NGitLab.Models.Variable>
 NGitLab.IGroupVariableClient.Create(NGitLab.Models.VariableCreate model) -> NGitLab.Models.Variable
 NGitLab.IGroupVariableClient.Delete(string key) -> void
+NGitLab.IGroupVariableClient.Delete(string key, string environmentScope) -> void
+NGitLab.IGroupVariableClient.this[string key, string environmentScope].get -> NGitLab.Models.Variable
 NGitLab.IGroupVariableClient.this[string key].get -> NGitLab.Models.Variable
 NGitLab.IGroupVariableClient.Update(string key, NGitLab.Models.VariableUpdate model) -> NGitLab.Models.Variable
+NGitLab.IGroupVariableClient.Update(string key, string environmentScope, NGitLab.Models.VariableUpdate model) -> NGitLab.Models.Variable
 NGitLab.IHttpRequestor
 NGitLab.IHttpRequestor.Execute(string tailAPIUrl) -> void
 NGitLab.IHttpRequestor.ExecuteAsync(string tailAPIUrl, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task
@@ -1075,8 +1078,11 @@ NGitLab.IProjectVariableClient
 NGitLab.IProjectVariableClient.All.get -> System.Collections.Generic.IEnumerable<NGitLab.Models.Variable>
 NGitLab.IProjectVariableClient.Create(NGitLab.Models.VariableCreate model) -> NGitLab.Models.Variable
 NGitLab.IProjectVariableClient.Delete(string key) -> void
+NGitLab.IProjectVariableClient.Delete(string key, string environmentScope) -> void
+NGitLab.IProjectVariableClient.this[string key, string environmentScope].get -> NGitLab.Models.Variable
 NGitLab.IProjectVariableClient.this[string key].get -> NGitLab.Models.Variable
 NGitLab.IProjectVariableClient.Update(string key, NGitLab.Models.VariableUpdate model) -> NGitLab.Models.Variable
+NGitLab.IProjectVariableClient.Update(string key, string environmentScope, NGitLab.Models.VariableUpdate model) -> NGitLab.Models.Variable
 NGitLab.IProtectedBranchClient
 NGitLab.IProtectedBranchClient.GetProtectedBranch(string branchName) -> NGitLab.Models.ProtectedBranch
 NGitLab.IProtectedBranchClient.GetProtectedBranches(string search = null) -> NGitLab.Models.ProtectedBranch[]
@@ -3911,12 +3917,18 @@ NGitLab.Models.UserUpsert.Username -> string
 NGitLab.Models.UserUpsert.UserUpsert() -> void
 NGitLab.Models.UserUpsert.WebsiteURL -> string
 NGitLab.Models.Variable
+NGitLab.Models.Variable.Description.get -> string
+NGitLab.Models.Variable.Description.set -> void
 NGitLab.Models.Variable.Key.get -> string
 NGitLab.Models.Variable.Key.set -> void
 NGitLab.Models.Variable.Masked.get -> bool
 NGitLab.Models.Variable.Masked.set -> void
 NGitLab.Models.Variable.Protected.get -> bool
 NGitLab.Models.Variable.Protected.set -> void
+NGitLab.Models.Variable.Raw.get -> bool
+NGitLab.Models.Variable.Raw.set -> void
+NGitLab.Models.Variable.EnvironmentScope.get -> string
+NGitLab.Models.Variable.EnvironmentScope.set -> void
 NGitLab.Models.Variable.Scope.get -> string
 NGitLab.Models.Variable.Scope.set -> void
 NGitLab.Models.Variable.Type.get -> NGitLab.Models.VariableType
@@ -3925,15 +3937,25 @@ NGitLab.Models.Variable.Value.get -> string
 NGitLab.Models.Variable.Value.set -> void
 NGitLab.Models.Variable.Variable() -> void
 NGitLab.Models.VariableCreate
+NGitLab.Models.VariableCreate.Description -> string
+NGitLab.Models.VariableCreate.EnvironmentScope -> string
 NGitLab.Models.VariableCreate.Key -> string
+NGitLab.Models.VariableCreate.Masked -> bool
 NGitLab.Models.VariableCreate.Protected -> bool
+NGitLab.Models.VariableCreate.Raw -> bool
+NGitLab.Models.VariableCreate.Type -> NGitLab.Models.VariableType
 NGitLab.Models.VariableCreate.Value -> string
 NGitLab.Models.VariableCreate.VariableCreate() -> void
 NGitLab.Models.VariableType
 NGitLab.Models.VariableType.File = 1 -> NGitLab.Models.VariableType
 NGitLab.Models.VariableType.Variable = 0 -> NGitLab.Models.VariableType
 NGitLab.Models.VariableUpdate
+NGitLab.Models.VariableUpdate.Description -> string
+NGitLab.Models.VariableUpdate.EnvironmentScope -> string
+NGitLab.Models.VariableUpdate.Masked -> bool
 NGitLab.Models.VariableUpdate.Protected -> bool
+NGitLab.Models.VariableUpdate.Raw -> bool
+NGitLab.Models.VariableUpdate.Type -> NGitLab.Models.VariableType
 NGitLab.Models.VariableUpdate.Value -> string
 NGitLab.Models.VariableUpdate.VariableUpdate() -> void
 NGitLab.Models.VisibilityLevel