diff --git a/services/Directory/FilterLists.Directory.Api/Controllers/ChangesController.cs b/services/Directory/FilterLists.Directory.Api/Controllers/ChangesController.cs
new file mode 100644
index 000000000..5601994e0
--- /dev/null
+++ b/services/Directory/FilterLists.Directory.Api/Controllers/ChangesController.cs
@@ -0,0 +1,29 @@
+using FilterLists.Directory.Application.Queries;
+using MediatR;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Caching.Memory;
+
+namespace FilterLists.Directory.Api.Controllers;
+
+public class ChangesController : BaseController
+{
+ private readonly IMediator _mediator;
+
+ public ChangesController(IMemoryCache cache, IMediator mediator) : base(cache)
+ {
+ _mediator = mediator;
+ }
+
+ ///
+ /// Gets the changes.
+ ///
+ /// The cancellation token.
+ /// The changes.
+ [HttpGet]
+ //[ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)]
+ public async Task Get(CancellationToken cancellationToken)
+ {
+ return Ok(await _mediator.Send(new GetChanges.Query(), cancellationToken));
+ //return CacheGetOrCreateAsync(() => _mediator.Send(new GetChanges.Query(), cancellationToken));
+ }
+}
diff --git a/services/Directory/FilterLists.Directory.Application/Queries/GetChanges.cs b/services/Directory/FilterLists.Directory.Application/Queries/GetChanges.cs
new file mode 100644
index 000000000..a5c3e293e
--- /dev/null
+++ b/services/Directory/FilterLists.Directory.Application/Queries/GetChanges.cs
@@ -0,0 +1,71 @@
+using System.Text.Json;
+using AutoMapper;
+using AutoMapper.QueryableExtensions;
+using FilterLists.Directory.Domain.Aggregates;
+using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
+using FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
+using MediatR;
+using Microsoft.EntityFrameworkCore;
+
+namespace FilterLists.Directory.Application.Queries;
+
+public static class GetChanges
+{
+ public record Query : IRequest>;
+
+ internal class Handler : IRequestHandler>
+ {
+ private readonly IQueryContext _context;
+ private readonly IMapper _mapper;
+
+ public Handler(IQueryContext context, IMapper mapper)
+ {
+ _context = context;
+ _mapper = mapper;
+ }
+
+ public Task> Handle(Query request, CancellationToken cancellationToken)
+ {
+ return _context.Changes
+ .Where(c => c.ApprovedAt == null && c.RejectedAt == null)
+ .OrderBy(c => c.SubmittedAt)
+ .ProjectTo(_mapper.ConfigurationProvider)
+ .ToListAsync(cancellationToken);
+ }
+ }
+
+ internal class ChangesVmProfile : Profile
+ {
+ public ChangesVmProfile()
+ {
+ CreateMap();
+ }
+ }
+
+ public record ChangesVm
+ {
+ public int Id { get; private init; }
+ public string? Reason { get; private init; }
+ public DateTime SubmittedAt { get; private init; }
+ public DateTime? ApprovedAt { get; private init; }
+ public DateTime? RejectedAt { get; private init; }
+ public string? RejectedReason { get; private init; }
+ public JsonDocument? Before { get; private init; }
+ public JsonDocument? After { get; private init; }
+ public AggregateType AggregateType { get; private init; }
+ public int? FilterListId { get; private init; }
+ public FilterList? FilterList { get; }
+ public string? LanguageIso6391 { get; private init; }
+ public Language? Language { get; }
+ public int? LicenseId { get; private init; }
+ public License? License { get; }
+ public int? MaintainerId { get; private init; }
+ public Maintainer? Maintainer { get; }
+ public int? SoftwareId { get; private init; }
+ public Software? Software { get; }
+ public int? SyntaxId { get; private init; }
+ public Syntax? Syntax { get; }
+ public int? TagId { get; private init; }
+ public Tag? Tag { get; }
+ }
+}