diff --git a/rmw/include/rmw/rmw.h b/rmw/include/rmw/rmw.h
index d57809d1..f9d19cbd 100644
--- a/rmw/include/rmw/rmw.h
+++ b/rmw/include/rmw/rmw.h
@@ -556,7 +556,25 @@ rmw_publisher_assert_liveliness(const rmw_publisher_t * publisher);
/**
* The ROS message is serialized into a byte stream contained within the
* rmw_serialized_message_t structure.
- * The serialization format depends on the underlying middleware.
+ * The serialization format depends on the underlying implementation.
+ *
+ * \pre Given ROS message must be a valid non-null instance, initialized
+ * by the caller and matching the provided typesupport.
+ * \pre Given typesupport must be a valid non-null instance, as provided
+ * by `rosidl` APIs.
+ * \pre Given serialized message must be a valid non-null instance, initialized
+ * by the caller.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | Maybe [1]
+ * Thread-Safe | No
+ * Uses Atomics | Maybe [2]
+ * Lock-Free | Maybe [2]
+ * [1] if the given serialized message does not have enough capacity to hold
+ * the ROS message serialization
+ * [2] rmw implementation defined, check the implementation documentation
*
* \param[in] ros_message the typed ROS message
* \param[in] type_support the typesupport for the ROS message
@@ -577,10 +595,26 @@ rmw_serialize(
/**
* The given rmw_serialized_message_t's internal byte stream buffer is deserialized
* into the given ROS message.
- * The ROS message must already be allocated and initialized, and must match
- * the given typesupport structure.
* The serialization format expected in the rmw_serialized_message_t depends on the
- * underlying middleware.
+ * underlying implementation.
+ *
+ * \pre Given serialized message must be a valid non-null instance, such
+ * as that returned by `rmw_serialize()`, matching provided typesupport
+ * and ROS message.
+ * \pre Given typesupport must be a valid non-null instance, as provided
+ * by `rosidl` APIs.
+ * \pre Given ROS message must be a valid non-null instance, initialized
+ * by the caller.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | Maybe [1]
+ * Thread-Safe | No
+ * Uses Atomics | Maybe [2]
+ * Lock-Free | Maybe [2]
+ * [1] if the given ROS message contains unbounded fields
+ * [2] rmw implementation defined, check the implementation documentation
*
* \param[in] serialized_message the serialized message holding the byte stream
* \param[in] type_support the typesupport for the typed ros message
diff --git a/rmw/include/rmw/serialized_message.h b/rmw/include/rmw/serialized_message.h
index 08ed3ac9..4f2d34c3 100644
--- a/rmw/include/rmw/serialized_message.h
+++ b/rmw/include/rmw/serialized_message.h
@@ -22,17 +22,81 @@ extern "C"
#include "rcutils/types/uint8_array.h"
-// aliases for rcutils_uint8_array_t
-/*
- * For now this is a simple aliasing from a serialized message to a uint8 array.
+/**
+ * \struct rmw_serialized_message_t
+ *
+ * \brief Serialized message as a string of bytes.
+ *
+ * It includes (but it is not limited to) the following members:
+ * \i \c buffer the reference to internal storage, as a pointer
+ * \i \c buffer_length the size of stored contents, as an unsigned integer
+ * \i \c buffer_capacity the capacity of internal storage, as an unsigned integer
+ */
+
+/* For now this is a simple aliasing from a serialized message to a uint8 array.
* However, in future developments this serialized message can become something
* more complex and is therefore aliased.
*/
typedef rcutils_uint8_array_t rmw_serialized_message_t;
+
+/// Return a zero initialized serialized message struct.
#define rmw_get_zero_initialized_serialized_message rcutils_get_zero_initialized_uint8_array
-#define rmw_serialized_message_init rcutils_uint8_array_init
-#define rmw_serialized_message_fini rcutils_uint8_array_fini
-#define rmw_serialized_message_resize rcutils_uint8_array_resize
+
+/// Initialize a serialized message, zero initializing its contents.
+/**
+ * \pre Given serialized message must have been zero initialized.
+ *
+ * \param[inout] serialized_message a pointer to the serialized message to initialize
+ * \param[in] message_capacity the size of the memory to allocate
+ * \param[in] allocator the allocator to use for the memory allocation
+ * \return `RMW_RET_OK` if successful, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if any arguments are invalid, or
+ * \return 'RMW_RET_BAD_ALLOC` if no memory could be allocated correctly, or
+ * \return `RMW_RET_ERROR` if an unexpected error occurs
+ */
+#define rmw_serialized_message_init(serialized_message, message_capacity, allocator) \
+ rcutils_uint8_array_init(serialized_message, message_capacity, allocator)
+
+/// Finalize a serialized message.
+/**
+ * \pre Given serialized message must have been initialized with `rmw_serialized_message_init()`.
+ *
+ * \remarks If serialized message is zero initialized, then `RMW_RET_INVALID_ARGUMENT` is returned.
+ *
+ * \param[in] serialized_message pointer to the serialized message to be cleaned up
+ * \return `RMW_RET_OK` if successful, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if serialized_message is invalid, or
+ * \return `RMW_RET_ERROR` if an unexpected error occurs
+ */
+#define rmw_serialized_message_fini(serialized_message) \
+ rcutils_uint8_array_fini(serialized_message)
+
+/// Resize the internal buffer of the serialized message.
+/**
+ * The internal buffer of the serialized message can be resized dynamically
+ * if needed.
+ * If the new size is smaller than the current capacity, then the memory is
+ * truncated.
+ *
+ * \pre Given serialized message must have been initialized with `rmw_serialized_message_init()`.
+ *
+ * \remarks If serialized message is zero initialized, then `RMW_RET_INVALID_ARGUMENT`
+ * is returned.
+ *
+ * \warning Be aware that this might deallocate the memory and therefore
+ * invalidate any pointers to the internal buffer.
+ *
+ * \param[inout] serialized_message pointer to the serialized message
+ * to be resized
+ * \param[in] new_size the new size of the internal buffer
+ * \return `RMW_RET_OK` if successful, or
+ * \return `RMW_RET_INVALID_ARGUMENT` if serialized_message is invalid
+ * or new_size is set to zero, or
+ * \return `RMW_RET_BAD_ALLOC` if memory allocation failed, or
+ * \return `RMW_RET_ERROR` if an unexpected error occurs
+ */
+#define rmw_serialized_message_resize(serialized_message, new_size) \
+ rcutils_uint8_array_resize(serialized_message, new_size)
#if __cplusplus
}