diff --git a/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRCodeSystemVersion.java b/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRCodeSystemVersion.java
index 8116ee9f3..c39658de6 100644
--- a/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRCodeSystemVersion.java
+++ b/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRCodeSystemVersion.java
@@ -3,6 +3,7 @@
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import org.hl7.fhir.r4.model.CodeSystem;
 import org.hl7.fhir.r4.model.Enumerations;
+import org.hl7.fhir.r4.model.Extension;
 import org.joda.time.DateTime;
 import org.joda.time.format.DateTimeFormat;
 import org.joda.time.format.DateTimeFormatter;
@@ -16,6 +17,7 @@
 import org.springframework.data.elasticsearch.annotations.*;
 
 import java.util.Date;
+import java.util.List;
 
 import static org.snomed.snowstorm.fhir.config.FHIRConstants.*;
 
@@ -31,6 +33,9 @@ public class FHIRCodeSystemVersion {
 	@Field(type = FieldType.Keyword)
 	private String version;
 
+	@Field(type = FieldType.Keyword)
+	private String language;
+
 	@Field(type = FieldType.Date, format = DateFormat.date_time)
 	private Date date;
 
@@ -55,6 +60,9 @@ public class FHIRCodeSystemVersion {
 	@Field(type = FieldType.Keyword)
 	private String content;
 
+	@Field(type = FieldType.Nested)
+	private List<Extension> extensions;
+
 	@Transient
 	private String snomedBranch;
 
@@ -84,6 +92,7 @@ public FHIRCodeSystemVersion(CodeSystem codeSystem) {
 		version = codeSystem.getVersion();
 		date = codeSystem.getDate();
 		title = codeSystem.getTitle();
+		language = codeSystem.getLanguage();
 		if (title != null) {
 			title = title.replace(" Code System", "");
 		}
@@ -96,6 +105,7 @@ public FHIRCodeSystemVersion(CodeSystem codeSystem) {
 		compositional = codeSystem.getCompositional();
 		CodeSystem.CodeSystemContentMode codeSystemContent = codeSystem.getContent();
 		content = codeSystemContent != null ? codeSystemContent.toCode() : null;
+		extensions = codeSystem.getExtension();
 	}
 
 	public FHIRCodeSystemVersion(CodeSystemVersion snomedVersion) {
@@ -144,9 +154,13 @@ public FHIRCodeSystemVersion(org.snomed.snowstorm.core.data.domain.CodeSystem sn
 
 	public CodeSystem toHapiCodeSystem() {
 		CodeSystem codeSystem = new CodeSystem();
+		codeSystem.setExtension(extensions);
 		codeSystem.setId(id);
 		codeSystem.setUrl(url);
-		codeSystem.setVersion(version);
+		if(!"0".equals(version)) {
+			codeSystem.setVersion(version);
+		}
+		codeSystem.setLanguage(language);
 		codeSystem.setDate(date);
 		codeSystem.setName(name);
 		codeSystem.setTitle(title);
@@ -181,7 +195,11 @@ public boolean isVersionMatch(String requestedVersion) {
 	}
 
 	public String getCanonical() {
-		return url + "|" + version;
+		if ("0".equals(version)){
+			return url;
+		} else {
+			return url + "|" + version;
+		}
 	}
 
 	public String getId() {
@@ -248,6 +266,14 @@ public void setPublisher(String publisher) {
 		this.publisher = publisher;
 	}
 
+	public List<Extension> getExtensions() {
+		return extensions;
+	}
+
+	public void setExtensions(List<Extension> extensions) {
+		this.extensions = extensions;
+	}
+
 	public String getHierarchyMeaning() {
 		return hierarchyMeaning;
 	}
@@ -291,4 +317,12 @@ public CodeSystemVersion getSnomedCodeSystemVersion() {
 	public String toString() {
 		return getId();
 	}
+
+	public String getLanguage() {
+		return language;
+	}
+
+	public void setLanguage(String language) {
+		this.language = language;
+	}
 }
diff --git a/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRConcept.java b/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRConcept.java
index 7ea2ec550..09ebd33ba 100644
--- a/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRConcept.java
+++ b/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRConcept.java
@@ -4,7 +4,7 @@
 import ca.uhn.fhir.jpa.entity.TermConceptDesignation;
 import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink;
 import ca.uhn.fhir.jpa.entity.TermConceptProperty;
-import org.hl7.fhir.r4.model.CodeSystem;
+import org.hl7.fhir.r4.model.*;
 import org.snomed.snowstorm.core.data.domain.ConceptMini;
 import org.snomed.snowstorm.core.data.domain.Description;
 import org.snomed.snowstorm.core.pojo.LanguageDialect;
@@ -24,6 +24,8 @@
 @Document(indexName = "#{@indexNameProvider.indexName('fhir-concept')}", createIndex = false)
 public class FHIRConcept implements FHIRGraphNode {
 
+	public static final String EXTENSION_MARKER = "://";
+
 	public interface Fields {
 
 		String CODE_SYSTEM_VERSION = "codeSystemVersion";
@@ -33,6 +35,7 @@ public interface Fields {
 		String PARENTS = "parents";
 		String ANCESTORS = "ancestors";
 		String PROPERTIES = "properties";
+		String EXTENSIONS = "extensions";
 	}
 	@Id
 	// Internal ID
@@ -62,6 +65,8 @@ public interface Fields {
 
 	private Map<String, List<FHIRProperty>> properties;
 
+	private Map<String, List<FHIRProperty>> extensions;
+
 	public FHIRConcept() {
 		active = true;
 	}
@@ -80,11 +85,17 @@ public FHIRConcept(TermConcept termConcept, FHIRCodeSystemVersion codeSystemVers
 		}
 
 		properties = new HashMap<>();
-		for (TermConceptProperty property : termConcept.getProperties()) {
+		for (TermConceptProperty property : termConcept.getProperties().stream().filter(p -> !p.getKey().contains(EXTENSION_MARKER)).toList()) {
 			properties.computeIfAbsent(property.getKey(), (i) -> new ArrayList<>())
 					.add(new FHIRProperty(property));
 		}
 
+		extensions = new HashMap<>();
+		for (TermConceptProperty extension : termConcept.getProperties().stream().filter(p -> p.getKey().contains(EXTENSION_MARKER)).toList()) {
+			extensions.computeIfAbsent(extension.getKey(), (i) -> new ArrayList<>())
+					.add(new FHIRProperty(extension));
+		}
+
 		parents = new HashSet<>();
 		for (TermConceptParentChildLink parent : termConcept.getParents()) {
 			parents.add(parent.getParent().getCode());
@@ -109,9 +120,37 @@ public FHIRConcept(CodeSystem.ConceptDefinitionComponent definitionConcept, FHIR
 		Optional.ofNullable(definitionConcept.getDefinition()).ifPresent(x -> properties.put("definition",Collections.singletonList(new FHIRProperty("definition",null,x,FHIRProperty.STRING))));
 		definitionConcept.getProperty().stream().filter(x-> x.getCode().equals("status") && x.getValueCodeType().getCode().equals("retired") ).findFirst().ifPresentOrElse(x -> active= false, ()->active =true);
 		properties.put("inactive",Collections.singletonList(new FHIRProperty("inactive",null,Boolean.toString(!isActive()),FHIRProperty.BOOLEAN)));
+		extensions = new HashMap<>();
+		definitionConcept.getExtension().forEach(
+				e ->{
+					Optional.ofNullable(extensions.get(e.getUrl())).ifPresentOrElse(list ->{
+						list.add(new FHIRProperty(e.getUrl(), null,e.getValue().primitiveValue(), FHIRProperty.typeToFHIRPropertyType(e.getValue())));
+
+					}, ()->{
+						List<FHIRProperty> list = new ArrayList<>();
+						list.add(new FHIRProperty(e.getUrl(), null,e.getValue().primitiveValue(), FHIRProperty.typeToFHIRPropertyType(e.getValue())));
+						extensions.put(e.getUrl(), list);
+					});
+
+				}
+		);
 		parents = new HashSet<>();
 		for (CodeSystem.ConceptPropertyComponent propertyComponent : definitionConcept.getProperty()) {
-			properties.computeIfAbsent(propertyComponent.getCode(), k -> new ArrayList<>()).add(new FHIRProperty(propertyComponent));
+			if (properties.get(propertyComponent.getCode())==null && !propertyComponent.getCode().contains(EXTENSION_MARKER)){
+				properties.put(propertyComponent.getCode(),new ArrayList<>());
+			}
+			try{
+				if(!propertyComponent.getCode().contains(EXTENSION_MARKER)){
+					properties.get(propertyComponent.getCode()).add(new FHIRProperty(propertyComponent));
+				}
+			} catch( UnsupportedOperationException e){
+				List<FHIRProperty> unmodifiableList = properties.get(propertyComponent.getCode());
+				List<FHIRProperty> modifiableList = new ArrayList<>();
+				modifiableList.addAll(unmodifiableList);
+				properties.put(propertyComponent.getCode(), modifiableList);
+				properties.get(propertyComponent.getCode()).add(new FHIRProperty(propertyComponent));
+			}
+
 			if (propertyComponent.getCode().equals("parent") || propertyComponent.getCode().equals("subsumedBy")) {
 				parents.add(propertyComponent.hasValueCoding() ? propertyComponent.getValueCoding().getCode() : propertyComponent.getValue().toString());
 			}
@@ -228,4 +267,12 @@ public Map<String, List<FHIRProperty>> getProperties() {
 	public void setProperties(Map<String, List<FHIRProperty>> properties) {
 		this.properties = properties;
 	}
+
+	public Map<String, List<FHIRProperty>> getExtensions() {
+		return extensions;
+	}
+
+	public void setExtensions(Map<String, List<FHIRProperty>> extensions) {
+		this.extensions = extensions;
+	}
 }
diff --git a/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRDesignation.java b/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRDesignation.java
index ffcf08098..58e212116 100644
--- a/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRDesignation.java
+++ b/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRDesignation.java
@@ -1,10 +1,17 @@
 package org.snomed.snowstorm.fhir.domain;
 
 import ca.uhn.fhir.jpa.entity.TermConceptDesignation;
+import org.apache.commons.lang3.StringUtils;
 import org.hl7.fhir.r4.model.CodeSystem;
 import org.hl7.fhir.r4.model.Coding;
+import org.hl7.fhir.r4.model.ValueSet;
 import org.snomed.snowstorm.core.data.domain.Description;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
 import static org.snomed.snowstorm.fhir.config.FHIRConstants.SNOMED_URI;
 
 public class FHIRDesignation {
@@ -13,6 +20,10 @@ public class FHIRDesignation {
 	private String use;
 	private String value;
 
+
+
+	private List<FHIRExtension> extensions;
+
 	public FHIRDesignation() {
 	}
 
@@ -43,6 +54,24 @@ public FHIRDesignation(CodeSystem.ConceptDefinitionDesignationComponent designat
 		language = designation.getLanguage();
 		value = designation.getValue();
 		setUse(designation.getUse());
+		designation.getExtension().forEach( ext -> {
+			if (extensions == null){
+				extensions = new ArrayList<>();
+			}
+			extensions.add(new FHIRExtension(ext));
+		});
+	}
+
+	public FHIRDesignation(ValueSet.ConceptReferenceDesignationComponent designation) {
+		language = designation.getLanguage();
+		value = designation.getValue();
+		setUse(designation.getUse());
+		designation.getExtension().forEach( ext -> {
+			if (extensions == null){
+				extensions = new ArrayList<>();
+			}
+			extensions.add(new FHIRExtension(ext));
+		});
 	}
 
 	public void setUse(Coding useCoding) {
@@ -50,7 +79,11 @@ public void setUse(Coding useCoding) {
 	}
 
 	public void setUse(String useSystem, String useCode) {
-		use = useSystem + "|" + useCode;
+		if(useSystem == null && useCode == null){
+			use = null;
+		} else {
+			use = useSystem + "|" + useCode;
+		}
 	}
 
 	public Coding getUseCoding() {
@@ -65,6 +98,17 @@ public Coding getUseCoding() {
 		return null;
 	}
 
+	public ValueSet.ConceptReferenceDesignationComponent getHapi() {
+		ValueSet.ConceptReferenceDesignationComponent hapiConceptReferenceDesignationComponent = new ValueSet.ConceptReferenceDesignationComponent();
+		hapiConceptReferenceDesignationComponent.setLanguage(language);
+		hapiConceptReferenceDesignationComponent.setValue(value);
+		if (StringUtils.isNotEmpty(use)) {
+			hapiConceptReferenceDesignationComponent.setUse(this.getUseCoding());
+		}
+		hapiConceptReferenceDesignationComponent.setExtension(Optional.ofNullable(extensions).orElse(Collections.emptyList()).stream().map(d->d.getHapi()).toList());
+		return hapiConceptReferenceDesignationComponent;
+	}
+
 	private static Coding addKnownDisplays(Coding coding) {
 		if (coding != null) {
 			if (SNOMED_URI.equals(coding.getSystem())) {
@@ -107,4 +151,12 @@ public String getValue() {
 	public void setValue(String value) {
 		this.value = value;
 	}
+
+	public List<FHIRExtension> getExtensions() {
+		return extensions;
+	}
+
+	public void setExtensions(List<FHIRExtension> extensions) {
+		this.extensions = extensions;
+	}
 }
diff --git a/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRExtension.java b/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRExtension.java
new file mode 100644
index 000000000..d798fb878
--- /dev/null
+++ b/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRExtension.java
@@ -0,0 +1,93 @@
+package org.snomed.snowstorm.fhir.domain;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.hl7.fhir.r4.model.*;
+import org.springframework.data.elasticsearch.annotations.Field;
+import org.springframework.data.elasticsearch.annotations.FieldType;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import static org.snomed.snowstorm.core.util.CollectionUtils.orEmpty;
+
+public class FHIRExtension {
+
+	@Field(type = FieldType.Keyword)
+	private String uri;
+	@Field(type = FieldType.Keyword)
+	private String value;
+	@Field(type = FieldType.Keyword)
+	private String type;
+
+	private List<FHIRExtension> extensions;
+
+	public FHIRExtension() {
+	}
+
+	public FHIRExtension(Extension hapiExtension) {
+		uri = hapiExtension.getUrl();
+		if (hapiExtension.getValue()!= null) {
+			value = hapiExtension.getValue().primitiveValue();
+			type = hapiExtension.getValue().fhirType();
+		} else {
+			hapiExtension.getExtension().forEach( extension -> {
+				if (extensions == null){
+					extensions = new ArrayList<>();
+				}
+				extensions.add(new FHIRExtension(extension));
+			});
+		}
+	}
+
+	@JsonIgnore
+	public Extension getHapi() {
+		Extension extension = new Extension();
+		extension.setUrl(uri);
+		Optional.ofNullable(getType(value, type))
+				.ifPresentOrElse(extension::setValue, () ->{
+					orEmpty(extensions).forEach( fhirExtension -> {
+						extension.addExtension(fhirExtension.getHapi());
+					});
+
+		});
+		return extension;
+	}
+	public static Type getType(String primitiveValue, String fhirType){
+		if (fhirType == null) return null;
+        return switch (fhirType) {
+            case "integer" -> new IntegerType(primitiveValue);
+            case "boolean" -> new BooleanType(primitiveValue);
+            case "string" -> new StringType(primitiveValue);
+            case "decimal" -> new DecimalType(primitiveValue);
+			case "id" -> new IdType(primitiveValue);
+			case "canonical" -> new CanonicalType(primitiveValue);
+			case "code" -> new CodeType(primitiveValue);
+            default -> null;
+        };
+    }
+
+	public String getUri() {
+		return uri;
+	}
+
+	public void setUri(String uri) {
+		this.uri = uri;
+	}
+
+	public String getValue() {
+		return value;
+	}
+
+	public void setValue(String value) {
+		this.value = value;
+	}
+
+	public List<FHIRExtension> getExtensions() {
+		return extensions;
+	}
+
+	public void setExtensions(List<FHIRExtension> extensions) {
+		this.extensions = extensions;
+	}
+}
diff --git a/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRProperty.java b/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRProperty.java
index 321b2c377..045cc9545 100644
--- a/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRProperty.java
+++ b/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRProperty.java
@@ -1,15 +1,23 @@
 package org.snomed.snowstorm.fhir.domain;
 
+import ca.uhn.fhir.jpa.cache.IResourceChangeListenerRegistry;
 import ca.uhn.fhir.jpa.entity.TermConceptProperty;
 import ca.uhn.fhir.jpa.entity.TermConceptPropertyTypeEnum;
 import org.hl7.fhir.r4.model.*;
 
+import java.util.Arrays;
+
 public class FHIRProperty {
 
 	public static final String STRING = "STRING";
 	public static final String CODING = "CODING";
 	public static final String CODE = "CODE";
 	public static final String BOOLEAN = "BOOLEAN";
+	public static final String INTEGER = "INTEGER";
+	public static final String DECIMAL = "DECIMAL";
+	public static final String[] URLS = {"http://hl7.org/fhir/StructureDefinition/itemWeight",
+			"http://hl7.org/fhir/StructureDefinition/codesystem-label",
+			"http://hl7.org/fhir/StructureDefinition/codesystem-conceptOrder"};
 
 	private String code;
 	private String display;
@@ -50,7 +58,33 @@ public FHIRProperty(CodeSystem.ConceptPropertyComponent propertyComponent) {
 		} else if (propertyComponent.hasValueBooleanType()){
 			value = propertyComponent.getValueBooleanType().getValueAsString();
 			type = BOOLEAN;
+		} else if (propertyComponent.hasValueIntegerType()){
+			value = propertyComponent.getValueIntegerType().getValueAsString();
+			type = INTEGER;
+		} else if (propertyComponent.hasValueDecimalType()){
+			value = propertyComponent.getValueDecimalType().getValueAsString();
+			type = DECIMAL;
+		}
+	}
+
+	static String typeToFHIRPropertyType(Type value) {
+		String fhirPropertyType;
+		if (value instanceof CodeType) {
+			fhirPropertyType = CODE;
+		} else if (value instanceof StringType){
+			fhirPropertyType = STRING;
+		} else if (value instanceof Coding) {
+			fhirPropertyType = CODING;
+		} else if (value instanceof BooleanType) {
+			fhirPropertyType = BOOLEAN;
+		} else if (value instanceof IntegerType) {
+			fhirPropertyType = INTEGER;
+		} else if (value instanceof DecimalType) {
+			fhirPropertyType = DECIMAL;
+		}else {
+			throw new RuntimeException("unknown FHIRProperty type");
 		}
+		return fhirPropertyType;
 	}
 
 	public Type toHapiValue(String systemVersionUrl) {
@@ -62,6 +96,10 @@ public Type toHapiValue(String systemVersionUrl) {
 			return new Coding(systemVersionUrl, value, display);
 		} else if (BOOLEAN.equals(type)) {
 			return new BooleanType(value);
+		} else if (INTEGER.equals(type)) {
+			return new IntegerType(value);
+		}else if (DECIMAL.equals(type)) {
+			return new DecimalType(value);
 		}
 		return null;
 	}
@@ -89,4 +127,8 @@ public String getValue() {
 	public void setValue(String value) {
 		this.value = value;
 	}
+
+	public boolean isSpecialExtension() {
+		return Arrays.asList(URLS).contains(code);
+	}
 }
diff --git a/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRValueSet.java b/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRValueSet.java
index 6ee66ed11..2da690e58 100644
--- a/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRValueSet.java
+++ b/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRValueSet.java
@@ -13,7 +13,9 @@
 import org.springframework.data.elasticsearch.annotations.Setting;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 
 import static org.snomed.snowstorm.core.util.CollectionUtils.orEmpty;
 
@@ -26,6 +28,9 @@ public class FHIRValueSet {
 	@Field(type = FieldType.Keyword)
 	private String url;
 
+	@Field(type = FieldType.Keyword)
+	private String language;
+
 	private List<FHIRIdentifier> identifier;
 
 	@Field(type = FieldType.Keyword)
@@ -58,6 +63,8 @@ public class FHIRValueSet {
 
 	private FHIRValueSetCompose compose;
 
+	private List<FHIRExtension> extensions;
+
 	public FHIRValueSet() {
 	}
 
@@ -71,6 +78,7 @@ public FHIRValueSet(ValueSet hapiValueSet) {
 			}
 			identifier.add(new FHIRIdentifier(hapiIdentifier));
 		}
+		language = hapiValueSet.getLanguage();
 		version = hapiValueSet.getVersion();
 		name = hapiValueSet.getName();
 		title = hapiValueSet.getTitle();
@@ -88,6 +96,15 @@ public FHIRValueSet(ValueSet hapiValueSet) {
 		copyright = hapiValueSet.getCopyright();
 
 		compose = new FHIRValueSetCompose(hapiValueSet.getCompose());
+
+		hapiValueSet.getExtension().forEach( e -> {
+			if(extensions == null){
+				extensions = new ArrayList<>();
+			}
+
+			extensions.add(new FHIRExtension(e));
+
+		});
 	}
 
 	@JsonIgnore
@@ -95,6 +112,7 @@ public ValueSet getHapi() {
 		ValueSet valueSet = new ValueSet();
 		valueSet.setId(id);
 		valueSet.setUrl(url);
+		valueSet.setLanguage(language);
 
 		for (FHIRIdentifier fhirIdentifier : orEmpty(getIdentifier())) {
 			valueSet.addIdentifier(fhirIdentifier.getHapi());
@@ -115,6 +133,10 @@ public ValueSet getHapi() {
 		valueSet.setCopyright(copyright);
 
 		valueSet.setCompose(compose.getHapi());
+
+		Optional.ofNullable(extensions).orElse(Collections.emptyList()).forEach( fe -> {
+			valueSet.addExtension(fe.getHapi());
+		});
 		return valueSet;
 	}
 
@@ -229,4 +251,20 @@ public FHIRValueSetCompose getCompose() {
 	public void setCompose(FHIRValueSetCompose compose) {
 		this.compose = compose;
 	}
+
+	public List<FHIRExtension> getExtensions() {
+		return extensions;
+	}
+
+	public void setExtensions(List<FHIRExtension> extensions) {
+		this.extensions = extensions;
+	}
+
+	public String getLanguage() {
+		return language;
+	}
+
+	public void setLanguage(String language) {
+		this.language = language;
+	}
 }
diff --git a/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRValueSetCompose.java b/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRValueSetCompose.java
index b6447fa33..f27501b51 100644
--- a/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRValueSetCompose.java
+++ b/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRValueSetCompose.java
@@ -12,6 +12,9 @@ public class FHIRValueSetCompose {
 	private List<FHIRValueSetCriteria> include;
 
 	private List<FHIRValueSetCriteria> exclude;
+
+	private List<FHIRExtension> extensions;
+
 	private Boolean inactive;
 
 	public FHIRValueSetCompose() {
@@ -30,6 +33,15 @@ public FHIRValueSetCompose(ValueSet.ValueSetComposeComponent hapiCompose) {
 		for (ValueSet.ConceptSetComponent hapiExclude : hapiCompose.getExclude()) {
 			addInclude(new FHIRValueSetCriteria(hapiExclude));
 		}
+
+		hapiCompose.getExtension().forEach( ext -> {
+			if (extensions == null){
+				extensions = new ArrayList<>();
+			}
+
+			extensions.add(new FHIRExtension(ext));
+
+		});
 	}
 
 	public ValueSet.ValueSetComposeComponent getHapi() {
@@ -43,6 +55,10 @@ public ValueSet.ValueSetComposeComponent getHapi() {
 		for (FHIRValueSetCriteria exclude : orEmpty(getExclude())) {
 			hapiCompose.addExclude(exclude.getHapi());
 		}
+
+		orEmpty(extensions).forEach( ext ->{
+			hapiCompose.addExtension(ext.getHapi());
+		});
 		return hapiCompose;
 	}
 
@@ -83,4 +99,13 @@ public void setInactive(Boolean inactive) {
 	public Boolean isInactive() {
 		return inactive;
 	}
+
+	public List<FHIRExtension> getExtensions() {
+		return extensions;
+	}
+
+	public void setExtensions(List<FHIRExtension> extensions) {
+		this.extensions = extensions;
+	}
+
 }
diff --git a/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRValueSetCriteria.java b/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRValueSetCriteria.java
index 3fe4851d1..a7f773678 100644
--- a/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRValueSetCriteria.java
+++ b/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRValueSetCriteria.java
@@ -6,7 +6,9 @@
 import org.springframework.data.elasticsearch.annotations.FieldType;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 import static org.snomed.snowstorm.core.util.CollectionUtils.orEmpty;
@@ -22,6 +24,8 @@ public class FHIRValueSetCriteria {
 	@Field(type = FieldType.Keyword)
 	private List<String> codes;
 
+	private List<FHIRValueSetCriteriaConcept> conceptReferences;
+
 	private List<FHIRValueSetFilter> filter;
 
 	private List<String> valueSet;
@@ -38,6 +42,13 @@ public FHIRValueSetCriteria(ValueSet.ConceptSetComponent hapiCriteria) {
 			}
 			codes.add(code.getCode());
 		}
+		hapiCriteria.getConcept().stream().forEach( c ->{
+			if (conceptReferences == null){
+				conceptReferences = new ArrayList<>();
+
+			}
+			conceptReferences.add(new FHIRValueSetCriteriaConcept(c));
+		});
 		for (ValueSet.ConceptSetFilterComponent hapiFilter : hapiCriteria.getFilter()) {
 			if (filter == null) {
 				filter = new ArrayList<>();
@@ -54,6 +65,12 @@ public ValueSet.ConceptSetComponent getHapi() {
 		for (String code : orEmpty(codes)) {
 			ValueSet.ConceptReferenceComponent component = new ValueSet.ConceptReferenceComponent();
 			component.setCode(code);
+			conceptReferences.stream().filter(x -> code.equals(x.getCode()))
+					.forEach(x -> {
+						Optional.ofNullable(x.getExtensions()).orElse(Collections.emptyList()).forEach(ext ->component.addExtension(ext.getHapi()));
+						Optional.ofNullable(x.getDesignations()).orElse(Collections.emptyList()).forEach(d ->component.addDesignation(d.getHapi()));
+					}
+				);
 			hapiConceptSet.addConcept(component);
 		}
 		for (FHIRValueSetFilter filter : orEmpty(getFilter())) {
diff --git a/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRValueSetCriteriaConcept.java b/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRValueSetCriteriaConcept.java
new file mode 100644
index 000000000..530541b01
--- /dev/null
+++ b/src/main/java/org/snomed/snowstorm/fhir/domain/FHIRValueSetCriteriaConcept.java
@@ -0,0 +1,82 @@
+package org.snomed.snowstorm.fhir.domain;
+
+import org.hl7.fhir.r4.model.CanonicalType;
+import org.hl7.fhir.r4.model.ValueSet;
+import org.springframework.data.elasticsearch.annotations.Field;
+import org.springframework.data.elasticsearch.annotations.FieldType;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import static org.snomed.snowstorm.core.util.CollectionUtils.orEmpty;
+
+public class FHIRValueSetCriteriaConcept {
+
+	@Field(type = FieldType.Keyword)
+	private String code;
+
+
+
+	private List<FHIRExtension> extensions;
+
+
+
+	private List<FHIRDesignation> designations;
+
+
+
+	public FHIRValueSetCriteriaConcept() {
+	}
+
+	public FHIRValueSetCriteriaConcept(ValueSet.ConceptReferenceComponent hapiConceptReferenceComponent) {
+		code = hapiConceptReferenceComponent.getCode();
+		hapiConceptReferenceComponent.getExtension().forEach( ext -> {
+			if (extensions == null){
+				extensions = new ArrayList<>();
+			}
+			extensions.add(new FHIRExtension(ext));
+		});
+		hapiConceptReferenceComponent.getDesignation().forEach( d -> {
+			if (designations == null){
+				designations = new ArrayList<>();
+			}
+			designations.add(new FHIRDesignation(d));
+		});
+	}
+
+	public ValueSet.ConceptReferenceComponent getHapi() {
+		ValueSet.ConceptReferenceComponent hapiConceptReferenceComponent = new ValueSet.ConceptReferenceComponent();
+		hapiConceptReferenceComponent.setCode(code);
+		hapiConceptReferenceComponent.setExtension(Optional.ofNullable(extensions).orElse(Collections.emptyList()).stream().map(e->e.getHapi()).toList());
+		hapiConceptReferenceComponent.setDesignation(Optional.ofNullable(designations).orElse(Collections.emptyList()).stream().map(d->d.getHapi()).toList());
+		return hapiConceptReferenceComponent;
+	}
+
+	public String getCode() {
+		return code;
+	}
+
+	public void setCode(String code) {
+		this.code = code;
+	}
+
+	public List<FHIRExtension> getExtensions() {
+		return extensions;
+	}
+
+	public void setExtensions(List<FHIRExtension> extensions) {
+		this.extensions = extensions;
+	}
+
+	public List<FHIRDesignation> getDesignations() {
+		return designations;
+	}
+
+	public void setDesignations(List<FHIRDesignation> designations) {
+		this.designations = designations;
+	}
+
+}
diff --git a/src/main/java/org/snomed/snowstorm/fhir/pojo/ValueSetExpansionParameters.java b/src/main/java/org/snomed/snowstorm/fhir/pojo/ValueSetExpansionParameters.java
index f746c4cfe..849723f67 100644
--- a/src/main/java/org/snomed/snowstorm/fhir/pojo/ValueSetExpansionParameters.java
+++ b/src/main/java/org/snomed/snowstorm/fhir/pojo/ValueSetExpansionParameters.java
@@ -38,16 +38,17 @@ public final class ValueSetExpansionParameters {
 	private final CanonicalUri forceSystemVersion;
 	private final String version;
 	private final ValueSet valueSet;
+	private final String property;
 
 	public ValueSetExpansionParameters(ValueSet valueSet, boolean includeDefinition1) {
 		this(null, valueSet, null, null, null, null, null, null, null, null, null,
-				null, includeDefinition1, null, null, null, null, null, null, null, null, null, null);
+				null, includeDefinition1, null, null, null, null, null, null, null, null, null, null, null);
 	}
 
 	public ValueSetExpansionParameters(String id, ValueSet valueSet, URI url, String valueSetVersion, String context, String contextDirection, String filter, String date,
 									   Integer offset, Integer count, Boolean includeDesignations, List<String> designations, Boolean includeDefinition, Boolean activeOnly,
 									   Boolean excludeNested, Boolean excludeNotForUI, Boolean excludePostCoordinated, String displayLanguage, CanonicalUri excludeSystem, CanonicalUri systemVersion,
-									   CanonicalUri checkSystemVersion, CanonicalUri forceSystemVersion, String version) {
+									   CanonicalUri checkSystemVersion, CanonicalUri forceSystemVersion, String version, String property) {
 
 		this.id = id;
 		this.url = url;
@@ -72,6 +73,7 @@ public ValueSetExpansionParameters(String id, ValueSet valueSet, URI url, String
 		this.forceSystemVersion = forceSystemVersion;
 		this.version = version;
 		this.valueSet = valueSet;
+		this.property = property;
 	}
 
 	public PageRequest getPageRequest(Sort sort) {
@@ -169,6 +171,10 @@ public CanonicalUri getForceSystemVersion() {
 		return forceSystemVersion;
 	}
 
+	public String getProperty(){
+		return property;
+	}
+
 	public String getVersion() {
 		return version;
 	}
diff --git a/src/main/java/org/snomed/snowstorm/fhir/services/FHIRCodeSystemService.java b/src/main/java/org/snomed/snowstorm/fhir/services/FHIRCodeSystemService.java
index 31a9caedb..2ab5465bb 100644
--- a/src/main/java/org/snomed/snowstorm/fhir/services/FHIRCodeSystemService.java
+++ b/src/main/java/org/snomed/snowstorm/fhir/services/FHIRCodeSystemService.java
@@ -1,6 +1,9 @@
 package org.snomed.snowstorm.fhir.services;
 
+import org.apache.commons.lang3.StringUtils;
+import org.hl7.fhir.r4.model.CanonicalType;
 import org.hl7.fhir.r4.model.CodeSystem;
+import org.hl7.fhir.r4.model.Extension;
 import org.hl7.fhir.r4.model.OperationOutcome;
 import org.ihtsdo.drools.helper.IdentifierHelper;
 import org.jetbrains.annotations.NotNull;
@@ -25,6 +28,7 @@
 import org.snomed.snowstorm.core.data.services.postcoordination.model.PostCoordinatedExpression;
 import org.snomed.snowstorm.core.pojo.LanguageDialect;
 import org.snomed.snowstorm.fhir.domain.FHIRCodeSystemVersion;
+import org.snomed.snowstorm.fhir.domain.FHIRConcept;
 import org.snomed.snowstorm.fhir.domain.SubsumesResult;
 import org.snomed.snowstorm.fhir.pojo.CanonicalUri;
 import org.snomed.snowstorm.fhir.pojo.ConceptAndSystemResult;
@@ -32,6 +36,7 @@
 import org.snomed.snowstorm.fhir.repositories.FHIRCodeSystemRepository;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
 import org.springframework.stereotype.Service;
 
@@ -44,6 +49,7 @@
 public class FHIRCodeSystemService {
 
 	public static final String SCT_ID_PREFIX = "sct_";
+	private static final int PAGESIZE = 1_000;
 
 	@Autowired
 	private FHIRCodeSystemRepository codeSystemRepository;
@@ -82,83 +88,7 @@ public FHIRCodeSystemVersion createUpdate(CodeSystem codeSystem) throws ServiceE
 		}
 
 		if (codeSystem.getContent() == CodeSystem.CodeSystemContentMode.SUPPLEMENT) {
-			// Attempt to process SNOMED CT code system supplement / expression repository
-
-			/*
-			 * Validation
-			 */
-			// if not SNOMED
-			if (!FHIRHelper.isSnomedUri(fhirCodeSystemVersion.getUrl())) {
-				throw exception("At this time this server only supports CodeSystem supplements that supplement SNOMED CT and contain postcoordinated expressions.",
-						OperationOutcome.IssueType.NOTSUPPORTED, 400);
-			}
-			// if no dependency
-			if (!codeSystem.hasSupplements()) {
-				throw exception("SNOMED CT CodeSystem supplements must declare which SNOMED CT edition and version they supplement " +
-						"using the 'supplements' property.", OperationOutcome.IssueType.INVARIANT, 400);
-			}
-			// Check dependency is SNOMED
-			FHIRCodeSystemVersionParams dependencyParams = FHIRHelper.getCodeSystemVersionParams(CanonicalUri.fromString(codeSystem.getSupplements()));
-			if (!dependencyParams.isSnomed() || dependencyParams.isUnversionedSnomed()
-					|| dependencyParams.isUnspecifiedReleasedSnomed() || dependencyParams.getVersion() == null) {
-				throw exception(format("The CodeSystem supplement must be a canonical URL with the SNOMED CT code system and a version using the SNOMED CT URI standard to " +
-								"quote a specific version of a specific edition. For example: http://snomed.info/sct|http://snomed.info/sct/900000000000207008/version/%s0131",
-						new GregorianCalendar().get(Calendar.YEAR)), OperationOutcome.IssueType.INVARIANT, 400);
-			}
-			// Check dependency exists
-			FHIRCodeSystemVersion dependantVersion = getSnomedVersionOrThrow(dependencyParams);
-
-			// Does the requested code system already exist?
-			FHIRCodeSystemVersionParams existingCodeSystemParams = FHIRHelper.getCodeSystemVersionParams(codeSystem.getUrl(), codeSystem.getVersion());
-			String snomedModule = existingCodeSystemParams.getSnomedModule();
-			if (!IdentifierHelper.isConceptId(snomedModule) || snomedModule.length() < 10) {// Long format concept identifier including namespace.
-				Long suggestedModuleConceptId = null;
-				if (snomedModule != null && snomedModule.length() == 7) {
-					// The module id is actually a SNOMED CT namespace... generate concept id that could be used
-					int namespace = Integer.parseInt(snomedModule);
-					try {
-						List<Long> conceptIds = identifierSource.reserveIds(namespace, IdentifierService.EXTENSION_CONCEPT_PARTITION_ID, 1);
-						if (!conceptIds.isEmpty()) {
-							suggestedModuleConceptId = conceptIds.get(0);
-						}
-					} catch (ServiceException e) {
-						logger.warn("Failed to generate a concept id using assumed namespace '{}'", namespace, e);
-					}
-				}
-				if (suggestedModuleConceptId != null) {
-					throw exception(format("The URL of this SNOMED CT CodeSystem supplement must have a version that follows the SNOMED CT URI standard and includes a module id." +
-											" If a namespace was given in the version URL then the module id '%s' could be used." +
-											" This id has been generated using the namespace given and is the next id sequence, considering all content currently loaded into Snowstorm.",
-									suggestedModuleConceptId),
-							OperationOutcome.IssueType.INVARIANT, 400);
-				} else {
-					throw exception("The URL of this SNOMED CT CodeSystem supplement must have a version that follows the SNOMED CT URI standard and includes a module id.",
-							OperationOutcome.IssueType.INVARIANT, 400);
-				}
-			}
-			org.snomed.snowstorm.core.data.domain.CodeSystem existingCodeSystem = snomedCodeSystemService.findByUriModule(snomedModule);
-			if (existingCodeSystem != null) {
-				throw exception("A code system supplement with the same URL and version already exists. Updating SNOMED CT code system supplements is not yet supported.",
-						OperationOutcome.IssueType.NOTSUPPORTED, 400);
-			}
-
-			org.snomed.snowstorm.core.data.domain.CodeSystem newCodeSystem = new org.snomed.snowstorm.core.data.domain.CodeSystem();
-			org.snomed.snowstorm.core.data.domain.CodeSystem dependentCodeSystem = dependantVersion.getSnomedCodeSystem();
-			String shortName = dependentCodeSystem.getShortName() + "-EXP";
-			newCodeSystem.setShortName(shortName);
-
-			// Append 2,3,4 etc to the short name to ensure uniqueness
-			int a = 2;
-			while (snomedCodeSystemService.find(newCodeSystem.getShortName()) != null) {
-				newCodeSystem.setShortName(shortName + a);
-				a++;
-			}
-			newCodeSystem.setName("SNOMED CT Postcoordinated Expression Repository");
-			newCodeSystem.setBranchPath(String.join("/", dependentCodeSystem.getBranchPath(), newCodeSystem.getShortName()));
-			newCodeSystem.setUriModuleId(snomedModule);
-			newCodeSystem.setMaximumPostcoordinationLevel(maxPostcoordinationLevel);
-			org.snomed.snowstorm.core.data.domain.CodeSystem savedCodeSystem = snomedCodeSystemService.createCodeSystem(newCodeSystem);
-			return new FHIRCodeSystemVersion(savedCodeSystem);
+			return handleSupplement(codeSystem, fhirCodeSystemVersion);
 
 		} else {// Not Supplement
 
@@ -196,6 +126,211 @@ public FHIRCodeSystemVersion createUpdate(CodeSystem codeSystem) throws ServiceE
 		}
 	}
 
+	private @NotNull FHIRCodeSystemVersion handleSupplement(CodeSystem codeSystem, FHIRCodeSystemVersion fhirCodeSystemVersion) throws ServiceException {
+		// Attempt to process SNOMED CT code system supplement / expression repository
+
+		/*
+		 * Validation
+		 */
+		// if not SNOMED
+		if (!FHIRHelper.isSnomedUri(fhirCodeSystemVersion.getUrl())) {
+			return handleNotSnomedSupplement(codeSystem);
+		}
+
+		return handleSnomedSupplement(codeSystem);
+	}
+
+	private @NotNull FHIRCodeSystemVersion handleSnomedSupplement(CodeSystem codeSystem) throws ServiceException {
+		// if no dependency
+		if (!codeSystem.hasSupplements()) {
+			throw exception("SNOMED CT CodeSystem supplements must declare which SNOMED CT edition and version they supplement " +
+					"using the 'supplements' property.", OperationOutcome.IssueType.INVARIANT, 400);
+		}
+		// Check dependency is SNOMED
+		FHIRCodeSystemVersionParams dependencyParams = FHIRHelper.getCodeSystemVersionParams(CanonicalUri.fromString(codeSystem.getSupplements()));
+		if (!dependencyParams.isSnomed() || dependencyParams.isUnversionedSnomed()
+				|| dependencyParams.isUnspecifiedReleasedSnomed() || dependencyParams.getVersion() == null) {
+			throw exception(format("The CodeSystem supplement must be a canonical URL with the SNOMED CT code system and a version using the SNOMED CT URI standard to " +
+							"quote a specific version of a specific edition. For example: http://snomed.info/sct|http://snomed.info/sct/900000000000207008/version/%s0131",
+					new GregorianCalendar().get(Calendar.YEAR)), OperationOutcome.IssueType.INVARIANT, 400);
+		}
+		// Check dependency exists
+		FHIRCodeSystemVersion dependantVersion = getSnomedVersionOrThrow(dependencyParams);
+
+		// Does the requested code system already exist?
+		FHIRCodeSystemVersionParams existingCodeSystemParams = FHIRHelper.getCodeSystemVersionParams(codeSystem.getUrl(), codeSystem.getVersion());
+		String snomedModule = existingCodeSystemParams.getSnomedModule();
+		if (!IdentifierHelper.isConceptId(snomedModule) || snomedModule.length() < 10) {// Long format concept identifier including namespace.
+			Long suggestedModuleConceptId = null;
+			if (snomedModule != null && snomedModule.length() == 7) {
+				// The module id is actually a SNOMED CT namespace... generate concept id that could be used
+				int namespace = Integer.parseInt(snomedModule);
+				try {
+					List<Long> conceptIds = identifierSource.reserveIds(namespace, IdentifierService.EXTENSION_CONCEPT_PARTITION_ID, 1);
+					if (!conceptIds.isEmpty()) {
+						suggestedModuleConceptId = conceptIds.get(0);
+					}
+				} catch (ServiceException e) {
+					logger.warn("Failed to generate a concept id using assumed namespace '{}'", namespace, e);
+				}
+			}
+			if (suggestedModuleConceptId != null) {
+				throw exception(format("The URL of this SNOMED CT CodeSystem supplement must have a version that follows the SNOMED CT URI standard and includes a module id." +
+										" If a namespace was given in the version URL then the module id '%s' could be used." +
+										" This id has been generated using the namespace given and is the next id sequence, considering all content currently loaded into Snowstorm.",
+								suggestedModuleConceptId),
+						OperationOutcome.IssueType.INVARIANT, 400);
+			} else {
+				throw exception("The URL of this SNOMED CT CodeSystem supplement must have a version that follows the SNOMED CT URI standard and includes a module id.",
+						OperationOutcome.IssueType.INVARIANT, 400);
+			}
+		}
+		org.snomed.snowstorm.core.data.domain.CodeSystem existingCodeSystem = snomedCodeSystemService.findByUriModule(snomedModule);
+		if (existingCodeSystem != null) {
+			throw exception("A code system supplement with the same URL and version already exists. Updating SNOMED CT code system supplements is not yet supported.",
+					OperationOutcome.IssueType.NOTSUPPORTED, 400);
+		}
+
+		org.snomed.snowstorm.core.data.domain.CodeSystem newCodeSystem = new org.snomed.snowstorm.core.data.domain.CodeSystem();
+		org.snomed.snowstorm.core.data.domain.CodeSystem dependentCodeSystem = dependantVersion.getSnomedCodeSystem();
+		String shortName = dependentCodeSystem.getShortName() + "-EXP";
+		newCodeSystem.setShortName(shortName);
+
+		// Append 2,3,4 etc to the short name to ensure uniqueness
+		int a = 2;
+		while (snomedCodeSystemService.find(newCodeSystem.getShortName()) != null) {
+			newCodeSystem.setShortName(shortName + a);
+			a++;
+		}
+		newCodeSystem.setName("SNOMED CT Postcoordinated Expression Repository");
+		newCodeSystem.setBranchPath(String.join("/", dependentCodeSystem.getBranchPath(), newCodeSystem.getShortName()));
+		newCodeSystem.setUriModuleId(snomedModule);
+		newCodeSystem.setMaximumPostcoordinationLevel(maxPostcoordinationLevel);
+		org.snomed.snowstorm.core.data.domain.CodeSystem savedCodeSystem = snomedCodeSystemService.createCodeSystem(newCodeSystem);
+		return new FHIRCodeSystemVersion(savedCodeSystem);
+	}
+
+	private @NotNull FHIRCodeSystemVersion handleNotSnomedSupplement(CodeSystem supplement) throws ServiceException {
+		// if no dependency
+		if (!supplement.hasSupplements()) {
+			throw exception("CodeSystem supplements must declare which codesystem they supplement " +
+					"using the 'supplements' property.", OperationOutcome.IssueType.INVARIANT, 400);
+		}
+		// Check dependency is SNOMED
+		FHIRCodeSystemVersionParams dependencyParams = FHIRHelper.getCodeSystemVersionParams(CanonicalUri.fromString(supplement.getSupplements()));
+		if (dependencyParams.isSnomed()) {
+			throw exception("Non SNOMED supplements cannot supplement a SNOMED codesystem on this server", OperationOutcome.IssueType.INVARIANT, 400);
+		}
+		// Check dependency exists
+		FHIRCodeSystemVersion dependentVersion = findCodeSystemVersionOrThrow(dependencyParams);
+
+		CodeSystem updatedCodeSystem = codeSystemRepository.findByUrlAndVersion(dependentVersion.getUrl(), dependentVersion.getVersion()).toHapiCodeSystem();
+
+		supplement.getExtension().stream().forEach(x -> updatedCodeSystem.addExtension(x));
+
+
+
+		//deleteCodeSystemVersion(dependentVersion);
+
+		FHIRCodeSystemVersion updatedDependentVersion = createUpdate(updatedCodeSystem);
+
+
+
+        return updatedDependentVersion;
+	}
+
+	public @NotNull CodeSystem addSupplementToCodeSystem(CodeSystem codeSystem, FHIRCodeSystemVersion dependentVersion) {
+		CodeSystem newCodeSystem = codeSystemRepository.findByUrlAndVersion(dependentVersion.getUrl(), dependentVersion.getVersion()).toHapiCodeSystem();
+		Page<FHIRConcept> conceptsPage = conceptService.findConcepts(dependentVersion.getId(), PageRequest.of(0, PAGESIZE));
+		List<FHIRConcept> conceptsList = new ArrayList<>();
+		for(int x = 0; x < conceptsPage.getTotalPages(); x++){
+			conceptsList.addAll(conceptsPage.getContent());
+			conceptsPage = conceptService.findConcepts(dependentVersion.getId(), PageRequest.of(x, PAGESIZE));
+		}
+		FHIRGraphBuilder graphBuilder = new FHIRGraphBuilder();
+		if (Objects.isNull(dependentVersion.getHierarchyMeaning()) || "is-a".equals(dependentVersion.getHierarchyMeaning())) {
+			// Record transitive closure of concepts for subsumption testing
+			for (FHIRConcept concept : conceptsList) {
+				for (String parentCode : concept.getParents()) {
+					graphBuilder.addParent(concept.getCode(), parentCode);
+				}
+			}
+		}
+
+
+		List<CodeSystem.ConceptDefinitionComponent> concepts = conceptsList.stream().map(concept -> {
+					CodeSystem.ConceptDefinitionComponent component = new CodeSystem.ConceptDefinitionComponent();
+					List<CodeSystem.ConceptDefinitionDesignationComponent> designations = concept.getDesignations().stream().map(fd -> {
+						CodeSystem.ConceptDefinitionDesignationComponent cd = new CodeSystem.ConceptDefinitionDesignationComponent();
+						cd.setLanguage(fd.getLanguage());
+						if (StringUtils.isNotEmpty(fd.getUse())) cd.setUse(fd.getUseCoding());
+						cd.setValue(fd.getValue());
+						fd.getExtensions().forEach( fhirExtension -> {
+							cd.addExtension(fhirExtension.getHapi());
+						});
+						return cd;
+					}).toList();
+					concept.getProperties().entrySet().stream().forEach(entry -> {
+
+						entry.getValue().stream().forEach(p -> {
+							CodeSystem.ConceptPropertyComponent propertyComponent = new CodeSystem.ConceptPropertyComponent();
+							propertyComponent.setCode(p.getCode());
+							propertyComponent.setValue(p.toHapiValue(dependentVersion.getUrl()));
+							component.addProperty(propertyComponent);
+						});
+
+					});
+					concept.getExtensions().entrySet().stream().forEach( entry ->{
+						entry.getValue().stream().forEach(e -> {
+							Extension t = new Extension();
+							t.setUrl(e.getCode());
+							t.setValue(e.toHapiValue(null));
+							component.addExtension(t);
+						});
+					});
+					component.setDesignation(designations)
+							.setCode(concept.getCode())
+							.setDisplay(concept.getDisplay())
+							.setId(concept.getId());
+					return component;
+				})
+				.toList();
+
+		List<CodeSystem.ConceptDefinitionComponent> finalConcepts = concepts;
+		concepts.stream().forEach(x ->{
+
+			Collection<String> children = graphBuilder.getNodeChildren(x.getCode());
+			List<CodeSystem.ConceptDefinitionComponent> toAdd = finalConcepts.stream().filter(y -> children.contains(y.getCode())).toList();
+			toAdd.stream().forEach(z -> x.addConcept(z));
+		});
+
+		concepts = concepts.stream().filter(x -> graphBuilder.getNodeParents(x.getCode()).isEmpty()).toList();
+
+		newCodeSystem.setConcept(concepts);
+
+
+		List<CodeSystem.ConceptDefinitionComponent> modifiedConceptDefinitions = newCodeSystem.getConcept().stream().map(conceptDefinitionToUpdate -> {
+			Optional<CodeSystem.ConceptDefinitionComponent> match = codeSystem.getConcept().stream().filter(y -> y.getCode().equals(conceptDefinitionToUpdate.getCode())).findFirst();
+			if (match.isPresent()) {
+				try {
+					match.get().getExtension().forEach(conceptDefinitionToUpdate::addExtension);
+					match.get().getProperty().forEach(conceptDefinitionToUpdate::addProperty);
+					List<CodeSystem.ConceptDefinitionDesignationComponent> newList = new ArrayList<>();
+					newList.addAll(conceptDefinitionToUpdate.getDesignation());
+					match.get().getDesignation().forEach( des ->	newList.add(des));
+					conceptDefinitionToUpdate.setDesignation(newList);
+				} catch (RuntimeException e){
+					System.out.println("bla");
+				}
+
+			}
+			return conceptDefinitionToUpdate;
+		}).toList();
+
+		newCodeSystem.setConcept(modifiedConceptDefinitions);
+		return newCodeSystem;
+	}
+
 	private static boolean isSnomedCodeSystemVersionId(String id) {
 		return id.startsWith(SCT_ID_PREFIX);
 	}
diff --git a/src/main/java/org/snomed/snowstorm/fhir/services/FHIRConceptService.java b/src/main/java/org/snomed/snowstorm/fhir/services/FHIRConceptService.java
index 3d81a99a7..51dc2837e 100644
--- a/src/main/java/org/snomed/snowstorm/fhir/services/FHIRConceptService.java
+++ b/src/main/java/org/snomed/snowstorm/fhir/services/FHIRConceptService.java
@@ -123,6 +123,13 @@ private void saveAllConceptsOfCodeSystemVersion(FHIRCodeSystemVersion codeSystem
 		}
 
 		Set<String> props = new HashSet<>();
+		//treat extensions as properties, until better solution...
+		concepts.forEach(concept ->{
+			concept.getExtensions().forEach((key,value)->{
+				concept.getProperties().put(key,value);
+			});
+		});
+
 		concepts.stream()
 				.filter(concept -> concept.getProperties() != null)
 				.forEach(concept -> props.addAll(concept.getProperties().keySet()));
@@ -154,6 +161,10 @@ private void saveAllConceptsOfCodeSystemVersion(FHIRCodeSystemVersion codeSystem
 		}
 	}
 
+	public Page<FHIRConcept> findConcepts(String idWithVersion, PageRequest pageRequest){
+		return conceptRepository.findByCodeSystemVersion(idWithVersion, pageRequest);
+	}
+
 	public void deleteExistingCodes(String idWithVersion) {
 		Page<FHIRConcept> existingConcepts = conceptRepository.findByCodeSystemVersion(idWithVersion, PageRequest.of(0, 1));
 		long totalExisting = existingConcepts.getTotalElements();
diff --git a/src/main/java/org/snomed/snowstorm/fhir/services/FHIRHelper.java b/src/main/java/org/snomed/snowstorm/fhir/services/FHIRHelper.java
index bcfc1d631..16ee66c42 100644
--- a/src/main/java/org/snomed/snowstorm/fhir/services/FHIRHelper.java
+++ b/src/main/java/org/snomed/snowstorm/fhir/services/FHIRHelper.java
@@ -106,8 +106,12 @@ public static Integer findParameterIntOrNull(List<Parameters.ParametersParameter
 
 	@SuppressWarnings("unchecked")
 	public static List<String> findParameterStringListOrNull(List<Parameters.ParametersParameterComponent> parametersParameterComponents, String name) {
-		return parametersParameterComponents.stream().filter(parametersParameterComponent -> parametersParameterComponent.getName().equals(name)).findFirst()
-				.map(param -> (List<String>) param.getValue()).orElse(null);
+		List<String> result =  parametersParameterComponents.stream().filter(parametersParameterComponent -> parametersParameterComponent.getName().equals(name)).map(parametersParameterComponent -> parametersParameterComponent.getValue().primitiveValue()).toList();
+		if (result.isEmpty()){
+			return null;
+		} else {
+			return result;
+		}
 	}
 
 	public static String getDisplayLanguage(String displayLanguageParam, String acceptHeader) {
diff --git a/src/main/java/org/snomed/snowstorm/fhir/services/FHIRLoadPackageService.java b/src/main/java/org/snomed/snowstorm/fhir/services/FHIRLoadPackageService.java
index 0bb5329d7..b2f6a5af8 100644
--- a/src/main/java/org/snomed/snowstorm/fhir/services/FHIRLoadPackageService.java
+++ b/src/main/java/org/snomed/snowstorm/fhir/services/FHIRLoadPackageService.java
@@ -7,6 +7,7 @@
 import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
 import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
 import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.hl7.fhir.instance.model.api.IBaseResource;
 import org.hl7.fhir.r4.model.CodeSystem;
 import org.hl7.fhir.r4.model.OperationOutcome;
@@ -91,15 +92,16 @@ public void uploadPackageResources(File packageFile, Set<String> resourceUrlsToI
 						codeSystemService.deleteCodeSystemVersion(existingCodeSystemVersion);
 					}
 				}
-				List<CodeSystem.ConceptDefinitionComponent> concepts = codeSystem.getConcept();
-				logger.info("Importing CodeSystem {} with {} concepts from package", codeSystem.getUrl(), concepts != null ? concepts.size() : 0);
+				logger.info("Creating CodeSystem {}", codeSystem.getUrl());
 				FHIRCodeSystemVersion codeSystemVersion;
 				try {
 					codeSystemVersion = codeSystemService.createUpdate(codeSystem);
 				} catch (ServiceException e) {
 					throw new IOException("Failed to create FHIR CodeSystem.", e);
 				}
-				if (concepts != null) {
+				List<CodeSystem.ConceptDefinitionComponent> concepts = getConcepts(codeSystem, codeSystemVersion);
+				logger.info("Importing CodeSystem {} with {} concepts from package", codeSystem.getUrl(), concepts != null ? concepts.size() : 0);
+				if (concepts != null ) {
 					fhirConceptService.saveAllConceptsOfCodeSystemVersion(concepts, codeSystemVersion);
 				}
 			}
@@ -130,6 +132,22 @@ public void uploadPackageResources(File packageFile, Set<String> resourceUrlsToI
 		logger.info("Completed import of package {}.", submittedFileName);
 	}
 
+	private List<CodeSystem.ConceptDefinitionComponent> getConcepts(CodeSystem codeSystem, FHIRCodeSystemVersion version) {
+		List<CodeSystem.ConceptDefinitionComponent> concepts;
+		if (StringUtils.isEmpty(codeSystem.getSupplements())){
+			concepts = codeSystem.getConcept();
+		} else {
+			CodeSystem newCodeSystem = codeSystemService.addSupplementToCodeSystem(codeSystem, version);
+			concepts = newCodeSystem.getConcept();
+		}
+
+
+
+
+
+		return concepts;
+	}
+
 	private static void validateResources(List<FHIRPackageIndexFile> filesToImport, Set<String> resourceUrlsToImport, boolean importAll, Set<String> supportedResourceTypes) {
 		for (FHIRPackageIndexFile fhirPackageIndexFile : filesToImport) {
 			if (importAll && !supportedResourceTypes.contains(fhirPackageIndexFile.getResourceType())) {
diff --git a/src/main/java/org/snomed/snowstorm/fhir/services/FHIRValueSetProvider.java b/src/main/java/org/snomed/snowstorm/fhir/services/FHIRValueSetProvider.java
index 04b31a288..a6edc90ed 100644
--- a/src/main/java/org/snomed/snowstorm/fhir/services/FHIRValueSetProvider.java
+++ b/src/main/java/org/snomed/snowstorm/fhir/services/FHIRValueSetProvider.java
@@ -215,7 +215,8 @@ public ValueSet expandInstance(
 			@OperationParam(name="system-version") StringType systemVersion,
 			@OperationParam(name="check-system-version") StringType checkSystemVersion,
 			@OperationParam(name="force-system-version") StringType forceSystemVersion,
-			@OperationParam(name="version") StringType version)// Invalid parameter
+			@OperationParam(name="version") StringType version,
+			@OperationParam(name="version") CodeType property)// Invalid parameter
 			{
 
 		ValueSetExpansionParameters params;
@@ -225,7 +226,7 @@ public ValueSet expandInstance(
 		} else {
 			params = FHIRValueSetProviderHelper.getValueSetExpansionParameters(id, url, valueSetVersion, context, contextDirection, filter, date, offset, count,
 					includeDesignationsType, designations, includeDefinition, activeType, excludeNested, excludeNotForUI, excludePostCoordinated, displayLanguage,
-					excludeSystem, systemVersion, checkSystemVersion, forceSystemVersion, version);
+					excludeSystem, systemVersion, checkSystemVersion, forceSystemVersion, version, property);
 		}
 		return valueSetService.expand(params, FHIRHelper.getDisplayLanguage(params.getDisplayLanguage(), request.getHeader(ACCEPT_LANGUAGE_HEADER)));
 	}
@@ -255,7 +256,8 @@ public ValueSet expandType(
 			@OperationParam(name="system-version") StringType systemVersion,
 			@OperationParam(name="check-system-version") StringType checkSystemVersion,
 			@OperationParam(name="force-system-version") StringType forceSystemVersion,
-			@OperationParam(name="version") StringType version)// Invalid parameter
+			@OperationParam(name="version") StringType version,
+			@OperationParam(name="property") CodeType property)// Invalid parameter
 			{
 		logger.info(FHIRValueSetProviderHelper.getFullURL(request));
 		ValueSetExpansionParameters params;
@@ -275,10 +277,10 @@ public ValueSet expandType(
 		} else {
 			params = FHIRValueSetProviderHelper.getValueSetExpansionParameters(null, url, valueSetVersion, context, contextDirection, filter, date, offset, count,
 					includeDesignationsType, designations, includeDefinition, activeType, excludeNested, excludeNotForUI, excludePostCoordinated, displayLanguage,
-					excludeSystem, systemVersion, checkSystemVersion, forceSystemVersion, version);
+					excludeSystem, systemVersion, checkSystemVersion, forceSystemVersion, version, property);
 		}
 
-		return valueSetService.expand(params, FHIRHelper.getDisplayLanguage(params.getDisplayLanguage(), request.getHeader(ACCEPT_LANGUAGE_HEADER)));
+		return valueSetService.expand(params,  request.getHeader(ACCEPT_LANGUAGE_HEADER));
 	}
 
 	@Operation(name="$validate-code", idempotent=true)
diff --git a/src/main/java/org/snomed/snowstorm/fhir/services/FHIRValueSetProviderHelper.java b/src/main/java/org/snomed/snowstorm/fhir/services/FHIRValueSetProviderHelper.java
index 05b61d1ef..de68755c0 100644
--- a/src/main/java/org/snomed/snowstorm/fhir/services/FHIRValueSetProviderHelper.java
+++ b/src/main/java/org/snomed/snowstorm/fhir/services/FHIRValueSetProviderHelper.java
@@ -60,8 +60,8 @@ static ValueSetExpansionParameters getValueSetExpansionParameters(IdType id, fin
 					findParameterCanonicalOrNull(parametersParameterComponents, "system-version"),
 					findParameterCanonicalOrNull(parametersParameterComponents, "check-system-version"),
 					findParameterCanonicalOrNull(parametersParameterComponents, "force-system-version"),
-					findParameterStringOrNull(parametersParameterComponents, "version"));
-
+					findParameterStringOrNull(parametersParameterComponents, "version"),
+					findParameterStringOrNull(parametersParameterComponents, "property"));
 	}
 
 	static ValueSetExpansionParameters getValueSetExpansionParameters(
@@ -86,7 +86,8 @@ static ValueSetExpansionParameters getValueSetExpansionParameters(
 			final StringType systemVersion,
 			final StringType checkSystemVersion,
 			final StringType forceSystemVersion,
-			final StringType version) {
+			final StringType version,
+			final CodeType property) {
 
 		try {
 			return new ValueSetExpansionParameters(
@@ -112,7 +113,8 @@ static ValueSetExpansionParameters getValueSetExpansionParameters(
 					CanonicalUri.fromString(getOrNull(systemVersion)),
 					CanonicalUri.fromString(getOrNull(checkSystemVersion)),
 					CanonicalUri.fromString(getOrNull(forceSystemVersion)),
-					getOrNull(version));
+					getOrNull(version),
+					getOrNull(property));
 		} catch (URISyntaxException e) {
 			throw  FHIRHelper.exception("Invalid url parameter.", OperationOutcome.IssueType.INVALID, 400);
 		}
diff --git a/src/main/java/org/snomed/snowstorm/fhir/services/FHIRValueSetService.java b/src/main/java/org/snomed/snowstorm/fhir/services/FHIRValueSetService.java
index b36fdb3bb..f41d8792e 100644
--- a/src/main/java/org/snomed/snowstorm/fhir/services/FHIRValueSetService.java
+++ b/src/main/java/org/snomed/snowstorm/fhir/services/FHIRValueSetService.java
@@ -8,6 +8,7 @@
 import io.kaicode.elasticvc.api.VersionControlHelper;
 import it.unimi.dsi.fastutil.longs.LongArrayList;
 
+import org.apache.commons.lang3.tuple.Pair;
 import org.hl7.fhir.r4.model.*;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -61,6 +62,21 @@
 @Service
 public class FHIRValueSetService {
 
+	public static final String[] URLS = {"http://hl7.org/fhir/StructureDefinition/itemWeight",
+			"http://hl7.org/fhir/StructureDefinition/valueset-label",
+			"http://hl7.org/fhir/StructureDefinition/valueset-conceptOrder",
+			"http://hl7.org/fhir/StructureDefinition/valueset-deprecated",
+			"http://hl7.org/fhir/StructureDefinition/valueset-concept-definition",
+			"http://hl7.org/fhir/StructureDefinition/valueset-supplement"
+	};
+
+	public static final HashMap<String,String> PROPERTY_TO_URL = new HashMap<>();
+
+	static{
+		PROPERTY_TO_URL.put("definition","http://hl7.org/fhir/concept-properties#definition");
+		PROPERTY_TO_URL.put("prop","http://hl7.org/fhir/test/CodeSystem/properties#prop");
+	}
+
 	// Constant to help with "?fhir_vs=refset"
 	public static final String REFSETS_WITH_MEMBERS = "Refsets";
 
@@ -178,7 +194,6 @@ public ValueSet expand(final ValueSetExpansionParameters params, String displayL
 		notSupported("context", params.getContext());
 		notSupported("contextDirection", params.getContextDirection());
 		notSupported("date", params.getDate());
-		notSupported("designation", params.getDesignations());
 		notSupported("excludeNotForUI", params.getExcludeNotForUI());
 		notSupported("excludePostCoordinated", params.getExcludePostCoordinated());
 		notSupported("version", params.getVersion());// Not part of the FHIR API spec but requested under MAINT-1363
@@ -234,7 +249,7 @@ public ValueSet expand(final ValueSetExpansionParameters params, String displayL
 			copyright = SNOMED_VALUESET_COPYRIGHT;
 
 			FHIRCodeSystemVersion codeSystemVersion = allInclusionVersions.iterator().next();
-			List<LanguageDialect> languageDialects = ControllerHelper.parseAcceptLanguageHeader(displayLanguage);
+			List<LanguageDialect> languageDialects = ControllerHelper.parseAcceptLanguageHeader(FHIRHelper.getDisplayLanguage(params.getDisplayLanguage(),displayLanguage));
 
 			// Constraints:
 			// - Elasticsearch prevents us from requesting results beyond the first 10K
@@ -377,6 +392,11 @@ public ValueSet expand(final ValueSetExpansionParameters params, String displayL
 
 		Map<String, String> idAndVersionToUrl = allInclusionVersions.stream()
 				.collect(Collectors.toMap(FHIRCodeSystemVersion::getId, FHIRCodeSystemVersion::getUrl));
+		Map<String, String> idAndVersionToLanguage = allInclusionVersions.stream()
+				.collect(Collectors.toMap(FHIRCodeSystemVersion::getId, FHIRCodeSystemVersion::getLanguage));
+		allInclusionVersions.forEach(codeSystemVersion -> {
+			codeSystemVersion.getExtensions().forEach(hapiValueSet::addExtension);
+				});
 		ValueSet.ValueSetExpansionComponent expansion = new ValueSet.ValueSetExpansionComponent();
 		String id = UUID.randomUUID().toString();
 		expansion.setId(id);
@@ -384,6 +404,12 @@ public ValueSet expand(final ValueSetExpansionParameters params, String displayL
 		expansion.setTimestamp(new Date());
 		Optional.ofNullable(params.getActiveOnly()).ifPresent(x->expansion.addParameter(new ValueSet.ValueSetExpansionParameterComponent(new StringType("activeOnly")).setValue(new BooleanType(x))));
 		Optional.ofNullable(params.getExcludeNested()).ifPresent(x->expansion.addParameter(new ValueSet.ValueSetExpansionParameterComponent(new StringType("excludeNested")).setValue(new BooleanType(x))));
+		Optional.ofNullable(params.getIncludeDesignations()).ifPresent(x->expansion.addParameter(new ValueSet.ValueSetExpansionParameterComponent(new StringType("includeDesignations")).setValue(new BooleanType(x))));
+		Optional.ofNullable(params.getDesignations()).ifPresent(x->{
+			x.stream().forEach( language -> {
+				expansion.addParameter(new ValueSet.ValueSetExpansionParameterComponent(new StringType("designation")).setValue(new StringType(language)));
+			});
+		});
 		allInclusionVersions.forEach(codeSystemVersion -> {
 				if (codeSystemVersion.getVersion() != null) {
 					expansion.addParameter(new ValueSet.ValueSetExpansionParameterComponent(new StringType("version"))
@@ -393,25 +419,98 @@ public ValueSet expand(final ValueSetExpansionParameters params, String displayL
 				}
 			}
 		);
-        //this line was removed because of the GG tests.
-		//expansion.addParameter(new ValueSet.ValueSetExpansionParameterComponent(new StringType("displayLanguage")).setValue(new StringType(displayLanguage)));
+
+		hapiValueSet.getExtension().forEach(ext ->{
+			if(ext.getUrl().equals("http://hl7.org/fhir/StructureDefinition/valueset-supplement")){
+				expansion.addParameter(new ValueSet.ValueSetExpansionParameterComponent(new StringType("used-supplement"))
+						.setValue(ext.getValue()));
+			}
+
+		});
+
+
+		Optional.ofNullable(params.getProperty()).ifPresent( x ->{
+					addPropertyToExpansion(x, PROPERTY_TO_URL.get(x), expansion);
+				}
+		);
+		final String fhirDisplayLanguage;
+		if(Optional.ofNullable(params.getDisplayLanguage()).isPresent()){
+			fhirDisplayLanguage = params.getDisplayLanguage();
+			expansion.addParameter(new ValueSet.ValueSetExpansionParameterComponent(new StringType("displayLanguage")).setValue(new CodeType(fhirDisplayLanguage)));
+		} else if (hasDisplayLanguage(hapiValueSet)){
+			fhirDisplayLanguage = hapiValueSet.getCompose().getExtensionByUrl("http://hl7.org/fhir/tools/StructureDefinion/valueset-expansion-param").getExtensionString("value");
+			expansion.addParameter(new ValueSet.ValueSetExpansionParameterComponent(new StringType("displayLanguage")).setValue(new CodeType(fhirDisplayLanguage)));
+
+		} else if (displayLanguage != null){
+			fhirDisplayLanguage = displayLanguage;
+			expansion.addParameter(new ValueSet.ValueSetExpansionParameterComponent(new StringType("displayLanguage")).setValue(new CodeType(fhirDisplayLanguage)));
+		} else {
+			fhirDisplayLanguage = null;
+		}
+
+
 		expansion.setContains(conceptsPage.stream().map(concept -> {
+					List<ValueSet.ConceptReferenceComponent> references = hapiValueSet.getCompose().getInclude().stream()
+							.flatMap(set -> set.getConcept().stream()).filter(c -> c.getCode().equals(concept.getCode())).toList();
+
+
 					ValueSet.ValueSetExpansionContainsComponent component = new ValueSet.ValueSetExpansionContainsComponent()
 							.setSystem(idAndVersionToUrl.get(concept.getCodeSystemVersion()))
 							.setCode(concept.getCode())
 							.setInactiveElement(concept.isActive() ? null : new BooleanType(true))
 							.setDisplay(concept.getDisplay());
-					concept.getProperties().getOrDefault("status",Collections.emptyList()).stream().filter(x -> x.getValue().equals("retired")).findFirst().ifPresent(x-> component.setAbstract(true));
-					concept.getProperties().getOrDefault("status",Collections.emptyList()).stream().filter(x -> x.getValue().equals("retired")).findFirst().ifPresent(x-> component.setInactive(true));
-					if (includeDesignations) {
-						for (FHIRDesignation designation : concept.getDesignations()) {
-							ValueSet.ConceptReferenceDesignationComponent designationComponent = new ValueSet.ConceptReferenceDesignationComponent();
-							designationComponent.setLanguage(designation.getLanguage());
-							designationComponent.setUse(designation.getUseCoding());
-							designationComponent.setValue(designation.getValue());
-							component.addDesignation(designationComponent);
+
+					concept.getProperties().entrySet().forEach( p -> {
+						if (p.getKey().equals("status")){
+							p.getValue().stream()
+									.filter(x -> x.getValue().equals("retired"))
+									.findFirst()
+									.ifPresent(x-> {
+										component.setAbstract(true);
+										component.setInactive(true);
+									});
+
+						} else if (p.getKey().equals("http://hl7.org/fhir/StructureDefinition/itemWeight")){
+							p.getValue().stream()
+									.findFirst()
+									.ifPresent(y-> {
+										addPropertyToContains("weight", component, y.toHapiValue(null));
+										addPropertyToExpansion("weight", "http://hl7.org/fhir/concept-properties#itemWeight", expansion);
+									});
+						} else if (p.getKey().equals("http://hl7.org/fhir/StructureDefinition/codesystem-label")){
+							p.getValue().stream()
+									.findFirst()
+									.ifPresent(y-> {
+										addPropertyToContains("label", component, y.toHapiValue(null));
+										addPropertyToExpansion("label", "http://hl7.org/fhir/concept-properties#label", expansion);
+									});
+						} else if (p.getKey().equals("http://hl7.org/fhir/StructureDefinition/codesystem-conceptOrder")){
+							p.getValue().stream()
+									.findFirst()
+									.ifPresent(y-> {
+										addPropertyToContains("order", component, new DecimalType(y.toHapiValue(null).primitiveValue()));
+										addPropertyToExpansion("order", "http://hl7.org/fhir/concept-properties#order", expansion);
+									});
 						}
-					}
+					});
+
+					Optional.ofNullable(params.getProperty()).ifPresent(x ->{
+						List<FHIRProperty> properties =concept.getProperties().getOrDefault(x, Collections.emptyList());
+						properties.stream()
+								.findFirst()
+								.ifPresent(y-> {
+									addPropertyToContains(y.getCode(), component, y.toHapiValue(null));
+								});
+					});
+
+					concept.getExtensions().forEach((key, value) ->{
+						value.stream().filter(x ->!x.isSpecialExtension()).forEach( fe ->{
+								//addition of these extensions is optional according to the G.G. tests
+								//component.addExtension(fe.getCode(), fe.toHapiValue(null));
+						});
+					});
+					addInfoFromReferences(component, references);
+					setDisplayAndDesignations(component, concept, idAndVersionToLanguage.get(concept.getCodeSystemVersion()), includeDesignations, fhirDisplayLanguage, params.getDesignations());
 					return component;
 		})
 				.collect(Collectors.toList()));
@@ -432,6 +531,214 @@ public ValueSet expand(final ValueSetExpansionParameters params, String displayL
 		}
 
 		return hapiValueSet;
+
+
+	}
+
+	private static boolean hasDisplayLanguage(ValueSet hapiValueSet) {
+        return Optional.ofNullable(hapiValueSet.getCompose().getExtensionByUrl("http://hl7.org/fhir/tools/StructureDefinion/valueset-expansion-param")).isPresent() && "displayLanguage".equals(hapiValueSet.getCompose().getExtensionByUrl("http://hl7.org/fhir/tools/StructureDefinion/valueset-expansion-param").getExtensionString("name"));
+	}
+
+	private static void setDisplayAndDesignations(ValueSet.ValueSetExpansionContainsComponent component, FHIRConcept concept, String defaultConceptLanguage, boolean includeDesignations, String displayLanguage, List<String> designationLanguages) {
+		List<String> designationLang = Optional.ofNullable(designationLanguages).orElse(Collections.emptyList()).stream().map(x -> {
+			String[] systemAndLanguage = x.split("\\|");
+			if (systemAndLanguage.length < 2){
+				return systemAndLanguage[0];
+			} else {
+				return systemAndLanguage[1];
+			}
+
+		}).toList();
+		Map<String, ValueSet.ConceptReferenceDesignationComponent> languageToDesignation = new HashMap<>();
+		Map<String, List<Locale>> languageToVarieties = new HashMap<>();
+		List<Pair<LanguageDialect, Double>> weightedLanguages = ControllerHelper.parseAcceptLanguageHeaderWithWeights(displayLanguage,true);
+		Locale defaultLocale = Locale.forLanguageTag(defaultConceptLanguage);
+        if(languageToVarieties.get(defaultLocale.getLanguage()) == null){
+			List<Locale> allVarieties = new ArrayList<>();
+			languageToVarieties.put(defaultLocale.getLanguage(),allVarieties);
+		}
+		languageToVarieties.get(defaultLocale.getLanguage()).add(defaultLocale);
+
+		languageToDesignation.put(defaultConceptLanguage, new ValueSet.ConceptReferenceDesignationComponent().setValue(component.getDisplay())
+				.setLanguage(defaultConceptLanguage) );
+
+		List<ValueSet.ConceptReferenceDesignationComponent> noLanguage = new ArrayList<>();
+
+		for (ValueSet.ConceptReferenceDesignationComponent designation : component.getDesignation()){
+			if (designation.getLanguage()==null) {
+				noLanguage.add(designation);
+			} else {
+				Locale designationLocale = Locale.forLanguageTag(designation.getLanguage());
+				if (languageToVarieties.get(designationLocale.getLanguage()) == null) {
+					List<Locale> allVarieties = new ArrayList<>();
+					languageToVarieties.put(designationLocale.getLanguage(), allVarieties);
+				}
+				languageToVarieties.get(designationLocale.getLanguage()).add(designationLocale);
+				languageToDesignation.put(designation.getLanguage(), designation);
+			}
+
+		}
+
+
+			for (FHIRDesignation designation : concept.getDesignations()) {
+				ValueSet.ConceptReferenceDesignationComponent designationComponent = new ValueSet.ConceptReferenceDesignationComponent();
+				designationComponent.setLanguage(designation.getLanguage());
+				designationComponent.setUse(designation.getUseCoding());
+				designationComponent.setValue(designation.getValue());
+				Optional.ofNullable(designation.getExtensions()).orElse(Collections.emptyList()).forEach(
+						e -> {
+							designationComponent.addExtension(e.getHapi());
+						}
+				);
+				if (designation.getLanguage()==null) {
+					noLanguage.add(designationComponent);
+				} else {
+					Locale designationLocale = Locale.forLanguageTag(designation.getLanguage());
+					if (languageToVarieties.get(designationLocale.getLanguage()) == null) {
+						List<Locale> allVarieties = new ArrayList<>();
+						languageToVarieties.put(designationLocale.getLanguage(), allVarieties);
+					}
+					languageToVarieties.get(designationLocale.getLanguage()).add(designationLocale);
+					languageToDesignation.put(designation.getLanguage(), designationComponent);
+				}
+			}
+
+		String requestedLanguage = determineRequestedLanguage(defaultConceptLanguage, weightedLanguages, languageToDesignation.keySet(), languageToVarieties);
+		if (requestedLanguage == null) {
+			component.setDisplay(null);
+		} else {
+			component.setDisplay(languageToDesignation.get(requestedLanguage).getValue());
+		}
+
+		if (includeDesignations) {
+			List<ValueSet.ConceptReferenceDesignationComponent> newDesignations = new ArrayList<>();
+			for (Map.Entry<String, ValueSet.ConceptReferenceDesignationComponent> entry : languageToDesignation.entrySet() ){
+
+				if (!entry.getKey().equals(requestedLanguage)) {
+					if (entry.getKey().equals(defaultConceptLanguage)) {
+						entry.getValue().setUse(new Coding("http://terminology.hl7.org/CodeSystem/designation-usage", "display", null));
+					}
+
+
+					if(designationLang.isEmpty() || designationLang.contains(entry.getValue().getLanguage())) {
+						newDesignations.add(entry.getValue());
+					}
+
+				}
+			}
+			newDesignations.addAll(noLanguage);
+			component.setDesignation(newDesignations);
+		} else {
+			component.setDesignation(Collections.emptyList());
+		}
+
+	}
+
+	private static String determineRequestedLanguage(String defaultConceptLanguage, List<Pair<LanguageDialect, Double>> weightedLanguages, Set<String> availableVarieties, Map<String, List<Locale>> languageToVarieties) {
+		List<Pair<LanguageDialect,Double>> allowedLanguages = new ArrayList<>(weightedLanguages.stream().filter(x -> (x.getRight()>0d)).toList());
+		allowedLanguages.sort( (a,b) ->{ return a.getRight().compareTo(b.getRight())*-1;});
+		String requestedLanguage = allowedLanguages.isEmpty() ?defaultConceptLanguage:allowedLanguages.get(0).getLeft().getLanguageCode();
+		if (!availableVarieties.contains(requestedLanguage)){
+			Locale requested = Locale.forLanguageTag(requestedLanguage);
+			if(languageToVarieties.get(requested.getLanguage())==null){
+				List<String> forbiddenLanguages = weightedLanguages.stream().filter(x -> x.getRight().equals(0d)).map(x -> x.getLeft().getLanguageCode()).toList();
+				if(forbiddenLanguages.contains(defaultConceptLanguage)||forbiddenLanguages.contains("*")){
+					requestedLanguage = null;
+				} else {
+					requestedLanguage = defaultConceptLanguage;
+				}
+			} else {
+				requestedLanguage = languageToVarieties.get(requested.getLanguage()).stream().findFirst().get().toLanguageTag();
+			}
+		}
+		return requestedLanguage;
+	}
+
+	private static void addPropertyToContains(String code, ValueSet.ValueSetExpansionContainsComponent component, Type value) {
+		Extension extension = new Extension();
+		extension.addExtension("code", new CodeType(code));
+		extension.addExtension("value", value);
+		extension.setUrl("http://hl7.org/fhir/5.0/StructureDefinition/extension-ValueSet.expansion.contains.property");
+		component.addExtension(extension);
+	}
+
+	private static void addPropertyToExpansion(String code, String url, ValueSet.ValueSetExpansionComponent expansion) {
+		if(expansion.getExtensionsByUrl("http://hl7.org/fhir/5.0/StructureDefinition/extension-ValueSet.expansion.property")
+				.stream()
+				.filter( extension -> extension.hasExtension("code"))
+				.noneMatch(extension -> extension.getExtensionByUrl("code").getValue().equalsDeep(new CodeType(code)))) {
+			Extension expExtension = new Extension();
+			expExtension.addExtension("code", new CodeType(code));
+			expExtension.addExtension("uri", new UriType(url));
+			expExtension.setUrl("http://hl7.org/fhir/5.0/StructureDefinition/extension-ValueSet.expansion.property");
+			expansion.addExtension(expExtension);
+		}
+	}
+
+	private static void removeExtension(Element component,String uri, String uri2,  Type value){
+		List<Extension> extensions = component.getExtensionsByUrl(uri);
+        for (Extension extension : extensions) {
+            List<Extension> extensions2 = extension.getExtensionsByUrl(uri2);
+            for (Extension item : extensions2) {
+                if (item.getValue().equalsDeep(value)) {
+                    component.getExtension().remove(extension);
+                    return;
+                }
+            }
+        }
+	}
+
+	private static void addInfoFromReferences(ValueSet.ValueSetExpansionContainsComponent component, List<ValueSet.ConceptReferenceComponent> references) {
+		references.stream().filter(reference -> reference.getCode().equals(component.getCode())).forEach( reference -> {
+			reference.getDesignation().forEach(
+					rd->{
+						Optional<ValueSet.ConceptReferenceDesignationComponent> od = component.getDesignation().stream().filter(ode -> ode.getLanguage().equals(rd.getLanguage())).findFirst();
+						od.ifPresentOrElse(x ->{
+							x.setValue(rd.getValue());
+							rd.getExtension().forEach(x::addExtension);
+						},()-> component.addDesignation(rd));
+					}
+			);
+			reference.getExtension().forEach(
+					re->{
+						if (Arrays.asList(FHIRValueSetService.URLS).contains(re.getUrl())){
+
+							Extension property = new Extension();
+							switch (re.getUrl()){
+								case "http://hl7.org/fhir/StructureDefinition/itemWeight":
+									removeExtension(component,"http://hl7.org/fhir/5.0/StructureDefinition/extension-ValueSet.expansion.contains.property","code" ,new CodeType("weight"));
+									property.addExtension("code",new CodeType("weight"));
+									property.addExtension("value", re.getValue());
+									property.setUrl("http://hl7.org/fhir/5.0/StructureDefinition/extension-ValueSet.expansion.contains.property");
+									break;
+								case "http://hl7.org/fhir/StructureDefinition/valueset-label":
+									removeExtension(component,"http://hl7.org/fhir/5.0/StructureDefinition/extension-ValueSet.expansion.contains.property","code" ,new CodeType("label"));
+									property.addExtension("code",new CodeType("label"));
+									property.addExtension("value", re.getValue());
+									property.setUrl("http://hl7.org/fhir/5.0/StructureDefinition/extension-ValueSet.expansion.contains.property");
+									break;
+								case "http://hl7.org/fhir/StructureDefinition/valueset-conceptOrder":
+									removeExtension(component,"http://hl7.org/fhir/5.0/StructureDefinition/extension-ValueSet.expansion.contains.property","code" ,new CodeType("order"));
+									property.addExtension("code",new CodeType("order"));
+									property.addExtension("value", new DecimalType(re.getValue().primitiveValue()));
+									property.setUrl("http://hl7.org/fhir/5.0/StructureDefinition/extension-ValueSet.expansion.contains.property");
+									break;
+								case "http://hl7.org/fhir/StructureDefinition/valueset-deprecated":
+									property = re;
+									break;
+								case "http://hl7.org/fhir/StructureDefinition/valueset-concept-definition":
+									property = re;
+									break;
+								default:
+							}
+							component.addExtension(property);
+						}
+					}
+			);
+
+
+		});
+
 	}
 
 	private String getUserRef(ValueSet valueSet) {
diff --git a/src/main/java/org/snomed/snowstorm/rest/ControllerHelper.java b/src/main/java/org/snomed/snowstorm/rest/ControllerHelper.java
index 55f47ae16..636679b57 100644
--- a/src/main/java/org/snomed/snowstorm/rest/ControllerHelper.java
+++ b/src/main/java/org/snomed/snowstorm/rest/ControllerHelper.java
@@ -2,6 +2,8 @@
 
 import com.google.common.base.Strings;
 import io.kaicode.rest.util.branchpathrewrite.BranchPathUriUtil;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
 import org.snomed.snowstorm.core.data.domain.ConceptMini;
 import org.snomed.snowstorm.core.data.services.DialectConfigurationService;
 import org.snomed.snowstorm.core.data.services.NotFoundException;
@@ -157,14 +159,15 @@ public static List<LanguageDialect> parseAcceptLanguageHeaderWithDefaultFallback
 		return languageDialects;
 	}
 
-	public static List<LanguageDialect> parseAcceptLanguageHeader(String acceptLanguageHeader) {
+
+	public static List<Pair<LanguageDialect, Double>> parseAcceptLanguageHeaderWithWeights(String acceptLanguageHeader, boolean wildcard){
 		// en-ie-x-21000220103;q=0.8,en-US;q=0.5
-		List<LanguageDialect> languageDialects = new ArrayList<>();
+		List<Pair<LanguageDialect,Double>> languageDialectsAndWeights = new ArrayList<>();
 
 		if (acceptLanguageHeader == null) {
 			acceptLanguageHeader = "";
 		}
-
+		Double weight;
 		acceptLanguageHeader = acceptLanguageHeader.replaceAll("\\s+", "");
 		String[] acceptLanguageList = acceptLanguageHeader.toLowerCase().split(",");
 		for (String acceptLanguage : acceptLanguageList) {
@@ -178,30 +181,46 @@ public static List<LanguageDialect> parseAcceptLanguageHeader(String acceptLangu
 			String[] valueAndWeight = acceptLanguage.split(";");
 			// We don't use the weight, just take the value
 			String value = valueAndWeight[0];
+			if (valueAndWeight.length < 2){
+				weight = 0.1;
+			} else {
+				weight = Double.parseDouble(valueAndWeight[1].substring(2));
+			}
 
-			Matcher matcher = LANGUAGE_PATTERN.matcher(value);
-			if (matcher.matches()) {
-				languageCode = matcher.group(1);
-			} else if ((matcher = LANGUAGE_AND_REFSET_PATTERN.matcher(value)).matches()) {
-				languageCode = matcher.group(1);
-				languageReferenceSet = parseLong(matcher.group(2));
-			} else if ((matcher = LANGUAGE_AND_DIALECT_PATTERN.matcher(value)).matches() || (matcher = LANGUAGE_AND_DIALECT_AND_CONTEXT_PATTERN.matcher(value)).matches()) {
-				languageCode = matcher.group(1);
-				languageReferenceSet = DialectConfigurationService.instance().findRefsetForDialect(value); 
-			} else if ((matcher = LANGUAGE_AND_DIALECT_AND_REFSET_PATTERN.matcher(value)).matches()) {
-				languageCode = matcher.group(1);
-				languageReferenceSet = parseLong(matcher.group(3));
+			if("*".equals(value) && wildcard){
+				languageCode = value;
 			} else {
-				throw new IllegalArgumentException("Unexpected value within Accept-Language request header '" + value + "'.");
+
+				Matcher matcher = LANGUAGE_PATTERN.matcher(value);
+				if (matcher.matches()) {
+					languageCode = matcher.group(1);
+				} else if ((matcher = LANGUAGE_AND_REFSET_PATTERN.matcher(value)).matches()) {
+					languageCode = matcher.group(1);
+					languageReferenceSet = parseLong(matcher.group(2));
+				} else if ((matcher = LANGUAGE_AND_DIALECT_PATTERN.matcher(value)).matches() || (matcher = LANGUAGE_AND_DIALECT_AND_CONTEXT_PATTERN.matcher(value)).matches()) {
+					languageCode = matcher.group(1);
+					languageReferenceSet = DialectConfigurationService.instance().findRefsetForDialect(value);
+				} else if ((matcher = LANGUAGE_AND_DIALECT_AND_REFSET_PATTERN.matcher(value)).matches()) {
+					languageCode = matcher.group(1);
+					languageReferenceSet = parseLong(matcher.group(3));
+				} else {
+					throw new IllegalArgumentException("Unexpected value within Accept-Language request header '" + value + "'.");
+				}
 			}
-			
-			LanguageDialect languageDialect = new LanguageDialect(languageCode, languageReferenceSet);
-			if (!languageDialects.contains(languageDialect)) {
+
+
+			Pair<LanguageDialect,Double> languageDialect = new ImmutablePair<>(new LanguageDialect(languageCode, languageReferenceSet), weight);
+
+			if (!languageDialectsAndWeights.contains(languageDialect)) {
 				//Would normally use a Set here, but the order may be important
-				languageDialects.add(languageDialect);
+				languageDialectsAndWeights.add(languageDialect);
 			}
 		}
-		return languageDialects;
+		return languageDialectsAndWeights;
+	}
+
+	public static List<LanguageDialect> parseAcceptLanguageHeader(String acceptLanguageHeader) {
+		return parseAcceptLanguageHeaderWithWeights(acceptLanguageHeader,false).stream().map(x -> x.getLeft()).toList();
 	}
 
 	static void validatePageSize(long offset, int limit) {