tree data FEATURE lyd_new_meta function
diff --git a/src/tree_data.c b/src/tree_data.c
index 8ca974d..d797239 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -11,6 +11,7 @@
  *
  *     https://opensource.org/licenses/BSD-3-Clause
  */
+#define _POSIX_C_SOURCE 200809L /* strndup */
 
 #include "common.h"
 
@@ -887,6 +888,42 @@
     return ret;
 }
 
+API struct lyd_meta *
+lyd_new_meta(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str)
+{
+    struct lyd_meta *ret = NULL;
+    struct ly_ctx *ctx = parent->schema->module->ctx;
+    const char *prefix, *tmp;
+    char *str;
+    size_t pref_len, name_len;
+
+    LY_CHECK_ARG_RET(ctx, parent, name, module || strchr(name, ':'), NULL);
+
+    /* parse the name */
+    tmp = name;
+    if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
+        LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
+        return NULL;
+    }
+
+    /* find the module */
+    if (prefix) {
+        str = strndup(name, name_len);
+        module = ly_ctx_get_module_implemented(ctx, str);
+        free(str);
+        LY_CHECK_ERR_RET(!module, LOGERR(ctx, LY_EINVAL, "Module \"%*.s\" not found.", pref_len, prefix), NULL);
+    }
+
+    /* set value if none */
+    if (!val_str) {
+        val_str = "";
+    }
+
+    lyd_create_meta(parent, &ret, module, name, name_len, val_str, strlen(val_str), NULL, lydjson_resolve_prefix, NULL,
+                    LYD_JSON, parent->schema);
+    return ret;
+}
+
 struct lyd_node *
 lyd_get_prev_key_anchor(const struct lyd_node *first_sibling, const struct lysc_node *new_key)
 {
diff --git a/src/tree_data.h b/src/tree_data.h
index 3aa5ab9..29b56cb 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -702,6 +702,21 @@
                              const void *value, LYD_ANYDATA_VALUETYPE value_type);
 
 /**
+ * @brief Create new metadata for a data node.
+ *
+ * @param[in] parent Parent node for the metadata being created.
+ * @param[in] module Module of the metdata being created. If NULL, @p name must include module name as the prefix.
+ * @param[in] name Annotation name of the new metadata. It can include the annotation module as the prefix.
+ *            If the prefix is specified it is always used but if not specified, @p module must be set.
+ * @param[in] val_str String form of the value of the metadata being created. In case of an instance-identifier or identityref
+ * value, the JSON format is expected (module names instead of prefixes).
+ * @return New created metadata in the @p parent.
+ * @return NULL on error.
+ */
+struct lyd_meta *lyd_new_meta(struct lyd_node *parent, const struct lys_module *module, const char *name,
+                              const char *val_str);
+
+/**
  * @brief Insert a child into a parent. It is inserted as the last child.
  *
  * - if the node is part of some other tree, it is automatically unlinked.