diff --git a/src/InternshipSystem.Api/ApiProfile.cs b/src/InternshipSystem.Api/ApiProfile.cs
index efbe56d..729a8ba 100644
--- a/src/InternshipSystem.Api/ApiProfile.cs
+++ b/src/InternshipSystem.Api/ApiProfile.cs
@@ -21,7 +21,7 @@ namespace InternshipSystem.Api
 
             CreateMap<Edition, EditionManagementResult>();
 
-            CreateMap<Edition, EditionFullResult>();
+            CreateMap<Edition, EditionDetailsResult>();
             
             CreateMap<Edition, EditionConfigurationResult>();
 
diff --git a/src/InternshipSystem.Api/Controllers/EditionManagementController.cs b/src/InternshipSystem.Api/Controllers/EditionManagementController.cs
index 71cecc2..d56543b 100644
--- a/src/InternshipSystem.Api/Controllers/EditionManagementController.cs
+++ b/src/InternshipSystem.Api/Controllers/EditionManagementController.cs
@@ -5,9 +5,11 @@ using System.Threading;
 using System.Threading.Tasks;
 using AutoMapper;
 using AutoMapper.QueryableExtensions;
+using InternshipSystem.Api.Queries;
 using InternshipSystem.Api.Queries.SearchQuery;
 using InternshipSystem.Api.Result;
 using InternshipSystem.Api.Security;
+using InternshipSystem.Core;
 using InternshipSystem.Repository;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Http;
@@ -46,7 +48,7 @@ namespace InternshipSystem.Api.Controllers
         [ProducesResponseType(StatusCodes.Status401Unauthorized)]
         [ProducesResponseType(StatusCodes.Status404NotFound)]
         [Authorize(Policy = Policies.IsOverseer)]
-        public async Task<ActionResult<EditionFullResult>> GetFullEdition(CancellationToken token)
+        public async Task<ActionResult<EditionDetailsResult>> GetFullEdition(Guid editionId, CancellationToken token)
         {
             var edition = await Context.Editions
                 .Include(e => e.Course)
@@ -54,7 +56,8 @@ namespace InternshipSystem.Api.Controllers
                     .ThenInclude(s => s.Subject)
                 .Include(e => e.AvailableInternshipTypes)
                     .ThenInclude(i => i.InternshipType)
-                .ProjectTo<EditionFullResult>(Mapper.ConfigurationProvider)
+                .Where(e => e.Id == editionId)
+                .ProjectTo<EditionDetailsResult>(Mapper.ConfigurationProvider)
                 .FirstOrDefaultAsync(token);
 
             if (edition == null)
@@ -68,22 +71,58 @@ namespace InternshipSystem.Api.Controllers
         [HttpPut]
         [ProducesResponseType(StatusCodes.Status200OK)]
         [ProducesResponseType(StatusCodes.Status400BadRequest)]
+        [ProducesResponseType(StatusCodes.Status400BadRequest)]
         [ProducesResponseType(StatusCodes.Status401Unauthorized)]
         [ProducesResponseType(StatusCodes.Status404NotFound)]
         [Authorize(Policy = Policies.IsOverseer)]
         public async Task<ActionResult> UpsertEdition(EditionForm editionForm, CancellationToken token)
         {
             var validator = new EditionForm.Validator();
-            // TODO: complete validation rules
             var validationResult = await validator.ValidateAsync(editionForm, token);
-
+    
             if (!validationResult.IsValid)
             {
                 return BadRequest(validationResult.ToString());
             }
-            
-            // TODO: complete add/update
 
+            //TODO: resolve courses (one for each edition or dictionary)
+            editionForm.Course.Id = 0;
+            
+            if (editionForm.Id.HasValue)
+            {
+                var editionToUpdate = await Context.Editions
+                    .Include(e => e.AvailableSubjects)
+                    .Include(e => e.AvailableInternshipTypes)
+                    .FirstOrDefaultAsync(e => e.Id == editionForm.Id.Value, token);
+
+                if (editionToUpdate == null)
+                {
+                    return NotFound();
+                }
+                
+                editionToUpdate.UpdateEdition(editionForm.EditionStart, editionForm.EditionFinish, editionForm.ReportingStart,
+                    editionForm.Course, editionForm.AvailableSubjectsIds, editionForm.AvailableInternshipTypesIds);
+                
+                if (!editionToUpdate.IsValidDates)
+                {
+                    return BadRequest();
+                }
+            }
+            else
+            {
+                var newEdition = 
+                    Edition.CreateEdition(editionForm.EditionStart.Value, editionForm.EditionFinish.Value, editionForm.ReportingStart.Value,
+                        editionForm.Course, editionForm.AvailableSubjectsIds, editionForm.AvailableInternshipTypesIds);
+                
+                if (!newEdition.IsValidDates)
+                {
+                    return BadRequest();
+                }
+                
+                await Context.Editions.AddAsync(newEdition, token);
+            }
+
+            await Context.SaveChangesAsync(token);
             return Ok();
         }
         
diff --git a/src/InternshipSystem.Api/Queries/EditionForm.cs b/src/InternshipSystem.Api/Queries/EditionForm.cs
index 3b41aac..6c30d3e 100644
--- a/src/InternshipSystem.Api/Queries/EditionForm.cs
+++ b/src/InternshipSystem.Api/Queries/EditionForm.cs
@@ -4,23 +4,34 @@ using FluentValidation;
 using InternshipSystem.Core;
 using InternshipSystem.Core.Entity.Internship;
 
-namespace InternshipSystem.Api.Controllers
+namespace InternshipSystem.Api.Queries
 {
     public class EditionForm
     {
-        public Guid Id { get; set; }
-        public DateTime EditionStart { get; set; }
-        public DateTime EditionFinish { get; set; }
-        public DateTime ReportingStart { get; set; }
+        public Guid? Id { get; set; }
+        public DateTime? EditionStart { get; set; }
+        public DateTime? EditionFinish { get; set; }
+        public DateTime? ReportingStart { get; set; }
         public Course Course { get; set; }
-        public List<InternshipSubject> AvailableSubjects { get; set; }
-        public List<InternshipType> AvailableInternshipTypes { get; set; }
+        public List<long> AvailableSubjectsIds { get; set; } = new List<long>();
+        public List<long> AvailableInternshipTypesIds { get; set; } = new List<long>();
         
         public class Validator : AbstractValidator<EditionForm>
         {
             public Validator()
             {
-                //TODO: later
+                RuleFor(e => e.Id).NotNull()
+                    .When(e => !e.EditionStart.HasValue || !e.EditionFinish.HasValue
+                                                        || !e.ReportingStart.HasValue || e.Course == null);
+                
+                RuleFor(e => e.EditionStart).NotEmpty()
+                    .When(e => !e.Id.HasValue);
+                RuleFor(e => e.EditionFinish).NotEmpty()
+                    .When(e => !e.Id.HasValue);
+                RuleFor(e => e.ReportingStart).NotEmpty()
+                    .When(e => !e.Id.HasValue);
+                RuleFor(e => e.Course).NotNull()
+                    .When(e => !e.Id.HasValue);
             }
         }
     }
diff --git a/src/InternshipSystem.Api/Result/EditionFullResult.cs b/src/InternshipSystem.Api/Result/EditionDetailsResult.cs
similarity index 93%
rename from src/InternshipSystem.Api/Result/EditionFullResult.cs
rename to src/InternshipSystem.Api/Result/EditionDetailsResult.cs
index 57c9e29..19754bd 100644
--- a/src/InternshipSystem.Api/Result/EditionFullResult.cs
+++ b/src/InternshipSystem.Api/Result/EditionDetailsResult.cs
@@ -5,7 +5,7 @@ using InternshipSystem.Core.Entity.Internship;
 
 namespace InternshipSystem.Api.Result
 {
-    public class EditionFullResult
+    public class EditionDetailsResult
     {
         public Guid Id { get; set; }
         public DateTime EditionStart { get; set; }
diff --git a/src/InternshipSystem.Core/Entity/Edition.cs b/src/InternshipSystem.Core/Entity/Edition.cs
index c22eb53..567693f 100644
--- a/src/InternshipSystem.Core/Entity/Edition.cs
+++ b/src/InternshipSystem.Core/Entity/Edition.cs
@@ -18,17 +18,77 @@ namespace InternshipSystem.Core
         public List<EditionInternshipType> AvailableInternshipTypes { get; set; }
 
         public bool IsOpen => EditionFinish < DateTime.Today;
-        
-        public Edition CreateEdition(DateTime start, DateTime end, DateTime reportingStart)
+
+        public static Edition CreateEdition(DateTime start, DateTime end, DateTime reportingStart, Course course,
+            IEnumerable<long> subjectsIds, IEnumerable<long> internshipTypesIds)
+        {
+            var newEdition = CreateEdition(start, end, reportingStart, course);
+
+            newEdition.AvailableSubjects =
+                subjectsIds
+                    .Select(s => new EditionSubject
+                    {
+                        Edition = newEdition,
+                        InternshipSubjectId = s,
+                    })
+                    .ToList();
+
+            newEdition.AvailableInternshipTypes =
+                internshipTypesIds
+                    .Select(i => new EditionInternshipType
+                    {
+                        Edition = newEdition,
+                        InternshipTypeId = i,
+                    })
+                    .ToList();
+
+            return newEdition;
+        }
+            
+        public static Edition CreateEdition(DateTime start, DateTime end, DateTime reportingStart, Course course)
         {
             return new Edition
             {
                 EditionStart = start,
                 EditionFinish = end,
-                ReportingStart = reportingStart
+                ReportingStart = reportingStart,
+                Course = course,
+                AvailableSubjects = new List<EditionSubject>(),
+                AvailableInternshipTypes = new List<EditionInternshipType>(),
             };
         }
 
+        public void UpdateEdition(DateTime? start, DateTime? end, DateTime? reportingStart, Course course,
+            IEnumerable<long> subjectsIds, IEnumerable<long> internshipTypesIds)
+        {
+            EditionStart = start ?? EditionStart;
+            EditionFinish = end ?? EditionFinish;
+            ReportingStart = reportingStart ?? ReportingStart;
+            Course = course;
+
+            if (subjectsIds != null)
+            {
+                AvailableSubjects =
+                    subjectsIds
+                        .Select(s => new EditionSubject
+                        {
+                            InternshipSubjectId = s,
+                        })
+                        .ToList();
+            }
+
+            if (internshipTypesIds != null)
+            {
+                AvailableInternshipTypes =
+                    internshipTypesIds
+                        .Select(i => new EditionInternshipType
+                        {
+                            InternshipTypeId = i,
+                        })
+                        .ToList();
+            }
+        }
+
         public void RegisterInternship(Student student)
         {
             if (Internships.Any(i => i.Student.Id == student.Id))
@@ -55,5 +115,7 @@ namespace InternshipSystem.Core
         {
             return internshipSubjects.All(s => AvailableSubjects.Any(su => su.InternshipSubjectId == s));
         }
+
+        public bool IsValidDates => EditionStart <= EditionFinish;
     }
 }
\ No newline at end of file