diff --git a/src/main/java/org/openepics/names/rest/api/v1/INames.java b/src/main/java/org/openepics/names/rest/api/v1/INames.java
new file mode 100644
index 0000000000000000000000000000000000000000..ff773e4c75ba8eec4242e869a06e7e55c0a6ff9a
--- /dev/null
+++ b/src/main/java/org/openepics/names/rest/api/v1/INames.java
@@ -0,0 +1,416 @@
+/*
+ * Copyright (C) 2021 European Spallation Source ERIC.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+package org.openepics.names.rest.api.v1;
+
+import java.util.List;
+
+import org.openepics.names.rest.beans.FieldName;
+import org.openepics.names.rest.beans.NameElement;
+import org.openepics.names.util.response.ResponseBoolean;
+import org.openepics.names.util.response.ResponseBooleanList;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * This part of REST API provides names data for Naming application.
+ *
+ * @author Lars Johansson
+ */
+@RequestMapping("/api/v1/names")
+public interface INames {
+
+    /*
+       FieldName   - UUID, NAME, NAMEEQUIVALENCE, SYSTEMSTRUCTURE, DEVICESTRUCTURE, DESCRIPTION
+
+       NameElement - uuid               (UUID)
+                     systemgroup        (UUID)
+                     system             (UUID)
+                     subsystem          (UUID)
+                     devicetype         (UUID)
+                     systemstructure    (String)(mnemonic path)
+                     devicestructure    (String)(mnemonic path)
+                     index              (String)
+                     name               (String)
+                     description        (String)
+                     status             (Status)
+                     latest             (Boolean)
+                     deleted            (Boolean)
+                     when               (Date)
+                     who                (String)
+                     comment            (String)
+
+       authentication/authorization
+           3 levels - no, user, administrator
+               no            - read
+               user          - create, update, delete
+             ( administrator )
+
+       Methods
+           create    POST   /names                                - createNames(List<NameElement>)
+           ----------------------------------------------------------------------------------------------------
+           read      GET    /names                                - readNames(Boolean, FieldName[], String[], FieldName, Boolean, Integer, Integer)
+           read      GET    /names/{name}                         - readNames(String, FieldName, Boolean, Integer, Integer)
+           read      GET    /names/systemstructure/{mnemonicpath} - readNamesSystemStructure(String, FieldName, Boolean, Integer, Integer)
+           read      GET    /names/devicestructure/{mnemonicpath} - readNamesDeviceStructure(String, FieldName, Boolean, Integer, Integer)
+           read      GET    /names/history/{uuid}                 - readNamesHistory(String, FieldName, Boolean, Integer, Integer)
+           ----------------------------------------------------------------------------------------------------
+           read      GET    /names/equivalence/{name}             - equivalenceName(String)
+           read      GET    /names/exists/{name}                  - existsName(String)
+           read      GET    /names/islegacy/{name}                - isLegacyName(String)
+           read      GET    /names/isvalidtocreate/{name}         - isValidToCreateName(String)
+           ----------------------------------------------------------------------------------------------------
+           read      GET    /names/validatecreate                 - validateNamesCreate(List<NameElement>)
+           read      GET    /names/validateupdate                 - validateNamesUpdate(List<NameElement>)
+           read      GET    /names/validatedelete                 - validateNamesDelete(List<NameElement>)
+           ----------------------------------------------------------------------------------------------------
+           update    PUT    /names                                - updateNames(List<NameElement>)
+           ----------------------------------------------------------------------------------------------------
+           delete    DELETE /names                                - deleteNames(List<NameElement>)
+
+       Note
+           read      GET    /names/{name} - both name and uuid (name - exact and search, uuid exact)
+     */
+
+    /**
+     * Create names by list of name elements.
+     * Return list of created name elements.
+     *
+     * @param nameElements name elements
+     * @return created name elements
+     */
+    @RequestMapping (
+            method = RequestMethod.POST,
+            produces = {"application/json"},
+            consumes = {"application/json"})
+    public List<NameElement> createNames(
+            @RequestBody(required = true) List<NameElement> nameElements);
+
+    // ----------------------------------------------------------------------------------------------------
+
+    /**
+     * Find valid names (search).
+     * Return list of name elements.
+     *
+     * @param deleted deleted
+     * @param queryFields query fields
+     * @param queryValues query values
+     * @param orderBy order by
+     * @param isAsc is ascending
+     * @param offset offset
+     * @param limit limit
+     * @return list of name elements
+     */
+    @RequestMapping (
+            method = RequestMethod.GET,
+            produces = {"application/json"})
+    public List<NameElement> readNames(
+            @RequestParam(required = false) Boolean deleted,
+            @RequestParam(required = false) FieldName[] queryFields,
+            @RequestParam(required = false) String[] queryValues,
+            @RequestParam(required = false) FieldName orderBy,
+            @RequestParam(required = false) Boolean isAsc,
+            @RequestParam(required = false) Integer offset,
+            @RequestParam(required = false) Integer limit);
+
+    /**
+     * Find valid names by name or uuid (search).
+     * Return list of name elements.
+     *
+     * @param name name or uuid
+     * @param orderBy order by
+     * @param isAsc is ascending
+     * @param offset offset
+     * @param limit limit
+     * @return list of name elements
+     */
+    @RequestMapping (
+            value = "/{name}",
+            method = RequestMethod.GET,
+            produces = {"application/json"})
+    public List<NameElement> readNames(
+            @PathVariable("name") String name,
+            @RequestParam(required = false) FieldName orderBy,
+            @RequestParam(required = false) Boolean isAsc,
+            @RequestParam(required = false) Integer offset,
+            @RequestParam(required = false) Integer limit);
+
+    /**
+     * Find valid names by system structure mnemonic path (search).
+     * Return list of name elements.
+     *
+     * @param mnemonicpath mnemonic path
+     * @param orderBy order by
+     * @param isAsc is ascending
+     * @param offset offset
+     * @param limit limit
+     * @return list of name elements
+     */
+    @RequestMapping (
+            value = "/systemstructure/{mnemonicpath}",
+            method = RequestMethod.GET,
+            produces = {"application/json"})
+    public List<NameElement> readNamesSystemStructure(
+            @PathVariable("mnemonicpath") String mnemonicpath,
+            @RequestParam(required = false) FieldName orderBy,
+            @RequestParam(required = false) Boolean isAsc,
+            @RequestParam(required = false) Integer offset,
+            @RequestParam(required = false) Integer limit);
+
+    /**
+     * Find valid names by device structure mnemonic path (search).
+     * Return list of name elements.
+     *
+     * @param mnemonicpath mnemonic path
+     * @param orderBy order by
+     * @param isAsc is ascending
+     * @param offset offset
+     * @param limit limit
+     * @return list of name elements
+     */
+    @RequestMapping (
+            value = "/devicestructure/{mnemonicpath}",
+            method = RequestMethod.GET,
+            produces = {"application/json"})
+    public List<NameElement> readNamesDeviceStructure(
+            @PathVariable("mnemonicpath") String mnemonicpath,
+            @RequestParam(required = false) FieldName orderBy,
+            @RequestParam(required = false) Boolean isAsc,
+            @RequestParam(required = false) Integer offset,
+            @RequestParam(required = false) Integer limit);
+
+    /**
+     * Find history for name by uuid (exact match).
+     * Return list of name elements.
+     *
+     * @param uuid uuid
+     * @param orderBy order by
+     * @param isAsc is ascending
+     * @param offset offset
+     * @param limit limit
+     * @return list of name elements
+     */
+    @RequestMapping (
+            value = "/history/{uuid}",
+            method = RequestMethod.GET,
+            produces = {"application/json"})
+    public List<NameElement> readNamesHistory(
+            @PathVariable("uuid") String uuid,
+            @RequestParam(required = false) FieldName orderBy,
+            @RequestParam(required = false) Boolean isAsc,
+            @RequestParam(required = false) Integer offset,
+            @RequestParam(required = false) Integer limit);
+
+    // ----------------------------------------------------------------------------------------------------
+
+    /**
+     * Return name equivalence for name.
+     *
+     * @param name name
+     * @return name equivalence
+     */
+    @RequestMapping (
+            value = "/equivalence/{name}",
+            method = RequestMethod.GET)
+    public String equivalenceName(
+            @PathVariable("name") String name);
+
+    /**
+     * Return if name exists (exact match).
+     *
+     * <p>
+     * Returned object has three fields (response, message, details).
+     * <ul>
+     * <li>response: boolean (true/false)</li>
+     * <li>message: reason, if method fails</li>
+     * <li>details: details, if method fails</li>
+     * </ul>
+     * </p>
+     *
+     * @param name name
+     * @return if name exists
+     */
+    @RequestMapping (
+            value = "/exists/{name}",
+            method = RequestMethod.GET,
+            produces = {"application/json"})
+    public ResponseEntity<ResponseBoolean> existsName(
+            @PathVariable("name") String name);
+
+    /**
+     * Return if name is legacy name.
+     * A name is considered legacy name if one or more of its parents is deleted.
+     *
+     * <p>
+     * Returned object has three fields (response, message, details).
+     * <ul>
+     * <li>response: boolean (true/false)</li>
+     * <li>message: reason, if method fails</li>
+     * <li>details: details, if method fails</li>
+     * </ul>
+     * </p>
+     *
+     * @param name name
+     * @return if name is legacy name
+     */
+    @RequestMapping (
+            value = "/islegacy/{name}",
+            method = RequestMethod.GET,
+            produces = {"application/json"})
+    public ResponseEntity<ResponseBoolean> isLegacyName(
+            @PathVariable("name") String name);
+
+    /**
+     * Return if name is valid to create.
+     * Method answers question 'would it be ok to create given name?'.
+     *
+     * <p>
+     * Returned object has three fields (response, message, details).
+     * <ul>
+     * <li>response: boolean (true/false)</li>
+     * <li>message: reason, if method fails</li>
+     * <li>details: details, if method fails</li>
+     * </ul>
+     * </p>
+     *
+     * @param name name
+     * @return if name is valid to create
+     */
+    @RequestMapping (
+            value = "/isvalidtocreate/{name}",
+            method = RequestMethod.GET,
+            produces = {"application/json"})
+    public ResponseEntity<ResponseBoolean> isValidToCreateName(
+            @PathVariable("name") String name);
+
+    // ----------------------------------------------------------------------------------------------------
+
+    /**
+     * Return if name elements are valid to create.
+     * If names are valid to create, successful create of names can be expected.
+     *
+     * <p>
+     * Returned object has four fields (message, details, response, responses).
+     * <ul>
+     * <li>message:   reason, if method fails</li>
+     * <li>details:   details, if method fails</li>
+     * <li>response:  boolean (true/false), overall result of method</li>
+     * <li>responses: list of response objects (with fields reason, details, response), one for each input element</li>
+     * </ul>
+     * </p>
+     *
+     * @param nameElements name elements
+     * @return if list of name elements is valid to create
+     */
+    @RequestMapping (
+            value = "/validatecreate",
+            method = RequestMethod.GET,
+            produces = {"application/json"},
+            consumes = {"application/json"})
+    public ResponseEntity<ResponseBooleanList> validateNamesCreate(
+            @RequestBody(required = true) List<NameElement> nameElements);
+
+    /**
+     * Return if name elements are valid to update.
+     * If names are valid to update, successful update of names can be expected.
+     *
+     * <p>
+     * Returned object has four fields (message, details, response, responses).
+     * <ul>
+     * <li>message:   reason, if method fails</li>
+     * <li>details:   details, if method fails</li>
+     * <li>response:  boolean (true/false), overall result of method</li>
+     * <li>responses: list of response objects (with fields reason, details, response), one for each input element</li>
+     * </ul>
+     * </p>
+     *
+     * @param nameElements name elements
+     * @return if list of name elements is valid to update
+     */
+    @RequestMapping (
+            value = "/validateupdate",
+            method = RequestMethod.GET,
+            produces = {"application/json"},
+            consumes = {"application/json"})
+    public ResponseEntity<ResponseBooleanList> validateNamesUpdate(
+            @RequestBody(required = true) List<NameElement> nameElements);
+
+    /**
+     * Return if name elements are valid to delete.
+     * If names are valid to update, successful delete of names can be expected.
+     *
+     * <p>
+     * Returned object has four fields (message, details, response, responses).
+     * <ul>
+     * <li>message:   reason, if method fails</li>
+     * <li>details:   details, if method fails</li>
+     * <li>response:  boolean (true/false), overall result of method</li>
+     * <li>responses: list of response objects (with fields reason, details, response), one for each input element</li>
+     * </ul>
+     * </p>
+     *
+     * @param nameElements name elements
+     * @return if list of name elements is valid to delete
+     */
+    @RequestMapping (
+            value = "/validatedelete",
+            method = RequestMethod.GET,
+            produces = {"application/json"},
+            consumes = {"application/json"})
+    public ResponseEntity<ResponseBooleanList> validateNamesDelete(
+            @RequestBody(required = true) List<NameElement> nameElements);
+
+    // ----------------------------------------------------------------------------------------------------
+
+    /**
+     * Update names by list of name elements.
+     * Returns list of updated name elements.
+     *
+     * @param nameElements name elements
+     * @return updated name elements
+     */
+    @RequestMapping (
+            method = RequestMethod.PUT,
+            produces = {"application/json"},
+            consumes = {"application/json"})
+    @PutMapping
+    public List<NameElement> updateNames(
+            @RequestBody(required = true) List<NameElement> nameElements);
+
+    // ----------------------------------------------------------------------------------------------------
+
+    /**
+     * Delete names by list of name elements.
+     * Returns list of deleted name elements.
+     *
+     * @param uuid uuid
+     * @return deleted name elements
+     */
+    @RequestMapping (
+            method = RequestMethod.DELETE,
+            produces = {"application/json"},
+            consumes = {"application/json"})
+    public List<NameElement> deleteNames(
+            @RequestBody(required = true) List<NameElement> nameElements);
+
+}
diff --git a/src/main/java/org/openepics/names/rest/api/v1/IStructures.java b/src/main/java/org/openepics/names/rest/api/v1/IStructures.java
new file mode 100644
index 0000000000000000000000000000000000000000..6279bfb9d0e29f5d1f3fbd3127de80f59fa65546
--- /dev/null
+++ b/src/main/java/org/openepics/names/rest/api/v1/IStructures.java
@@ -0,0 +1,555 @@
+/*
+ * Copyright (C) 2021 European Spallation Source ERIC.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+package org.openepics.names.rest.api.v1;
+
+import java.util.List;
+
+import org.openepics.names.rest.beans.FieldStructure;
+import org.openepics.names.rest.beans.Status;
+import org.openepics.names.rest.beans.StructureElement;
+import org.openepics.names.rest.beans.Type;
+import org.openepics.names.util.response.ResponseBoolean;
+import org.openepics.names.util.response.ResponseBooleanList;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * This part of REST API provides structures data for Naming application.
+ *
+ * @author Lars Johansson
+ */
+@RequestMapping("/api/v1/structures")
+public interface IStructures {
+
+    /*
+       Type             - SYSTEMGROUP, SYSTEM, SUBSYSTEM, DISCIPLINE, DEVICEGROUP, DEVICETYPE
+       Status           - APPROVED, ARCHIVED, CANCELLED, PENDING, REJECTED
+       FieldStructure   - UUID, PARENT, NAME, MNEMONIC, MNEMONICEQUIVALENCE, MNEMONICPATH, DESCRIPTION
+
+       StructureElement - type            (Type)
+                          uuid            (UUID)
+                          parent          (UUID)
+                          name            (String)
+                          mnemonic        (String)
+                          mnemonicpath    (String)
+                          level           (Integer)
+                          description     (String)
+                          status          (Status)
+                          latest          (Boolean)
+                          deleted         (Boolean)
+                          when            (Date)
+                          who             (String)
+                          comment         (String)
+
+       authentication/authorization
+           3 levels - no, user, administrator
+               no            - read
+               user          - create, update, delete
+               administrator - approve, reject (, checkdevices)
+
+       mnemonic path for structure includes all levels of mnemonics
+
+       Methods
+           create    POST   /structures                                       - createStructures               (List<StructureElement>)
+           ----------------------------------------------------------------------------------------------------
+           read      GET    /structures/{type}                                - readStructures                 (Type, Status[], Boolean, FieldStructure[], String[], FieldStructure, Boolean, Integer, Integer)
+           read      GET    /structures/children/{type}/{uuid}                - readStructuresChildren         (Type, String, FieldStructure, Boolean, Integer, Integer)
+           read      GET    /structures/mnemonic/{mnemonic}                   - readStructuresMnemonic         (String, FieldStructure, Boolean, Integer, Integer, FieldStructure, Boolean, Integer, Integer)
+           read      GET    /structures/mnemonicpath/{mnemonicpath}           - readStructuresMnemonicpath     (String, FieldStructure, Boolean, Integer, Integer, FieldStructure, Boolean, Integer, Integer)
+           read      GET    /structures/history/{uuid}                        - readStructuresHistory          (String, Type, FieldStructure, Boolean, Integer, Integer)
+           ----------------------------------------------------------------------------------------------------
+           read      GET    /structures/equivalence/{mnemonic}                - equivalenceMnemonic            (String)
+           read      GET    /structures/exists/{type}/{mnemonic}              - existsStructure                (Type, String)
+           read      GET    /structures/isvalidtocreate/{type}/{mnemonicpath} - isValidToCreateStructure       (Type, String)
+           ----------------------------------------------------------------------------------------------------
+           read      GET    /structures/validatecreate                        - validateStructuresCreate       (List<StructureElement>)
+           read      GET    /structures/validateupdate                        - validateStructuresUpdate       (List<StructureElement>)
+           read      GET    /structures/validatedelete                        - validateStructuresDelete       (List<StructureElement>)
+           read      GET    /structures/validateapprove                       - validateStructuresApprove      (List<StructureElement>)
+           read      GET    /structures/validatecancel                        - validateStructuresCancel       (List<StructureElement>)
+           read      GET    /structures/validatereject                        - validateStructuresReject       (List<StructureElement>)
+           ----------------------------------------------------------------------------------------------------
+           update    PUT    /structures                                       - updateStructures               (List<StructureElement>)
+           ----------------------------------------------------------------------------------------------------
+           delete    DELETE /structures                                       - deleteStructures               (List<StructureElement>)
+           ----------------------------------------------------------------------------------------------------
+           update    PATCH  /structures/approve                               - approveStructures              (List<StructureElement>)
+           update    PATCH  /structures/cancel                                - cancelStructures               (List<StructureElement>)
+           update    PATCH  /structures/reject                                - rejectStructures               (List<StructureElement>)
+     */
+
+    /**
+     * Create (propose) structures by list of structure elements.
+     * Return list of created structure elements (proposals).
+     *
+     * <p>
+     * StructureElement attributes required:
+     * <ul>
+     * <li>type</li>
+     * <li>parent (System, Subsystem, DeviceGroup, DeviceType)</li>
+     * <li>name</li>
+     * <li>mnemonic (System, Subsystem, Discipline, DeviceType)(may be set for SystemGroup, not allowed for DeviceGroup)</li>
+     * <li>description</li>
+     * <li>comment</li>
+     * </ul>
+     * </p>
+     *
+     * @param structureElements structure elements
+     * @return structure elements for created structures (proposals)
+     */
+    @RequestMapping (
+            method = RequestMethod.POST,
+            produces = {"application/json"},
+            consumes = {"application/json"})
+    public List<StructureElement> createStructures(
+            @RequestBody(required = true) List<StructureElement> structureElements);
+
+    // ----------------------------------------------------------------------------------------------------
+
+    /**
+     * Find valid structures (search).
+     * Return list of structure elements.
+     *
+     * @param type type
+     * @param statuses statuses
+     * @param deleted deleted
+     * @param queryFields query fields
+     * @param queryValues query values
+     * @param orderBy order by
+     * @param isAsc is ascending
+     * @param offset offset
+     * @param limit limit
+     * @return list of structure elements
+     */
+    @RequestMapping (
+            value = "/{type}",
+            method = RequestMethod.GET,
+            produces = {"application/json"})
+    @GetMapping
+    public List<StructureElement> readStructures(
+            @PathVariable("type") Type type,
+            @RequestParam(required = false) Status[] statuses,
+            @RequestParam(required = false) Boolean deleted,
+            @RequestParam(required = false) FieldStructure[] queryFields,
+            @RequestParam(required = false) String[] queryValues,
+            @RequestParam(required = false) FieldStructure orderBy,
+            @RequestParam(required = false) Boolean isAsc,
+            @RequestParam(required = false) Integer offset,
+            @RequestParam(required = false) Integer limit);
+
+    /**
+     * Find valid children structures by type and parent uuid (exact match).
+     *
+     * @param type type
+     * @param uuid uuid
+     * @param orderBy order by
+     * @param isAsc is ascending
+     * @param offset offset
+     * @param limit limit
+     * @return list of structure elements
+     */
+    @RequestMapping (
+            value = "/children/{type}/{uuid}",
+            method = RequestMethod.GET,
+            produces = {"application/json"})
+    @GetMapping
+    public List<StructureElement> readStructuresChildren(
+            @PathVariable("type") Type type,
+            @PathVariable("uuid") String uuid,
+            @RequestParam(required = false) FieldStructure orderBy,
+            @RequestParam(required = false) Boolean isAsc,
+            @RequestParam(required = false) Integer offset,
+            @RequestParam(required = false) Integer limit);
+
+    /**
+     * Find valid structures by mnemonic (search).
+     * Return list of structure elements.
+     *
+     * @param mnemonic mnemonic
+     * @param orderBy order by
+     * @param isAsc is ascending
+     * @param offset offset
+     * @param limit limit
+     * @return list of structure elements
+     */
+    @RequestMapping (
+            value = "/mnemonic/{mnemonic}",
+            method = RequestMethod.GET,
+            produces = {"application/json"})
+    @GetMapping
+    public List<StructureElement> readStructuresMnemonic(
+            @PathVariable("mnemonic") String mnemonic,
+            @RequestParam(required = false) FieldStructure orderBy,
+            @RequestParam(required = false) Boolean isAsc,
+            @RequestParam(required = false) Integer offset,
+            @RequestParam(required = false) Integer limit);
+
+    /**
+     * Find valid structures by mnemonic path (search).
+     * Return list of structure elements.
+     *
+     * @param mnemonicpath mnemonic path
+     * @param orderBy order by
+     * @param isAsc is ascending
+     * @param offset offset
+     * @param limit limit
+     * @return list of structure elements
+     */
+    @RequestMapping (
+            value = "/mnemonicpath/{mnemonicpath}",
+            method = RequestMethod.GET,
+            produces = {"application/json"})
+    @GetMapping
+    public List<StructureElement> readStructuresMnemonicpath(
+            @PathVariable("mnemonicpath") String mnemonicpath,
+            @RequestParam(required = false) FieldStructure orderBy,
+            @RequestParam(required = false) Boolean isAsc,
+            @RequestParam(required = false) Integer offset,
+            @RequestParam(required = false) Integer limit);
+
+    /**
+     * Find history for structure by uuid (exact match).
+     * Return list of structure elements.
+     *
+     * @param uuid uuid
+     * @param type type
+     * @param orderBy order by
+     * @param isAsc is ascending
+     * @param offset offset
+     * @param limit limit
+     * @return list of structure elements
+     */
+    @RequestMapping (
+            value = "/history/{uuid}",
+            method = RequestMethod.GET,
+            produces = {"application/json"})
+    public List<StructureElement> readStructuresHistory(
+            @PathVariable("uuid") String uuid,
+            @RequestParam(required = false) Type type,
+            @RequestParam(required = false) FieldStructure orderBy,
+            @RequestParam(required = false) Boolean isAsc,
+            @RequestParam(required = false) Integer offset,
+            @RequestParam(required = false) Integer limit);
+
+    // ----------------------------------------------------------------------------------------------------
+
+    /**
+     * Return mnemonic equivalence for mnemonic.
+     *
+     * @param mnemonic mnemonic
+     * @return mnemonic equivalence
+     */
+    @RequestMapping (
+            value = "/equivalence/{mnemonic}",
+            method = RequestMethod.GET)
+    public String equivalenceMnemonic(
+            @PathVariable("mnemonic") String mnemonic);
+
+    /**
+     * Return if mnemonic exists in structure (exact match).
+     *
+     * <p>
+     * Returned object has three fields (response, message, details).
+     * <ul>
+     * <li>response: boolean (true/false)</li>
+     * <li>message: reason, if method fails</li>
+     * <li>details: details, if method fails</li>
+     * </ul>
+     * </p>
+     *
+     * @param type type
+     * @param mnemonic mnemonic
+     * @return if mnemonic exists in structure
+     */
+    @RequestMapping (
+            value = "/exists/{type}/{mnemonic}",
+            method = RequestMethod.GET)
+    public ResponseEntity<ResponseBoolean> existsStructure(
+            @PathVariable("type") Type type,
+            @PathVariable("mnemonic") String mnemonic);
+
+    /**
+     * Return if mnemonic path is valid to create in structure.
+     * Method answers question 'would it be ok to create given mnemonic path in structure?'.
+     *
+     * <p>
+     * Note that method can not fully answer question posed above. One reason is that system group
+     * may have empty mnemonic. Another reason is that device groups has no mnemonic and is between
+     * discipline and device type. Thus it can not be found which discipline (uuid-wise) that
+     * a device type belongs.
+     * </p>
+     *
+     * <p>
+     * Returned object has three fields (response, message, details).
+     * <ul>
+     * <li>response: boolean (true/false)</li>
+     * <li>message: reason, if method fails</li>
+     * <li>details: details, if method fails</li>
+     * </ul>
+     * </p>
+     *
+     * @param type type
+     * @param mnemonicpath mnemonic path
+     * @return if mnemonic path is valid to create in structure
+     */
+    @RequestMapping (
+            value = "/isvalidtocreate/{type}/{mnemonicpath}",
+            method = RequestMethod.GET,
+            produces = {"application/json"})
+    public ResponseEntity<ResponseBoolean> isValidToCreateStructure(
+            @PathVariable("type") Type type,
+            @PathVariable("mnemonicpath") String mnemonicpath);
+
+    // ----------------------------------------------------------------------------------------------------
+
+    /**
+     * Return if structure elements are valid to create (propose).
+     * If structure elements are valid to create, successful create of structures can be expected.
+     *
+     * <p>
+     * Returned object has four fields (message, details, response, responses).
+     * <ul>
+     * <li>message:   reason, if method fails</li>
+     * <li>details:   details, if method fails</li>
+     * <li>response:  boolean (true/false), overall result of method</li>
+     * <li>responses: list of response objects (with fields reason, details, response), one for each input element</li>
+     * </ul>
+     * </p>
+     *
+     * @param structureElements structure elements
+     * @return if list of structure elements is valid to create (propose)
+     */
+    @RequestMapping (
+            value = "/validatecreate",
+            method = RequestMethod.GET,
+            produces = {"application/json"},
+            consumes = {"application/json"})
+    public ResponseEntity<ResponseBooleanList> validateStructuresCreate(
+            @RequestBody(required = true) List<StructureElement> structureElements);
+
+    /**
+     * Return if structure elements are valid to update (propose).
+     * If structure elements are valid to update, successful update of structures can be expected.
+     *
+     * <p>
+     * Returned object has four fields (message, details, response, responses).
+     * <ul>
+     * <li>message:   reason, if method fails</li>
+     * <li>details:   details, if method fails</li>
+     * <li>response:  boolean (true/false), overall result of method</li>
+     * <li>responses: list of response objects (with fields reason, details, response), one for each input element</li>
+     * </ul>
+     * </p>
+     *
+     * @param structureElements structure elements
+     * @return if list of structure elements is valid to update (propose)
+     */
+    @RequestMapping (
+            value = "/validateupdate",
+            method = RequestMethod.GET,
+            produces = {"application/json"},
+            consumes = {"application/json"})
+    public ResponseEntity<ResponseBooleanList> validateStructuresUpdate(
+            @RequestBody(required = true) List<StructureElement> structureElements);
+
+    /**
+     * Return if structure elements are valid to delete (propose).
+     * If structure elements are valid to delete, successful delete of structures can be expected.
+     *
+     * <p>
+     * Returned object has four fields (message, details, response, responses).
+     * <ul>
+     * <li>message:   reason, if method fails</li>
+     * <li>details:   details, if method fails</li>
+     * <li>response:  boolean (true/false), overall result of method</li>
+     * <li>responses: list of response objects (with fields reason, details, response), one for each input element</li>
+     * </ul>
+     * </p>
+     *
+     * @param structureElements structure elements
+     * @return if list of structure elements is valid to delete (propose)
+     */
+    @RequestMapping (
+            value = "/validatedelete",
+            method = RequestMethod.GET,
+            produces = {"application/json"},
+            consumes = {"application/json"})
+    public ResponseEntity<ResponseBooleanList> validateStructuresDelete(
+            @RequestBody(required = true) List<StructureElement> structureElements);
+
+    /**
+     * Return if structure elements are valid to approve.
+     * If structure elements are valid to approve, successful approve of structures can be expected.
+     *
+     * <p>
+     * Returned object has four fields (message, details, response, responses).
+     * <ul>
+     * <li>message:   reason, if method fails</li>
+     * <li>details:   details, if method fails</li>
+     * <li>response:  boolean (true/false), overall result of method</li>
+     * <li>responses: list of response objects (with fields reason, details, response), one for each input element</li>
+     * </ul>
+     * </p>
+     *
+     * @param structureElements structure elements
+     * @return if list of structure elements is valid to approve
+     */
+    @RequestMapping (
+            value = "/validateapprove",
+            method = RequestMethod.GET,
+            produces = {"application/json"},
+            consumes = {"application/json"})
+    public ResponseEntity<ResponseBooleanList> validateStructuresApprove(
+            @RequestBody(required = true) List<StructureElement> structureElements);
+
+    /**
+     * Return if structure elements are valid to cancel.
+     * If structure elements are valid to cancel, successful cancel of structures can be expected.
+     *
+     * <p>
+     * Returned object has four fields (message, details, response, responses).
+     * <ul>
+     * <li>message:   reason, if method fails</li>
+     * <li>details:   details, if method fails</li>
+     * <li>response:  boolean (true/false), overall result of method</li>
+     * <li>responses: list of response objects (with fields reason, details, response), one for each input element</li>
+     * </ul>
+     * </p>
+     *
+     * @param structureElements structure elements
+     * @return if list of structure elements is valid to cancel
+     */
+    @RequestMapping (
+            value = "/validatecancel",
+            method = RequestMethod.GET,
+            produces = {"application/json"},
+            consumes = {"application/json"})
+    public ResponseEntity<ResponseBooleanList> validateStructuresCancel(
+            @RequestBody(required = true) List<StructureElement> structureElements);
+
+    /**
+     * Return if structure elements are valid to reject.
+     * If structure elements are valid to reject, successful reject of structures can be expected.
+     *
+     * <p>
+     * Returned object has four fields (message, details, response, responses).
+     * <ul>
+     * <li>message:   reason, if method fails</li>
+     * <li>details:   details, if method fails</li>
+     * <li>response:  boolean (true/false), overall result of method</li>
+     * <li>responses: list of response objects (with fields reason, details, response), one for each input element</li>
+     * </ul>
+     * </p>
+     *
+     * @param structureElements structure elements
+     * @return if list of structure elements is valid to reject
+     */
+    @RequestMapping (
+            value = "/validatereject",
+            method = RequestMethod.GET,
+            produces = {"application/json"},
+            consumes = {"application/json"})
+    public ResponseEntity<ResponseBooleanList> validateStructuresReject(
+            @RequestBody(required = true) List<StructureElement> structureElements);
+
+    // ----------------------------------------------------------------------------------------------------
+
+    /**
+     * Update (propose) structures by list of structure elements.
+     * Return list of updated structure elements (proposals).
+     *
+     * @param structureElements structure elements
+     * @return structure elements for updated structures (proposals)
+     */
+    @RequestMapping (
+            method = RequestMethod.PUT,
+            produces = {"application/json"},
+            consumes = {"application/json"})
+    public List<StructureElement> updateStructures(
+            @RequestBody(required = true) List<StructureElement> structureElements);
+
+    // ----------------------------------------------------------------------------------------------------
+
+    /**
+     * Delete (propose) structures by list of structure elements.
+     * Return list of deleted structure elements (proposals).
+     *
+     * @param structureElements structure elements
+     * @return structure elements for deleted structures (proposals)
+     */
+    @RequestMapping (
+            method = RequestMethod.DELETE,
+            produces = {"application/json"},
+            consumes = {"application/json"})
+    public List<StructureElement> deleteStructures(
+            @RequestBody(required = true) List<StructureElement> structureElements);
+
+    // ----------------------------------------------------------------------------------------------------
+
+    /**
+     * Approve structures (proposals) by list of structure elements.
+     * Return list of approved structure elements.
+     *
+     * @param structureElements structure elements
+     * @return structure elements for approved structures
+     */
+    @RequestMapping (
+            value = "/approve",
+            method = RequestMethod.PATCH,
+            produces = {"application/json"},
+            consumes = {"application/json"})
+    public List<StructureElement> approveStructures(
+            @RequestBody(required = true) List<StructureElement> structureElements);
+
+    /**
+     * Cancel structures (proposals) by list of structure elements.
+     * Return list of cancelled structure elements.
+     *
+     * @param structureElements structure elements
+     * @return structure elements for cancelled structures
+     */
+    @RequestMapping (
+            value = "/cancel",
+            method = RequestMethod.PATCH,
+            produces = {"application/json"},
+            consumes = {"application/json"})
+    public List<StructureElement> cancelStructures(
+            @RequestBody(required = true) List<StructureElement> structureElements);
+
+    /**
+     * Reject structures (proposals) by list of structure elements.
+     * Return list of rejected structure elements.
+     *
+     * @param structureElements structure elements
+     * @return structure elements for rejected structures
+     */
+    @RequestMapping (
+            value = "/reject",
+            method = RequestMethod.PATCH,
+            produces = {"application/json"},
+            consumes = {"application/json"})
+    public List<StructureElement> rejectStructures(
+            @RequestBody(required = true) List<StructureElement> structureElements);
+
+}
diff --git a/src/main/java/org/openepics/names/rest/beans/FieldName.java b/src/main/java/org/openepics/names/rest/beans/FieldName.java
new file mode 100644
index 0000000000000000000000000000000000000000..5ed6b831d6497781455a5602f3c48e77b9753aa3
--- /dev/null
+++ b/src/main/java/org/openepics/names/rest/beans/FieldName.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 European Spallation Source ERIC.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+package org.openepics.names.rest.beans;
+
+/**
+ * This enum  represents fields for name in beans and for communication.
+ *
+ * @author Lars Johansson
+ */
+public enum FieldName {
+
+    UUID,
+    NAME,
+    NAMEEQUIVALENCE,
+    SYSTEMSTRUCTURE,
+    DEVICESTRUCTURE,
+    DESCRIPTION;
+
+}
diff --git a/src/main/java/org/openepics/names/rest/beans/FieldStructure.java b/src/main/java/org/openepics/names/rest/beans/FieldStructure.java
new file mode 100644
index 0000000000000000000000000000000000000000..2958fd8df1f83d49856eebc59e5a02ef2959ad0a
--- /dev/null
+++ b/src/main/java/org/openepics/names/rest/beans/FieldStructure.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 European Spallation Source ERIC.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+package org.openepics.names.rest.beans;
+
+/**
+ * This enum  represents fields for structures in beans and for communication.
+ *
+ * @author Lars Johansson
+ */
+public enum FieldStructure {
+
+    UUID,
+    PARENT,
+    NAME,
+    MNEMONIC,
+    MNEMONICEQUIVALENCE,
+    MNEMONICPATH,
+    DESCRIPTION;
+
+}
diff --git a/src/main/java/org/openepics/names/rest/beans/NameElement.java b/src/main/java/org/openepics/names/rest/beans/NameElement.java
new file mode 100644
index 0000000000000000000000000000000000000000..0505cb06c02a3ec6540493e609f18fba401a752b
--- /dev/null
+++ b/src/main/java/org/openepics/names/rest/beans/NameElement.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2021 European Spallation Source ERIC.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+package org.openepics.names.rest.beans;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.UUID;
+
+/**
+ * Bean (data transfer object) for communication and (json, xml) serialization.
+ *
+ * @author Lars Johansson
+ */
+public class NameElement extends NameStructureElement implements Serializable {
+
+    /**
+     *
+     */
+    private static final long serialVersionUID = -5998490678202969520L;
+
+    private UUID systemgroup;
+    private UUID system;
+    private UUID subsystem;
+    private UUID devicetype;
+    private String systemstructure;
+    private String devicestructure;
+    private String index;
+    private String name;
+
+    /**
+     * Public constructor.
+     */
+    public NameElement () {
+    }
+
+    /**
+     * Public constructor.
+     *
+     * @param uuid uuid
+     * @param systemgroup system group
+     * @param system system
+     * @param subsystem subsystem
+     * @param devicetype device type
+     * @param systemstructure system structure mnemonic path
+     * @param devicestructure device structure mnemonic path
+     * @param index instance index
+     * @param name name
+     * @param description description
+     * @param status status
+     * @param latest latest
+     * @param deleted deleted
+     * @param when when
+     * @param who who
+     * @param comment comment
+     */
+    public NameElement (
+            UUID uuid,
+            UUID systemgroup, UUID system, UUID subsystem, UUID devicetype,
+            String systemstructure, String devicestructure,
+            String index, String name,
+            String description, Status status, Boolean latest, Boolean deleted,
+            Date when, String who, String comment) {
+
+        super(uuid, description, status, latest, deleted, when, who, comment);
+
+        setSystemgroup(systemgroup);
+        setSystem(system);
+        setSubsystem(subsystem);
+        setDevicetype(devicetype);
+        setSystemstructure(systemstructure);
+        setDevicestructure(devicestructure);
+        setIndex(index);
+        setName(name);
+    }
+
+    public UUID getSystemgroup() {
+        return systemgroup;
+    }
+    public void setSystemgroup(UUID systemgroup) {
+        this.systemgroup = systemgroup;
+    }
+    public UUID getSystem() {
+        return system;
+    }
+    public void setSystem(UUID system) {
+        this.system = system;
+    }
+    public UUID getSubsystem() {
+        return subsystem;
+    }
+    public void setSubsystem(UUID subsystem) {
+        this.subsystem = subsystem;
+    }
+    public UUID getDevicetype() {
+        return devicetype;
+    }
+    public void setDevicetype(UUID devicetype) {
+        this.devicetype = devicetype;
+    }
+    public String getSystemstructure() {
+        return systemstructure;
+    }
+    public void setSystemstructure(String systemstructure) {
+        this.systemstructure = systemstructure;
+    }
+    public String getDevicestructure() {
+        return devicestructure;
+    }
+    public void setDevicestructure(String devicestructure) {
+        this.devicestructure = devicestructure;
+    }
+    public String getIndex() {
+        return index;
+    }
+    public void setIndex(String index) {
+        this.index = index;
+    }
+    public String getName() {
+        return name;
+    }
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+
+        return equals ((NameElement) obj);
+    }
+
+    public boolean equals(NameElement other) {
+        if (other == null)
+            return false;
+
+        if (!super.equals(other)) {
+            return false;
+        }
+
+        if (getSystemgroup() == null) {
+            if (other.getSystemgroup() != null)
+                return false;
+        } else if (!getSystemgroup().equals(other.getSystemgroup()))
+            return false;
+        if (getSystem() == null) {
+            if (other.getSystem() != null)
+                return false;
+        } else if (!getSystem().equals(other.getSystem()))
+            return false;
+        if (getSubsystem() == null) {
+            if (other.getSubsystem() != null)
+                return false;
+        } else if (!getSubsystem().equals(other.getSubsystem()))
+            return false;
+        if (getDevicetype() == null) {
+            if (other.getDevicetype() != null)
+                return false;
+        } else if (!getDevicetype().equals(other.getDevicetype()))
+            return false;
+        if (getSystemstructure() == null) {
+            if (other.getSystemstructure() != null)
+                return false;
+        } else if (!getSystemstructure().equals(other.getSystemstructure()))
+            return false;
+        if (getDevicestructure() == null) {
+            if (other.getDevicestructure() != null)
+                return false;
+        } else if (!getDevicestructure().equals(other.getDevicestructure()))
+            return false;
+        if (getIndex() == null) {
+            if (other.getIndex() != null)
+                return false;
+        } else if (!getIndex().equals(other.getIndex()))
+            return false;
+        if (getName() == null) {
+            if (other.getName() != null)
+                return false;
+        } else if (!getName().equals(other.getName()))
+            return false;
+
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("{");
+        sb.append("\"uuid\": "              + getUuid());
+        sb.append(", \"systemgroup\": "     + getSystemgroup());
+        sb.append(", \"system\": "          + getSystem());
+        sb.append(", \"subsystem\": "       + getSubsystem());
+        sb.append(", \"devicetype\": "      + getDevicetype());
+        sb.append(", \"systemstructure\": " + getSystemstructure());
+        sb.append(", \"devicestructure\": " + getDevicestructure());
+        sb.append(", \"index\": "           + getIndex());
+        sb.append(", \"name\": "            + getName());
+        sb.append(", \"description\": "     + getDescription());
+        sb.append(", \"status\": "          + getStatus());
+        sb.append(", \"latest\": "          + isLatest());
+        sb.append(", \"deleted\": "         + isDeleted());
+        sb.append(", \"when\": "            + getWhen());
+        sb.append(", \"who\": "             + getWho());
+        sb.append(", \"comment\": "         + getComment());
+        sb.append("}");
+        return sb.toString();
+    }
+
+    public String toStringSimple() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("{");
+        sb.append("\"uuid\": "              + getUuid());
+        sb.append(", \"name\": "            + getName());
+        sb.append(", \"status\": "          + getStatus());
+        sb.append(", \"latest\": "          + isLatest());
+        sb.append(", \"deleted\": "         + isDeleted());
+        sb.append("}");
+        return sb.toString();
+    }
+
+}
diff --git a/src/main/java/org/openepics/names/rest/beans/NameStructureElement.java b/src/main/java/org/openepics/names/rest/beans/NameStructureElement.java
new file mode 100644
index 0000000000000000000000000000000000000000..b995fbd2e679ab8dd4b77e2ebcd9aa8a58b95d3d
--- /dev/null
+++ b/src/main/java/org/openepics/names/rest/beans/NameStructureElement.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2021 European Spallation Source ERIC.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+package org.openepics.names.rest.beans;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.UUID;
+
+/**
+ * Bean (data transfer object) for communication and (json, xml) serialization.
+ *
+ * @author Lars Johansson
+ */
+public abstract class NameStructureElement implements Serializable {
+
+    /**
+     *
+     */
+    private static final long serialVersionUID = -1124618368080704934L;
+
+    private UUID uuid;
+    private String description;
+    private Status status;
+    private Boolean latest;
+    private Boolean deleted;
+    private Date when;
+    private String who;
+    private String comment;
+
+    /**
+     * Public constructor.
+     */
+    public NameStructureElement() {
+    }
+
+    /**
+     * Public constructor.
+     *
+     * @param uuid uuid
+     * @param description description
+     * @param status status
+     * @param latest latest
+     * @param deleted deleted
+     * @param when when
+     * @param who who
+     * @param comment comment
+     */
+    public NameStructureElement(
+            UUID uuid,
+            String description,
+            Status status, Boolean latest, Boolean deleted,
+            Date when, String who, String comment) {
+
+        setUuid(uuid);
+        setDescription(description);
+        setStatus(status);
+        setLatest(latest);
+        setDeleted(deleted);
+        setWhen(when);
+        setWho(who);
+        setComment(comment);
+    }
+
+    public UUID getUuid() {
+        return uuid;
+    }
+    public void setUuid(UUID uuid) {
+        this.uuid = uuid;
+    }
+    public String getDescription() {
+        return description;
+    }
+    public void setDescription(String description) {
+        this.description = description;
+    }
+    public Status getStatus() {
+        return status;
+    }
+    public void setStatus(Status status) {
+        this.status = status;
+    }
+    public Boolean isLatest() {
+        return latest;
+    }
+    public void setLatest(Boolean latest) {
+        this.latest = latest;
+    }
+    public Boolean isDeleted() {
+        return deleted;
+    }
+    public void setDeleted(Boolean deleted) {
+        this.deleted = deleted;
+    }
+    public Date getWhen() {
+        return when;
+    }
+    public void setWhen(Date when) {
+        this.when = when;
+    }
+    public String getWho() {
+        return who;
+    }
+    public void setWho(String who) {
+        this.who = who;
+    }
+    public String getComment() {
+        return comment;
+    }
+    public void setComment(String comment) {
+        this.comment = comment;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+
+        return equals((NameStructureElement) obj);
+    }
+
+    public boolean equals(NameStructureElement other) {
+        if (other == null)
+            return false;
+
+        if (getUuid() == null) {
+            if (other.getUuid() != null)
+                return false;
+        } else if (!getUuid().equals(other.getUuid()))
+            return false;
+        if (getDescription() == null) {
+            if (other.getDescription() != null)
+                return false;
+        } else if (!getDescription().equals(other.getDescription()))
+            return false;
+        if (getStatus() == null) {
+            if (other.getStatus() != null)
+                return false;
+        } else if (!getStatus().equals(other.getStatus()))
+            return false;
+        if (isLatest() == null) {
+            if (other.isLatest() != null)
+                return false;
+        } else if (!isLatest().equals(other.isLatest()))
+            return false;
+        if (isDeleted() == null) {
+            if (other.isDeleted() != null)
+                return false;
+        } else if (!isDeleted().equals(other.isDeleted()))
+            return false;
+        if (getWhen() == null) {
+            if (other.getWhen() != null)
+                return false;
+        } else if (!getWhen().equals(other.getWhen()))
+            return false;
+        if (getWho() == null) {
+            if (other.getWho() != null)
+                return false;
+        } else if (!getWho().equals(other.getWho()))
+            return false;
+        if (getComment() == null) {
+            if (other.getComment() != null)
+                return false;
+        } else if (!getComment().equals(other.getComment()))
+            return false;
+
+        return true;
+    }
+
+}
diff --git a/src/main/java/org/openepics/names/rest/beans/StructureElement.java b/src/main/java/org/openepics/names/rest/beans/StructureElement.java
new file mode 100644
index 0000000000000000000000000000000000000000..7374afc0bfa7db7c3cea541db593bca360e00da2
--- /dev/null
+++ b/src/main/java/org/openepics/names/rest/beans/StructureElement.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2021 European Spallation Source ERIC.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+package org.openepics.names.rest.beans;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.UUID;
+
+/**
+ * Bean (data transfer object) for communication and (json, xml) serialization.
+ *
+ * @author Lars Johansson
+ */
+public class StructureElement extends NameStructureElement implements Serializable {
+
+    /**
+     *
+     */
+    private static final long serialVersionUID = -8892788697188691804L;
+
+    private Type type;
+    private UUID parent;
+    private String name;
+    private String mnemonic;
+    private String mnemonicpath;
+    private Integer level;
+
+    /**
+     * Public constructor.
+     */
+    public StructureElement() {
+    }
+
+    /**
+     * Public constructor.
+     *
+     * @param type type
+     * @param uuid uuid
+     * @param parent parent uuid
+     * @param name name
+     * @param mnemonic mnemonic
+     * @param mnemonicpath mnemonic path
+     * @param level level
+     * @param description description
+     * @param status status
+     * @param latest latest
+     * @param deleted deleted
+     * @param when when
+     * @param who who
+     * @param comment comment
+     */
+    public StructureElement(
+            Type type,
+            UUID uuid,
+            UUID parent,
+            String name, String mnemonic, String mnemonicpath, Integer level,
+            String description, Status status, Boolean latest, Boolean deleted,
+            Date when, String who, String comment) {
+
+        super(uuid, description, status, latest, deleted, when, who, comment);
+
+        setType(type);
+        setParent(parent);
+        setName(name);
+        setMnemonic(mnemonic);
+        setMnemonicpath(mnemonicpath);
+        setLevel(level);
+    }
+
+    public Type getType() {
+        return type;
+    }
+    public void setType(Type type) {
+        this.type = type;
+    }
+    public UUID getParent() {
+        return parent;
+    }
+    public void setParent(UUID parent) {
+        this.parent = parent;
+    }
+    public String getName() {
+        return name;
+    }
+    public void setName(String name) {
+        this.name = name;
+    }
+    public String getMnemonic() {
+        return mnemonic;
+    }
+    public void setMnemonic(String mnemonic) {
+        this.mnemonic = mnemonic;
+    }
+    public String getMnemonicpath() {
+        return mnemonicpath;
+    }
+    public void setMnemonicpath(String mnemonicpath) {
+        this.mnemonicpath = mnemonicpath;
+    }
+    public Integer getLevel() {
+        return level;
+    }
+    public void setLevel(Integer level) {
+        this.level = level;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+
+        return equals ((StructureElement) obj);
+    }
+
+    public boolean equals(StructureElement other) {
+        if (other == null)
+            return false;
+
+        if (!super.equals(other)) {
+            return false;
+        }
+
+        if (getType() == null) {
+            if (other.getType() != null)
+                return false;
+        } else if (!getType().equals(other.getType()))
+            return false;
+        if (getParent() == null) {
+            if (other.getParent() != null)
+                return false;
+        } else if (!getParent().equals(other.getParent()))
+            return false;
+        if (getName() == null) {
+            if (other.getName() != null)
+                return false;
+        } else if (!getName().equals(other.getName()))
+            return false;
+        if (getMnemonic() == null) {
+            if (other.getMnemonic() != null)
+                return false;
+        } else if (!getMnemonic().equals(other.getMnemonic()))
+            return false;
+        if (getMnemonicpath() == null) {
+            if (other.getMnemonicpath() != null)
+                return false;
+        } else if (!getMnemonicpath().equals(other.getMnemonicpath()))
+            return false;
+        if (getLevel() == null) {
+            if (other.getLevel() != null)
+                return false;
+        } else if (!getLevel().equals(other.getLevel()))
+            return false;
+
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("{");
+        sb.append("\"type\": "           + getType());
+        sb.append(", \"uuid\": "         + getUuid());
+        sb.append(", \"parent_uuid\": "  + getParent());
+        sb.append(", \"name\": "         + getName());
+        sb.append(", \"mnemonic\": "     + getMnemonic());
+        sb.append(", \"mnemonicpath\": " + getMnemonicpath());
+        sb.append(", \"level\": "        + getLevel());
+        sb.append(", \"description\": "  + getDescription());
+        sb.append(", \"status\": "       + getStatus());
+        sb.append(", \"latest\": "       + isLatest());
+        sb.append(", \"deleted\": "      + isDeleted());
+        sb.append(", \"when\": "         + getWhen());
+        sb.append(", \"who\": "          + getWho());
+        sb.append(", \"comment\": "      + getComment());
+        sb.append("}");
+        return sb.toString();
+    }
+
+    public String toStringSimple() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("{");
+        sb.append("\"type\": "           + getType());
+        sb.append(", \"uuid\": "         + getUuid());
+        sb.append(", \"mnemonic\": "     + getMnemonic());
+        sb.append(", \"status\": "       + getStatus());
+        sb.append(", \"latest\": "       + isLatest());
+        sb.append(", \"deleted\": "      + isDeleted());
+        sb.append("}");
+        return sb.toString();
+    }
+
+}
diff --git a/src/main/java/org/openepics/names/rest/beans/Type.java b/src/main/java/org/openepics/names/rest/beans/Type.java
new file mode 100644
index 0000000000000000000000000000000000000000..fad17a5e23d5a117c72dedc8b0f813a8f8845806
--- /dev/null
+++ b/src/main/java/org/openepics/names/rest/beans/Type.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 European Spallation Source ERIC.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+package org.openepics.names.rest.beans;
+
+/**
+ * This enum represents types for structures data in beans and for communication.
+ *
+ * @author Lars Johansson
+ */
+public enum Type {
+
+    SYSTEMGROUP,
+    SYSTEM,
+    SUBSYSTEM,
+    DISCIPLINE,
+    DEVICEGROUP,
+    DEVICETYPE;
+
+}
diff --git a/src/main/java/org/openepics/names/util/response/ResponseBoolean.java b/src/main/java/org/openepics/names/util/response/ResponseBoolean.java
new file mode 100644
index 0000000000000000000000000000000000000000..5077279aaf4282ac36ce9b4d9f519a4b1c45c875
--- /dev/null
+++ b/src/main/java/org/openepics/names/util/response/ResponseBoolean.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 European Spallation Source ERIC.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+package org.openepics.names.util.response;
+
+/**
+ * This class is used to ensure response to request origin are handled in a uniform way.
+ *
+ * @author Lars Johansson
+ */
+public class ResponseBoolean extends Response {
+
+    private Boolean response = null;
+
+    public ResponseBoolean() {
+        super("", "");
+    }
+
+    public ResponseBoolean(Boolean response) {
+        this();
+        this.response = response;
+    }
+
+    public ResponseBoolean(Boolean response, String message) {
+        super(message, "");
+        this.response = response;
+    }
+
+    public ResponseBoolean(Boolean response, String message, String details) {
+        super(message, details);
+        this.response = response;
+    }
+
+    public Boolean getResponse() {
+        return this.response;
+    }
+
+}
diff --git a/src/main/java/org/openepics/names/util/response/ResponseBooleanList.java b/src/main/java/org/openepics/names/util/response/ResponseBooleanList.java
new file mode 100644
index 0000000000000000000000000000000000000000..ccffcc09ede2086a35070baffff0141505976d61
--- /dev/null
+++ b/src/main/java/org/openepics/names/util/response/ResponseBooleanList.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2022 European Spallation Source ERIC.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+package org.openepics.names.util.response;
+
+import java.util.List;
+
+import com.google.common.collect.Lists;
+
+/**
+ * This class is used to ensure response to request origin are handled in a uniform way.
+ *
+ * @author Lars Johansson
+ */
+public class ResponseBooleanList extends ResponseBoolean {
+
+    private List<ResponseBoolean> responses = Lists.newArrayList();
+
+    public ResponseBooleanList() {
+        super();
+    }
+
+    public ResponseBooleanList(Boolean response) {
+        super(response);
+    }
+
+    public ResponseBooleanList(Boolean response, String message) {
+        super(response, message, "");
+    }
+
+    public ResponseBooleanList(Boolean response, String message, String details) {
+        super(response, message, details);
+    }
+
+    public ResponseBooleanList(List<ResponseBoolean> responses, Boolean response) {
+        super(response);
+        this.responses = responses;
+    }
+
+    public ResponseBooleanList(List<ResponseBoolean> responses, Boolean response, String message) {
+        super(response, message, "");
+        this.responses = responses;
+    }
+
+    public ResponseBooleanList(List<ResponseBoolean> responses, Boolean response, String message, String details) {
+        super(response, message, details);
+        this.responses = responses;
+    }
+
+    public List<ResponseBoolean> getResponses() {
+        return this.responses;
+    }
+
+}