Repository: line/line-bot-sdk-python
Pull request #96 (2018-03-07 11:45:27)

Fix richmenu for release
In order to release the richmenu feature, I made a minor fix.

In addition, since TemplateAction is now used other than TemplateMessage, I rename it and move it to the actions module. We try to maintain compatibility. (Compatibility is maintained.)

okdtsk: Thanks! LGTM :octocat: 

Patch:
diff --git a/README.rst b/README.rst
index 379a5d7..ee2a985 100644
--- a/README.rst
+++ b/README.rst
@@ -241,44 +241,44 @@ https://developers.line.me/en/docs/messaging-api/reference/#leave-room
 
     line_bot_api.leave_room(room_id)
 
-create\_rich\_menu(self, data, timeout=None)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Create a rich menu object through a group of given data and return rich menu id.
-The data is an rich menu object to create.
+get\_rich\_menu(self, rich\_menu\_id, timeout=None)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Gets a rich menu via a rich menu ID.
+
+https://developers.line.me/en/docs/messaging-api/reference/#get-rich-menu
+
+.. code:: python
+
+    rich_menu = line_bot_api.get_rich_menu(rich_menu_id)
+    print(rich_menu.rich_menu_id)
+
+create\_rich\_menu(self, rich_\menu, timeout=None)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Creates a rich menu.
+You must upload a rich menu image and link the rich menu to a user for the rich menu to be displayed. You can create up to 10 rich menus for one bot.
 
 https://developers.line.me/en/docs/messaging-api/reference/#create-rich-menu
 
 .. code:: python
-    
+
     rich_menu_to_create = RichMenu(
-                                size=RichMenuBound(
-                                    width=2500,
-                                    height=1686
-                                ),
-                                selected= False,
-                                name="nice richmenu",
-                                chatBarText="touch me",
-                                areas=[
-                                    RichMenuArea(
-                                        RichMenuBound(
-                                            x=0,
-                                            y=0,
-                                            width=2500,
-                                            height=1686 
-                                        ),
-                                        URITemplateAction(
-                                            uri='line://nv/location'
-                                        )                    
-                                    )
-                                ]
-                            )
-    rich_menu_id = line_bot_api.create_rich_menu(data=rich_menu_to_create)
+        size=RichMenuSize(width=2500, height=843),
+        selected=False,
+        name="Nice richmenu",
+        chat_bar_text="Tap here",
+        areas=[RichMenuArea(
+            bounds=RichMenuBounds(x=0, y=0, width=2500, height=843),
+            action=URIAction(label='Go to line.me', uri='https://line.me'))]
+    )
+    rich_menu_id = line_bot_api.create_rich_menu(rich_menu=rich_menu_to_create)
     print(rich_menu_id)
 
 delete\_rich\_menu(self, rich\_menu\_id, timeout=None)
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-Delete rich menu object through a given rich_menu_id.
+Deletes a rich menu.
 
 https://developers.line.me/en/docs/messaging-api/reference/#delete-rich-menu
         
@@ -286,16 +286,17 @@ https://developers.line.me/en/docs/messaging-api/reference/#delete-rich-menu
 
     line_bot_api.delete_rich_menu(rich_menu_id)
 
-set\_rich\_menu\_image(self, rich\_menu\_id, content\_type, content, timeout=None)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+get\_rich\_menu\_id\_of\_user(self, user\_id, timeout=None)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-Uploads and attaches an image to a rich menu through id and image path.
+Gets the ID of the rich menu linked to a user.
 
-https://developers.line.me/en/docs/messaging-api/reference/#upload-rich-menu-image
+https://developers.line.me/en/docs/messaging-api/reference/#get-rich-menu-id-of-user
 
 .. code:: python
 
-    line_bot_api.set_rich_menu_image(rich_menu_id, content_type, content)
+    rich_menu_id = ine_bot_api.get_rich_menu_id_of_user(user_id)
+    print(rich_menu_id)
 
 link\_rich\_menu\_to\_user(self, user\_id, rich\_menu\_id, timeout=None)
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -308,67 +309,55 @@ https://developers.line.me/en/docs/messaging-api/reference/#link-rich-menu-to-us
 
     line_bot_api.link_rich_menu_to_user(user_id, rich_menu_id)
 
-get\_rich\_menu\_list(self, timeout=None)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Gets a list of all uploaded rich menus.
-
-https://developers.line.me/en/docs/messaging-api/reference/#get-rich-menu-list
-
-.. code:: python
-
-    lst_rich_menu_obj = line_bot_api.get_rich_menu_list()
-    for rich_menu_obj in lst_rich_menu_obj:
-        print(rich_menu_obj.rich_menu_id)
-
-get\_rich\_menu(self, rich\_menu\_id, timeout=None)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+unlink\_rich\_menu\_from\_user(self, user\_id, timeout=None)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-Get rich menu object through a given Rich menu ID.
+Unlinks a rich menu from a user.
 
-https://developers.line.me/en/docs/messaging-api/reference/#get-rich-menu
+https://developers.line.me/en/docs/messaging-api/reference/#unlink-rich-menu-from-user
 
 .. code:: python
 
-    rich_menu_object = line_bot_api.get_rich_menu(rich_menu_id)
-    print(rich_menu_obj.rich_menu_id)
+    line_bot_api.unlink_rich_menu_from_user(user_id)
 
-get\_rich\_menu\_id\_of\_user(self, user\_id, timeout=None)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+get\_rich\_menu\_image(self, rich\_menu\_id, timeout=None)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-Gets the ID of the rich menu linked to a user.
+Downloads an image associated with a rich menu.
 
-https://developers.line.me/en/docs/messaging-api/reference/#get-rich-menu-id-of-user
+https://developers.line.me/en/docs/messaging-api/reference/#download-rich-menu-image
 
 .. code:: python
 
-    rich_menu_object = ine_bot_api.get_rich_menu_id_of_user(user_id)
-    print(rich_menu_object.rich_menu_id)
+    content = line_bot_api.get_rich_menu_image(rich_menu_id)
+    with open(file_path, 'wb') as fd:
+        for chunk in content.iter_content():
+            fd.write(chunk)
 
-unlink\_rich\_menu\_from\_user(self, user\_id, timeout=None)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+set\_rich\_menu\_image(self, rich\_menu\_id, content\_type, content, timeout=None)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-Unlinks a rich menu from a user.
+Uploads and attaches an image to a rich menu.
 
-https://developers.line.me/en/docs/messaging-api/reference/#unlink-rich-menu-from-user
+https://developers.line.me/en/docs/messaging-api/reference/#upload-rich-menu-image
 
 .. code:: python
 
-    line_bot_api.unlink_rich_menu_from_user(user_id)
+    with open(file_path, 'rb') as f:
+        line_bot_api.set_rich_menu_image(rich_menu_id, content_type, f)
 
-get_rich_menu_image(self, rich\_menu\_id, timeout=None)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+get\_rich\_menu\_list(self, timeout=None)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-Downloads an image associated with a rich menu.
+Gets a list of all uploaded rich menus.
 
-https://developers.line.me/en/docs/messaging-api/reference/#download-rich-menu-image
+https://developers.line.me/en/docs/messaging-api/reference/#get-rich-menu-list
 
 .. code:: python
 
-    message_content = line_bot_api.get_rich_menu_image(rich_menu_id)
-    with open(file_path, 'wb') as fd:
-        for chunk in message_content.iter_content():
-            fd.write(chunk)
+    rich_menu_list = line_bot_api.get_rich_menu_list()
+    for rich_menu in rich_menu_list:
+        print(rich_menu.rich_menu_id)
 
 ※ Error handling
 ^^^^^^^^^^^^^^^^
@@ -489,16 +478,16 @@ TemplateSendMessage - ButtonsTemplate
             title='Menu',
             text='Please select',
             actions=[
-                PostbackTemplateAction(
+                PostbackAction(
                     label='postback',
                     text='postback text',
                     data='action=buy&itemid=1'
                 ),
-                MessageTemplateAction(
+                MessageAction(
                     label='message',
                     text='message text'
                 ),
-                URITemplateAction(
+                URIAction(
                     label='uri',
                     uri='http://example.com/'
                 )
@@ -516,12 +505,12 @@ TemplateSendMessage - ConfirmTemplate
         template=ConfirmTemplate(
             text='Are you sure?',
             actions=[
-                PostbackTemplateAction(
+                PostbackAction(
                     label='postback',
                     text='postback text',
                     data='action=buy&itemid=1'
                 ),
-                MessageTemplateAction(
+                MessageAction(
                     label='message',
                     text='message text'
                 )
@@ -543,16 +532,16 @@ TemplateSendMessage - CarouselTemplate
                     title='this is menu1',
                     text='description1',
                     actions=[
-                        PostbackTemplateAction(
+                        PostbackAction(
                             label='postback1',
                             text='postback text1',
                             data='action=buy&itemid=1'
                         ),
-                        MessageTemplateAction(
+                        MessageAction(
                             label='message1',
                             text='message text1'
                         ),
-                        URITemplateAction(
+                        URIAction(
                             label='uri1',
                             uri='http://example.com/1'
                         )
@@ -563,16 +552,16 @@ TemplateSendMessage - CarouselTemplate
                     title='this is menu2',
                     text='description2',
                     actions=[
-                        PostbackTemplateAction(
+                        PostbackAction(
                             label='postback2',
                             text='postback text2',
                             data='action=buy&itemid=2'
                         ),
-                        MessageTemplateAction(
+                        MessageAction(
                             label='message2',
                             text='message text2'
                         ),
-                        URITemplateAction(
+                        URIAction(
                             label='uri2',
                             uri='http://example.com/2'
                         )
@@ -593,7 +582,7 @@ TemplateSendMessage - ImageCarouselTemplate
             columns=[
                 ImageCarouselColumn(
                     image_url='https://example.com/item1.jpg',
-                    action=PostbackTemplateAction(
+                    action=PostbackAction(
                         label='postback1',
                         text='postback text1',
                         data='action=buy&itemid=1'
@@ -601,7 +590,7 @@ TemplateSendMessage - ImageCarouselTemplate
                 ),
                 ImageCarouselColumn(
                     image_url='https://example.com/item2.jpg',
-                    action=PostbackTemplateAction(
+                    action=PostbackAction(
                         label='postback2',
                         text='postback text2',
                         data='action=buy&itemid=2'
diff --git a/examples/flask-kitchensink/app.py b/examples/flask-kitchensink/app.py
index 8f12846..3608b42 100644
--- a/examples/flask-kitchensink/app.py
+++ b/examples/flask-kitchensink/app.py
@@ -31,9 +31,9 @@ from linebot.exceptions import (
 from linebot.models import (
     MessageEvent, TextMessage, TextSendMessage,
     SourceUser, SourceGroup, SourceRoom,
-    TemplateSendMessage, ConfirmTemplate, MessageTemplateAction,
-    ButtonsTemplate, ImageCarouselTemplate, ImageCarouselColumn, URITemplateAction,
-    PostbackTemplateAction, DatetimePickerTemplateAction,
+    TemplateSendMessage, ConfirmTemplate, MessageAction,
+    ButtonsTemplate, ImageCarouselTemplate, ImageCarouselColumn, URIAction,
+    PostbackAction, DatetimePickerAction,
     CarouselTemplate, CarouselColumn, PostbackEvent,
     StickerMessage, StickerSendMessage, LocationMessage, LocationSendMessage,
     ImageMessage, VideoMessage, AudioMessage, FileMessage,
@@ -96,35 +96,31 @@ def handle_text_message(event):
             profile = line_bot_api.get_profile(event.source.user_id)
             line_bot_api.reply_message(
                 event.reply_token, [
-                    TextSendMessage(
-                        text='Display name: ' + profile.display_name
-                    ),
-                    TextSendMessage(
-                        text='Status message: ' + profile.status_message
-                    )
+                    TextSendMessage(text='Display name: ' + profile.display_name),
+                    TextSendMessage(text='Status message: ' + profile.status_message)
                 ]
             )
         else:
             line_bot_api.reply_message(
                 event.reply_token,
-                TextMessage(text="Bot can't use profile API without user ID"))
+                TextSendMessage(text="Bot can't use profile API without user ID"))
     elif text == 'bye':
         if isinstance(event.source, SourceGroup):
             line_bot_api.reply_message(
-                event.reply_token, TextMessage(text='Leaving group'))
+                event.reply_token, TextSendMessage(text='Leaving group'))
             line_bot_api.leave_group(event.source.group_id)
         elif isinstance(event.source, SourceRoom):
             line_bot_api.reply_message(
-                event.reply_token, TextMessage(text='Leaving group'))
+                event.reply_token, TextSendMessage(text='Leaving group'))
             line_bot_api.leave_room(event.source.room_id)
         else:
             line_bot_api.reply_message(
                 event.reply_token,
-                TextMessage(text="Bot can't leave from 1:1 chat"))
+                TextSendMessage(text="Bot can't leave from 1:1 chat"))
     elif text == 'confirm':
         confirm_template = ConfirmTemplate(text='Do it?', actions=[
-            MessageTemplateAction(label='Yes', text='Yes!'),
-            MessageTemplateAction(label='No', text='No!'),
+            MessageAction(label='Yes', text='Yes!'),
+            MessageAction(label='No', text='No!'),
         ])
         template_message = TemplateSendMessage(
             alt_text='Confirm alt text', template=confirm_template)
@@ -132,13 +128,10 @@ def handle_text_message(event):
     elif text == 'buttons':
         buttons_template = ButtonsTemplate(
             title='My buttons sample', text='Hello, my buttons', actions=[
-                URITemplateAction(
-                    label='Go to line.me', uri='https://line.me'),
-                PostbackTemplateAction(label='ping', data='ping'),
-                PostbackTemplateAction(
-                    label='ping with text', data='ping',
-                    text='ping'),
-                MessageTemplateAction(label='Translate Rice', text='米')
+                URIAction(label='Go to line.me', uri='https://line.me'),
+                PostbackAction(label='ping', data='ping'),
+                PostbackAction(label='ping with text', data='ping', text='ping'),
+                MessageAction(label='Translate Rice', text='米')
             ])
         template_message = TemplateSendMessage(
             alt_text='Buttons alt text', template=buttons_template)
@@ -146,15 +139,12 @@ def handle_text_message(event):
     elif text == 'carousel':
         carousel_template = CarouselTemplate(columns=[
             CarouselColumn(text='hoge1', title='fuga1', actions=[
-                URITemplateAction(
-                    label='Go to line.me', uri='https://line.me'),
-                PostbackTemplateAction(label='ping', data='ping')
+                URIAction(label='Go to line.me', uri='https://line.me'),
+                PostbackAction(label='ping', data='ping')
             ]),
             CarouselColumn(text='hoge2', title='fuga2', actions=[
-                PostbackTemplateAction(
-                    label='ping with text', data='ping',
-                    text='ping'),
-                MessageTemplateAction(label='Translate Rice', text='米')
+                PostbackAction(label='ping with text', data='ping', text='ping'),
+                MessageAction(label='Translate Rice', text='米')
             ]),
         ])
         template_message = TemplateSendMessage(
@@ -163,13 +153,13 @@ def handle_text_message(event):
     elif text == 'image_carousel':
         image_carousel_template = ImageCarouselTemplate(columns=[
             ImageCarouselColumn(image_url='https://via.placeholder.com/1024x1024',
-                                action=DatetimePickerTemplateAction(label='datetime',
-                                                                    data='datetime_postback',
-                                                                    mode='datetime')),
+                                action=DatetimePickerAction(label='datetime',
+                                                            data='datetime_postback',
+                                                            mode='datetime')),
             ImageCarouselColumn(image_url='https://via.placeholder.com/1024x1024',
-                                action=DatetimePickerTemplateAction(label='date',
-                                                                    data='date_postback',
-                                                                    mode='date'))
+                                action=DatetimePickerAction(label='date',
+                                                            data='date_postback',
+                                                            mode='date'))
         ])
         template_message = TemplateSendMessage(
             alt_text='ImageCarousel alt text', template=image_carousel_template)
diff --git a/linebot/api.py b/linebot/api.py
index f894169..70f7faf 100644
--- a/linebot/api.py
+++ b/linebot/api.py
@@ -21,8 +21,9 @@ import json
 from .__about__ import __version__
 from .exceptions import LineBotApiError
 from .http_client import HttpClient, RequestsHttpClient
-from .models.error import Error
-from .models.responses import Profile, MemberIds, MessageContent, RichMenuResponse
+from .models import (
+    Error, Profile, MemberIds, Content, RichMenuResponse
+)
 
 
 class LineBotApi(object):
@@ -124,206 +125,6 @@ class LineBotApi(object):
             '/v2/bot/message/push', data=json.dumps(data), timeout=timeout
         )
 
-    def get_rich_menu(self, rich_menu_id, timeout=None):
-        """Call get rich menu API.
-
-        https://developers.line.me/en/docs/messaging-api/reference/#get-rich-menu
-
-        Get rich menu object through a given rich_menu_id
-
-        :param str rich_menu_id: ID of the rich menu
-        :param timeout: (optional) How long to wait for the server
-            to send data before giving up, as a float,
-            or a (connect timeout, read timeout) float tuple.
-            Default is self.http_client.timeout
-        :type timeout: float | tuple(float, float)
-        :return: RichMenuResponse instance
-        :type RichMenuResponse: T <= :py:class:`linebot.models.reponse.RichMenuResponse`
-        """
-        response = self._get(
-            '/v2/bot/richmenu/{rich_menu_id}'.format(rich_menu_id=rich_menu_id),
-            timeout=timeout
-        )
-
-        return RichMenuResponse.new_from_json_dict(response.json)
-
-    def delete_rich_menu(self, rich_menu_id, timeout=None):
-        """Call delete rich menu API.
-
-        https://developers.line.me/en/docs/messaging-api/reference/#delete-rich-menu
-
-        Delete rich menu object through a given rich_menu_id
-
-        :param str rich_menu_id: ID of the rich menu
-        :param timeout: (optional) How long to wait for the server
-            to send data before giving up, as a float,
-            or a (connect timeout, read timeout) float tuple.
-            Default is self.http_client.timeout
-        :type timeout: float | tuple(float, float)
-        """
-        self._delete(
-            '/v2/bot/richmenu/{rich_menu_id}'.format(rich_menu_id=rich_menu_id),
-            timeout=timeout
-        )
-
-    def create_rich_menu(self, rich_menu, timeout=None):
-        """Call delete rich menu API.
-
-        https://developers.line.me/en/docs/messaging-api/reference/#create-rich-menu
-
-        Create a rich menu object through a group of given rich_menu data
-
-        :param rich_menu: Inquired to create a rich menu.
-        :type rich_menu: T <= :py:class:`linebot.models.rich_menu.RichMenu`
-        :param timeout: (optional) How long to wait for the server
-            to send data before giving up, as a float,
-            or a (connect timeout, read timeout) float tuple.
-            Default is self.http_client.timeout
-        :type timeout: float | tuple(float, float)
-        :return: rich menu id
-        """
-        response = self._post(
-            '/v2/bot/richmenu', data=rich_menu.as_json_string(), timeout=timeout
-        )
-
-        return response.json.get('richMenuId')
-
-    def link_rich_menu_to_user(self, user_id, rich_menu_id, timeout=None):
-        """Call link rich menu to user API.
-
-        https://developers.line.me/en/docs/messaging-api/reference/#link-rich-menu-to-user
-
-        Links a rich menu to a user. Only one rich menu can be linked to a user at one time.
-
-        :param str user_id: ID of an uploaded rich menu
-        :param str rich_menu_id: ID of the user
-        :type timeout: float | tuple(float, float)
-        """
-        self._post(
-            '/v2/bot/user/{user_id}/richmenu/{rich_menu_id}'.format(
-                user_id=user_id,
-                rich_menu_id=rich_menu_id
-            ),
-            timeout=timeout
-        )
-
-    def get_rich_menu_list(self, timeout=None):
-        """Call get rich menu list API.
-
-        https://developers.line.me/en/docs/messaging-api/reference/#get-rich-menu-list
-
-        Gets a list of all uploaded rich menus.
-
-        :return: An list of RichMenuResponse instances
-        :type RichMenuResponse: T <= :py:class:`linebot.models.reponse.RichMenuResponse`
-        :param timeout: (optional) How long to wait for the server
-            to send data before giving up, as a float,
-            or a (connect timeout, read timeout) float tuple.
-            Default is self.http_client.timeout
-        :type timeout: float | tuple(float, float)
-        """
-        response = self._get(
-            '/v2/bot/richmenu/list',
-            timeout=timeout
-        )
-
-        lst_result = []
-        for richmenu in response.json['richmenus']:
-            lst_result.append(RichMenuResponse.new_from_json_dict(richmenu))
-
-        return lst_result
-
-    def set_rich_menu_image(self, rich_menu_id, content_type, content, timeout=None):
-        """Call upload rich menu image API.
-
-        https://developers.line.me/en/docs/messaging-api/reference/#upload-rich-menu-image
-
-        Uploads and attaches an image to a rich menu.
-
-        :param str rich_menu_id: IDs of the rechmenu
-        :param str content_type: image/jpeg or image/png
-        :param str content: image content as request body in bytes
-        :param timeout: (optional) How long to wait for the server
-            to send data before giving up, as a float,
-            or a (connect timeout, read timeout) float tuple.
-            Default is self.http_client.timeout
-        :type timeout: float | tuple(float, float)
-        """
-        self.headers['Content-Type'] = content_type
-
-        # send request
-        self._post(
-            '/v2/bot/richmenu/{rich_menu_id}/content'.format(rich_menu_id=rich_menu_id),
-            data=content,
-            timeout=timeout
-        )
-
-        # remove added header to avoid side effect in other apis
-        del self.headers['Content-Type']
-
-    def get_rich_menu_id_of_user(self, user_id, timeout=None):
-        """Call get rich menu ID of user API.
-
-        https://developers.line.me/en/docs/messaging-api/reference/#get-rich-menu-id-of-user
-
-        Gets the ID of the rich menu linked to a user.
-
-        :param str user_id: IDs of the user
-        :param timeout: (optional) How long to wait for the server
-            to send data before giving up, as a float,
-            or a (connect timeout, read timeout) float tuple.
-            Default is self.http_client.timeout
-        :type timeout: float | tuple(float, float)
-        """
-        response = self._get(
-            '/v2/bot/user/{user_id}/richmenu'.format(user_id=user_id),
-            timeout=timeout
-        )
-
-        return response.json.get('richMenuId')
-
-    def unlink_rich_menu_from_user(self, user_id, timeout=None):
-        """Call unlink rich menu from user API.
-
-        https://developers.line.me/en/docs/messaging-api/reference/#unlink-rich-menu-from-user
-
-        Unlinks a rich menu from a user.
-
-        :param str user_id: ID of the user
-        :param timeout: (optional) How long to wait for the server
-            to send data before giving up, as a float,
-            or a (connect timeout, read timeout) float tuple.
-            Default is self.http_client.timeout
-        :type timeout: float | tuple(float, float)
-        """
-        self._delete(
-            '/v2/bot/user/{user_id}/richmenu'.format(user_id=user_id),
-            timeout=timeout
-        )
-
-    def get_rich_menu_image(self, rich_menu_id, timeout=None):
-        """Call download rich menu image API.
-
-        https://developers.line.me/en/docs/messaging-api/reference/#download-rich-menu-image
-
-        Downloads an image associated with a rich menu.
-
-        :param str rich_menu_id: ID of the rich menu with the image to be downloaded
-        :param timeout: (optional) How long to wait for the server
-            to send data before giving up, as a float,
-            or a (connect timeout, read timeout) float tuple.
-            Default is self.http_client.timeout
-        :type timeout: float | tuple(float, float)
-        :rtype: :py:class:`linebot.models.responses.MessageContent`
-        :return: MessageContent instance
-        """
-        response = self._get(
-            '/v2/bot/richmenu/{rich_menu_id}/content'.format(rich_menu_id=rich_menu_id),
-            timeout=timeout
-        )
-
-        return MessageContent(response)
-
     def multicast(self, to, messages, timeout=None):
         """Call multicast API.
 
@@ -502,15 +303,15 @@ class LineBotApi(object):
             or a (connect timeout, read timeout) float tuple.
             Default is self.http_client.timeout
         :type timeout: float | tuple(float, float)
-        :rtype: :py:class:`linebot.models.responses.MessageContent`
-        :return: MessageContent instance
+        :rtype: :py:class:`linebot.models.responses.Content`
+        :return: Content instance
         """
         response = self._get(
             '/v2/bot/message/{message_id}/content'.format(message_id=message_id),
             stream=True, timeout=timeout
         )
 
-        return MessageContent(response)
+        return Content(response)
 
     def leave_group(self, group_id, timeout=None):
         """Call leave group API.
@@ -550,19 +351,207 @@ class LineBotApi(object):
             timeout=timeout
         )
 
-    def _get(self, path, params=None, stream=False, timeout=None):
+    def get_rich_menu(self, rich_menu_id, timeout=None):
+        """Call get rich menu API.
+
+        https://developers.line.me/en/docs/messaging-api/reference/#get-rich-menu
+
+        :param str rich_menu_id: ID of the rich menu
+        :param timeout: (optional) How long to wait for the server
+            to send data before giving up, as a float,
+            or a (connect timeout, read timeout) float tuple.
+            Default is self.http_client.timeout
+        :type timeout: float | tuple(float, float)
+        :rtype: :py:class:`linebot.models.responses.RichMenuResponse`
+        :return: RichMenuResponse instance
+        """
+        response = self._get(
+            '/v2/bot/richmenu/{rich_menu_id}'.format(rich_menu_id=rich_menu_id),
+            timeout=timeout
+        )
+
+        return RichMenuResponse.new_from_json_dict(response.json)
+
+    def create_rich_menu(self, rich_menu, timeout=None):
+        """Call create rich menu API.
+
+        https://developers.line.me/en/docs/messaging-api/reference/#create-rich-menu
+
+        :param rich_menu: Inquired to create a rich menu object.
+        :type rich_menu: T <= :py:class:`linebot.models.rich_menu.RichMenu`
+        :param timeout: (optional) How long to wait for the server
+            to send data before giving up, as a float,
+            or a (connect timeout, read timeout) float tuple.
+            Default is self.http_client.timeout
+        :type timeout: float | tuple(float, float)
+        :rtype: str
+        :return: rich menu id
+        """
+        response = self._post(
+            '/v2/bot/richmenu', data=rich_menu.as_json_string(), timeout=timeout
+        )
+
+        return response.json.get('richMenuId')
+
+    def delete_rich_menu(self, rich_menu_id, timeout=None):
+        """Call delete rich menu API.
+
+        https://developers.line.me/en/docs/messaging-api/reference/#delete-rich-menu
+
+        :param str rich_menu_id: ID of an uploaded rich menu
+        :param timeout: (optional) How long to wait for the server
+            to send data before giving up, as a float,
+            or a (connect timeout, read timeout) float tuple.
+            Default is self.http_client.timeout
+        :type timeout: float | tuple(float, float)
+        """
+        self._delete(
+            '/v2/bot/richmenu/{rich_menu_id}'.format(rich_menu_id=rich_menu_id),
+            timeout=timeout
+        )
+
+    def get_rich_menu_id_of_user(self, user_id, timeout=None):
+        """Call get rich menu ID of user API.
+
+        https://developers.line.me/en/docs/messaging-api/reference/#get-rich-menu-id-of-user
+
+        :param str user_id: IDs of the user
+        :param timeout: (optional) How long to wait for the server
+            to send data before giving up, as a float,
+            or a (connect timeout, read timeout) float tuple.
+            Default is self.http_client.timeout
+        :type timeout: float | tuple(float, float)
+        :rtype: str
+        :return: rich menu id
+        """
+        response = self._get(
+            '/v2/bot/user/{user_id}/richmenu'.format(user_id=user_id),
+            timeout=timeout
+        )
+
+        return response.json.get('richMenuId')
+
+    def link_rich_menu_to_user(self, user_id, rich_menu_id, timeout=None):
+        """Call link rich menu to user API.
+
+        https://developers.line.me/en/docs/messaging-api/reference/#link-rich-menu-to-user
+
+        :param str user_id: ID of an uploaded rich menu
+        :param str rich_menu_id: ID of the user
+        :type timeout: float | tuple(float, float)
+        """
+        self._post(
+            '/v2/bot/user/{user_id}/richmenu/{rich_menu_id}'.format(
+                user_id=user_id,
+                rich_menu_id=rich_menu_id
+            ),
+            timeout=timeout
+        )
+
+    def unlink_rich_menu_from_user(self, user_id, timeout=None):
+        """Call unlink rich menu from user API.
+
+        https://developers.line.me/en/docs/messaging-api/reference/#unlink-rich-menu-from-user
+
+        :param str user_id: ID of the user
+        :param timeout: (optional) How long to wait for the server
+            to send data before giving up, as a float,
+            or a (connect timeout, read timeout) float tuple.
+            Default is self.http_client.timeout
+        :type timeout: float | tuple(float, float)
+        """
+        self._delete(
+            '/v2/bot/user/{user_id}/richmenu'.format(user_id=user_id),
+            timeout=timeout
+        )
+
+    def get_rich_menu_image(self, rich_menu_id, timeout=None):
+        """Call download rich menu image API.
+
+        https://developers.line.me/en/docs/messaging-api/reference/#download-rich-menu-image
+
+        :param str rich_menu_id: ID of the rich menu with the image to be downloaded
+        :param timeout: (optional) How long to wait for the server
+            to send data before giving up, as a float,
+            or a (connect timeout, read timeout) float tuple.
+            Default is self.http_client.timeout
+        :type timeout: float | tuple(float, float)
+        :rtype: :py:class:`linebot.models.responses.Content`
+        :return: Content instance
+        """
+        response = self._get(
+            '/v2/bot/richmenu/{rich_menu_id}/content'.format(rich_menu_id=rich_menu_id),
+            timeout=timeout
+        )
+
+        return Content(response)
+
+    def set_rich_menu_image(self, rich_menu_id, content_type, content, timeout=None):
+        """Call upload rich menu image API.
+
+        https://developers.line.me/en/docs/messaging-api/reference/#upload-rich-menu-image
+
+        Uploads and attaches an image to a rich menu.
+
+        :param str rich_menu_id: IDs of the richmenu
+        :param str content_type: image/jpeg or image/png
+        :param content: image content as bytes, or file-like object
+        :param timeout: (optional) How long to wait for the server
+            to send data before giving up, as a float,
+            or a (connect timeout, read timeout) float tuple.
+            Default is self.http_client.timeout
+        :type timeout: float | tuple(float, float)
+        """
+        self._post(
+            '/v2/bot/richmenu/{rich_menu_id}/content'.format(rich_menu_id=rich_menu_id),
+            data=content,
+            headers={'Content-Type': content_type},
+            timeout=timeout
+        )
+
+    def get_rich_menu_list(self, timeout=None):
+        """Call get rich menu list API.
+
+        https://developers.line.me/en/docs/messaging-api/reference/#get-rich-menu-list
+
+        :param timeout: (optional) How long to wait for the server
+            to send data before giving up, as a float,
+            or a (connect timeout, read timeout) float tuple.
+            Default is self.http_client.timeout
+        :type timeout: float | tuple(float, float)
+        :rtype: list(T <= :py:class:`linebot.models.reponse.RichMenuResponse`)
+        :return: list[RichMenuResponse] instance
+        """
+        response = self._get(
+            '/v2/bot/richmenu/list',
+            timeout=timeout
+        )
+
+        result = []
+        for richmenu in response.json['richmenus']:
+            result.append(RichMenuResponse.new_from_json_dict(richmenu))
+
+        return result
+
+    def _get(self, path, params=None, headers=None, stream=False, timeout=None):
         url = self.endpoint + path
 
+        if headers is None:
+            headers = {}
+        headers.update(self.headers)
+
         response = self.http_client.get(
-            url, headers=self.headers, params=params, stream=stream, timeout=timeout
+            url, headers=headers, params=params, stream=stream, timeout=timeout
         )
 
         self.__check_error(response)
         return response
 
-    def _post(self, path, data=None, timeout=None):
+    def _post(self, path, data=None, headers=None, timeout=None):
         url = self.endpoint + path
-        headers = {'Content-Type': 'application/json'}
+
+        if headers is None:
+            headers = {'Content-Type': 'application/json'}
         headers.update(self.headers)
 
         response = self.http_client.post(
@@ -572,9 +561,11 @@ class LineBotApi(object):
         self.__check_error(response)
         return response
 
-    def _delete(self, path, data=None, timeout=None):
+    def _delete(self, path, data=None, headers=None, timeout=None):
         url = self.endpoint + path
-        headers = {'Content-Type': 'application/json'}
+
+        if headers is None:
+            headers = {}
         headers.update(self.headers)
 
         response = self.http_client.delete(
diff --git a/linebot/models/__init__.py b/linebot/models/__init__.py
index 505eab8..3c6a6ae 100644
--- a/linebot/models/__init__.py
+++ b/linebot/models/__init__.py
@@ -14,6 +14,18 @@
 
 """linebot.models package."""
 
+from .actions import (  # noqa
+    Action,
+    PostbackAction,
+    MessageAction,
+    URIAction,
+    DatetimePickerAction,
+    Action as TemplateAction,  # backward compatibility
+    PostbackAction as PostbackTemplateAction,  # backward compatibility
+    MessageAction as MessageTemplateAction,  # backward compatibility
+    URIAction as URITemplateAction,  # backward compatibility
+    DatetimePickerAction as DatetimePickerTemplateAction,  # backward compatibility
+)
 from .base import (  # noqa
     Base,
 )
@@ -49,10 +61,20 @@ from .messages import (  # noqa
     AudioMessage,
     LocationMessage,
     StickerMessage,
-    FileMessage
+    FileMessage,
 )
 from .responses import (  # noqa
     Profile,
+    MemberIds,
+    Content,
+    RichMenuResponse,
+    Content as MessageContent,  # backward compatibility
+)
+from .rich_menu import (  # noqa
+    RichMenu,
+    RichMenuSize,
+    RichMenuArea,
+    RichMenuBounds,
 )
 from .send_messages import (  # noqa
     SendMessage,
@@ -76,16 +98,6 @@ from .template import (  # noqa
     ConfirmTemplate,
     CarouselTemplate,
     CarouselColumn,
-    TemplateAction,
-    PostbackTemplateAction,
-    MessageTemplateAction,
-    URITemplateAction,
-    DatetimePickerTemplateAction,
     ImageCarouselTemplate,
     ImageCarouselColumn,
 )
-from .rich_menu import ( # noqa
-    RichMenu,
-    RichMenuBound,
-    RichMenuArea,
-)
diff --git a/linebot/models/actions.py b/linebot/models/actions.py
new file mode 100644
index 0000000..b8cd7ab
--- /dev/null
+++ b/linebot/models/actions.py
@@ -0,0 +1,175 @@
+# -*- coding: utf-8 -*-
+
+#  Licensed under the Apache License, Version 2.0 (the "License"); you may
+#  not use this file except in compliance with the License. You may obtain
+#  a copy of the License at
+#
+#       https://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#  License for the specific language governing permissions and limitations
+#  under the License.
+
+"""linebot.models.template module."""
+
+from __future__ import unicode_literals
+
+from abc import ABCMeta
+
+from future.utils import with_metaclass
+
+from .base import Base
+
+
+def get_action(action):
+    """Get action."""
+    action_obj = Base.get_or_new_from_json_dict_with_types(
+        action, {
+            'postback': PostbackAction,
+            'message': MessageAction,
+            'uri': URIAction,
+            'datetimepicker': DatetimePickerAction
+        }
+    )
+    return action_obj
+
+
+def get_actions(actions):
+    """Get actions."""
+    new_actions = []
+    if actions:
+        for action in actions:
+            action_obj = get_action(action)
+            if action_obj:
+                new_actions.append(action_obj)
+
+    return new_actions
+
+
+class Action(with_metaclass(ABCMeta, Base)):
+    """Abstract base class of Action."""
+
+    def __init__(self, **kwargs):
+        """__init__ method.
+
+        :param kwargs:
+        """
+        super(Action, self).__init__(**kwargs)
+
+        self.type = None
+
+
+class PostbackAction(Action):
+    """PostbackAction.
+
+    https://developers.line.me/en/docs/messaging-api/reference/#postback-action
+
+    When a control associated with this action is tapped,
+    a postback event is returned via webhook with the specified string in the data property.
+    """
+
+    def __init__(self, label=None, data=None, text=None, **kwargs):
+        """__init__ method.
+
+        :param str label: Label for the action.
+        :param str data: String returned via webhook
+            in the postback.data property of the postback event.
+        :param str text: Text displayed in the chat as a message sent by
+            the user when the action is performed. Returned from the server through a webhook.
+        :param kwargs:
+        """
+        super(PostbackAction, self).__init__(**kwargs)
+
+        self.type = 'postback'
+        self.label = label
+        self.data = data
+        self.text = text
+
+
+class MessageAction(Action):
+    """MessageAction.
+
+    https://developers.line.me/en/docs/messaging-api/reference/#message-action
+
+    When a control associated with this action is tapped,
+    the string in the text property is sent as a message from the user.
+    """
+
+    def __init__(self, label=None, text=None, **kwargs):
+        """__init__ method.
+
+        :param str label: Label for the action.
+        :param str text: Text sent when the action is performed.
+        :param kwargs:
+        """
+        super(MessageAction, self).__init__(**kwargs)
+
+        self.type = 'message'
+        self.label = label
+        self.text = text
+
+
+class URIAction(Action):
+    """URIAction.
+
+    https://developers.line.me/en/docs/messaging-api/reference/#uri-action
+
+    When a control associated with this action is tapped,
+    the URI specified in the uri property is opened.
+    """
+
+    def __init__(self, label=None, uri=None, **kwargs):
+        """__init__ method.
+
+        :param str label: Label for the action
+            Max: 20 characters
+        :param str uri: URI opened when the action is performed.
+        :param kwargs:
+        """
+        super(URIAction, self).__init__(**kwargs)
+
+        self.type = 'uri'
+        self.label = label
+        self.uri = uri
+
+
+class DatetimePickerAction(Action):
+    """DatetimePickerAction.
+
+    https://developers.line.me/en/docs/messaging-api/reference/#datetime-picker-action
+
+    When a control associated with this action is tapped,
+    a postback event is returned via webhook with the date and time
+    selected by the user from the date and time selection dialog.
+    The datetime picker action does not support time zones.
+    """
+
+    def __init__(self, label=None, data=None, mode=None,
+                 initial=None, max=None, min=None, **kwargs):
+        """__init__ method.
+
+        :param str label: Label for the action
+        :param str data: String returned via webhook
+            in the postback.data property of the postback event
+        :param str mode: Action mode
+            date: Pick date
+            time: Pick time
+            datetime: Pick date and time
+        :param str initial: Initial value of date or time
+        :param str max: Largest date or time value that can be selected.
+            Must be greater than the min value.
+        :param str min: Smallest date or time value that can be selected.
+            Must be less than the max value.
+        :param kwargs:
+        """
+        super(DatetimePickerAction, self).__init__(**kwargs)
+
+        self.type = 'datetimepicker'
+        self.label = label
+        self.data = data
+        self.mode = mode
+        self.initial = initial
+        self.max = max
+        self.min = min
diff --git a/linebot/models/responses.py b/linebot/models/responses.py
index bea4be0..8cd6e08 100644
--- a/linebot/models/responses.py
+++ b/linebot/models/responses.py
@@ -17,40 +17,7 @@
 from __future__ import unicode_literals
 
 from .base import Base
-
-
-class RichMenuResponse(Base):
-    """RichMenuResponse.
-
-    https://developers.line.me/en/docs/messaging-api/reference/#rich-menu-response-object
-    """
-
-    def __init__(self, rich_menu_id=None, size=None, selected=None, name=None, chatBarText=None,
-                 areas=None, **kwargs):
-        """__init__ method.
-
-        :param str id: Rich Menu ID
-        :param size: size object which describe the rich menu displayed in the chat.
-                      Rich menu images must be one of the following sizes: 2500x1686, 2500x843.
-        :type size: T <= :py:class:`linebot.models.rich_menu.RichMenuBound`
-        :param bool selected: true to display the rich menu by default. Otherwise, false.
-        :param str name: Name of the rich menu.
-                         Maximum of 300 characters.
-        :param str chatBarText: Text displayed in the chat bar.
-                                Maximum of 14 characters.
-        :param areas: Array of area objects which define coordinates and size of tappable areas.
-                      Maximum of 20 area objects.
-        :type areas: T <= :py:class:`linebot.models.rich_menu.RichMenuArea`
-        :param kwargs:
-        """
-        super(RichMenuResponse, self).__init__(**kwargs)
-
-        self.rich_menu_id = rich_menu_id
-        self.size = size
-        self.selected = selected
-        self.name = name
-        self.chatBarText = chatBarText
-        self.areas = areas
+from .rich_menu import RichMenuSize, RichMenuArea
 
 
 class Profile(Base):
@@ -99,7 +66,7 @@ class MemberIds(Base):
         self.next = next
 
 
-class MessageContent(object):
+class Content(object):
     """MessageContent.
 
     https://devdocs.line.me/ja/#get-content
@@ -142,3 +109,44 @@ class MessageContent(object):
         :return:
         """
         return self.response.iter_content(chunk_size=chunk_size)
+
+
+class RichMenuResponse(Base):
+    """RichMenuResponse.
+
+    https://developers.line.me/en/docs/messaging-api/reference/#rich-menu-response-object
+    """
+
+    def __init__(self, rich_menu_id=None, size=None, selected=None, name=None,
+                 chat_bar_text=None, areas=None, **kwargs):
+        """__init__ method.
+
+        :param str id: Rich Menu ID
+        :param size: size object which describe the rich menu displayed in the chat.
+            Rich menu images must be one of the following sizes: 2500x1686, 2500x843.
+        :type size: :py:class:`linebot.models.rich_menu.RichMenuSize`
+        :param bool selected: true to display the rich menu by default. Otherwise, false.
+        :param str name: Name of the rich menu.
+            Maximum of 300 characters.
+        :param str chat_bar_text: Text displayed in the chat bar.
+            Maximum of 14 characters.
+        :param areas: Array of area objects which define coordinates and size of tappable areas.
+            Maximum of 20 area objects.
+        :type areas: list[T <= :py:class:`linebot.models.rich_menu.RichMenuArea`]
+        :param kwargs:
+        """
+        super(RichMenuResponse, self).__init__(**kwargs)
+
+        self.rich_menu_id = rich_menu_id
+        self.size = self.get_or_new_from_json_dict(size, RichMenuSize)
+        self.selected = selected
+        self.name = name
+        self.chat_bar_text = chat_bar_text
+
+        new_areas = []
+        if areas:
+            for area in areas:
+                new_areas.append(
+                    self.get_or_new_from_json_dict(area, RichMenuArea)
+                )
+        self.areas = new_areas
diff --git a/linebot/models/rich_menu.py b/linebot/models/rich_menu.py
index 8ebf3fa..c4db446 100644
--- a/linebot/models/rich_menu.py
+++ b/linebot/models/rich_menu.py
@@ -20,6 +20,7 @@ from abc import ABCMeta
 
 from future.utils import with_metaclass
 
+from .actions import get_action
 from .base import Base
 
 
@@ -27,64 +28,56 @@ class RichMenu(with_metaclass(ABCMeta, Base)):
     """RichMenu.
 
     https://developers.line.me/en/docs/messaging-api/reference/#rich-menu-object
-
-    This is the template to create a richmenu before posting to remote server,
-    or a template to receive rich menu query result from remote server.
     """
 
-    def __init__(self, size=None, selected=None, name=None, chatBarText=None,
+    def __init__(self, size=None, selected=None, name=None, chat_bar_text=None,
                  areas=None, **kwargs):
         """__init__ method.
 
         :param size: size object which describe the rich menu displayed in the chat.
-                      Rich menu images must be one of the following sizes: 2500x1686, 2500x843.
-        :type size: T <= :py:class:`linebot.models.rich_menu.RichMenuBound`
+            Rich menu images must be one of the following sizes: 2500x1686, 2500x843.
+        :type size: :py:class:`linebot.models.rich_menu.RichMenuSize`
         :param bool selected: true to display the rich menu by default. Otherwise, false.
         :param str name: Name of the rich menu.
-                         Maximum of 300 characters.
+            Maximum of 300 characters.
         :param str chatBarText: Text displayed in the chat bar.
                                 Maximum of 14 characters.
         :param areas: Array of area objects which define coordinates and size of tappable areas.
                       Maximum of 20 area objects.
-        :type areas: T <= :py:class:`linebot.models.rich_menu.RichMenuArea`
+        :type areas: list[T <= :py:class:`linebot.models.rich_menu.RichMenuArea`]
         :param kwargs:
         """
         super(RichMenu, self).__init__(**kwargs)
 
-        self.size = size  # RichMenuBound
+        self.size = self.get_or_new_from_json_dict(size, RichMenuSize)
         self.selected = selected
         self.name = name
-        self.chatBarText = chatBarText
-        self.areas = []
-        if not isinstance(areas, (list, tuple)):
-            areas = [areas]
+        self.chat_bar_text = chat_bar_text
 
-        self.areas = [area.as_json_dict() for area in areas]  # RichMenuArea
+        new_areas = []
+        if areas:
+            for area in areas:
+                new_areas.append(
+                    self.get_or_new_from_json_dict(area, RichMenuArea)
+                )
+        self.areas = new_areas
 
 
-class RichMenuBound(with_metaclass(ABCMeta, Base)):
-    """RichMenuBound.
+class RichMenuSize(with_metaclass(ABCMeta, Base)):
+    """RichMenuSize.
 
-    https://developers.line.me/en/docs/messaging-api/reference/#bounds-object
     https://developers.line.me/en/docs/messaging-api/reference/#size-object
-
-    This is the template to describe the boundaries of the area in pixels.
-    If x and y are equal to default value, the bound object is equal to size object.
     """
 
-    def __init__(self, x=None, y=None, width=None, height=None, **kwargs):
+    def __init__(self, width=None, height=None, **kwargs):
         """__init__ method.
 
-        :param int x: Horizontal position relative to the top-left corner of the area.
-        :param int y: Vertical position relative to the top-left corner of the area.
-        :param int width: Width of the area.
-        :param int height: Height of the area.
+        :param int width: Width of the rich menu. Must be 2500.
+        :param int height: Height of the rich menu. Possible values: 1686, 843.
         :param kwargs:
         """
-        super(RichMenuBound, self).__init__(id=id, **kwargs)
+        super(RichMenuSize, self).__init__(**kwargs)
 
-        self.x = x
-        self.y = y
         self.width = width
         self.height = height
 
@@ -93,23 +86,41 @@ class RichMenuArea(with_metaclass(ABCMeta, Base)):
     """RichMenuArea.
 
     https://developers.line.me/en/docs/messaging-api/reference/#area-object
-
-    Array of area objects which define the coordinates and size of tappable areas.
     """
 
     def __init__(self, bounds=None, action=None, **kwargs):
         """__init__ method.
 
-        :param bounds: Object describing the boundaries of the area in pixels.
-        :type areas: T <= :py:class:`linebot.models.template.RichMenuBound`
-        :param action: Action performed when the area is tapped.
-        :type action: T <= :py:class:`linebot.models.template.PostbackTemplateAction` |
-                      T <= :py:class:`linebot.models.template.MessageTemplateAction` |
-                      T <= :py:class:`linebot.models.template.URITemplateAction` |
-                      T <= :py:class:`linebot.models.template.DatetimePickerTemplateAction`
+        :param bounds: Object describing the boundaries of the area in pixels. See bounds object.
+        :type bounds: :py:class:`linebot.models.rich_menu.RichMenuBound`
+        :param action: Action performed when the area is tapped. See action objects.
+        :type action: T <= :py:class:`linebot.models.actions.Action`
         :param kwargs:
         """
-        super(RichMenuArea, self).__init__(id=id, **kwargs)
+        super(RichMenuArea, self).__init__(**kwargs)
+
+        self.bounds = self.get_or_new_from_json_dict(bounds, RichMenuBounds)
+        self.action = get_action(action)
 
-        self.action = action
-        self.bounds = bounds  # RichMenuBound
+
+class RichMenuBounds(with_metaclass(ABCMeta, Base)):
+    """RichMenuBounds.
+
+    https://developers.line.me/en/docs/messaging-api/reference/#bounds-object
+    """
+
+    def __init__(self, x=None, y=None, width=None, height=None, **kwargs):
+        """__init__ method.
+
+        :param int x: Horizontal position relative to the top-left corner of the area.
+        :param int y: Vertical position relative to the top-left corner of the area.
+        :param int width: Width of the area.
+        :param int height: Height of the area.
+        :param kwargs:
+        """
+        super(RichMenuBounds, self).__init__(**kwargs)
+
+        self.x = x
+        self.y = y
+        self.width = width
+        self.height = height
diff --git a/linebot/models/template.py b/linebot/models/template.py
index f45b044..0e8efb5 100644
--- a/linebot/models/template.py
+++ b/linebot/models/template.py
@@ -20,33 +20,11 @@ from abc import ABCMeta
 
 from future.utils import with_metaclass
 
+from .actions import get_action, get_actions
 from .base import Base
 from .send_messages import SendMessage
 
 
-def _get_action(action):
-    action_obj = Base.get_or_new_from_json_dict_with_types(
-        action, {
-            'postback': PostbackTemplateAction,
-            'message': MessageTemplateAction,
-            'uri': URITemplateAction,
-            'datetimepicker': DatetimePickerTemplateAction,
-        }
-    )
-    return action_obj
-
-
-def _get_actions(actions):
-    new_actions = []
-    if actions:
-        for action in actions:
-            action_obj = _get_action(action)
-            if action_obj:
-                new_actions.append(action_obj)
-
-    return new_actions
-
-
 class TemplateSendMessage(SendMessage):
     """TemplateSendMessage.
 
@@ -132,7 +110,7 @@ class ButtonsTemplate(Template):
             Specify a RGB color value.
         :param actions: Action when tapped.
             Max: 4
-        :type actions: list[T <= :py:class:`linebot.models.template.TemplateAction`]
+        :type actions: list[T <= :py:class:`linebot.models.actions.Action`]
         :param kwargs:
         """
         super(ButtonsTemplate, self).__init__(**kwargs)
@@ -144,7 +122,7 @@ class ButtonsTemplate(Template):
         self.image_aspect_ratio = image_aspect_ratio
         self.image_size = image_size
         self.image_background_color = image_background_color
-        self.actions = _get_actions(actions)
+        self.actions = get_actions(actions)
 
 
 class ConfirmTemplate(Template):
@@ -162,14 +140,14 @@ class ConfirmTemplate(Template):
             Max: 240 characters
         :param actions: Action when tapped.
             Max: 2
-        :type actions: list[T <= :py:class:`linebot.models.template.TemplateAction`]
+        :type actions: list[T <= :py:class:`linebot.models.actions.Action`]
         :param kwargs:
         """
         super(ConfirmTemplate, self).__init__(**kwargs)
 
         self.type = 'confirm'
         self.text = text
-        self.actions = _get_actions(actions)
+        self.actions = get_actions(actions)
 
 
 class CarouselTemplate(Template):
@@ -269,7 +247,7 @@ class CarouselColumn(Base):
             Specify a RGB color value.
         :param actions: Action when tapped.
             Max: 3
-        :type actions: list[T <= :py:class:`linebot.models.template.TemplateAction`]
+        :type actions: list[T <= :py:class:`linebot.models.actions.Action`]
         :param kwargs:
         """
         super(CarouselColumn, self).__init__(**kwargs)
@@ -278,7 +256,7 @@ class CarouselColumn(Base):
         self.title = title
         self.thumbnail_image_url = thumbnail_image_url
         self.image_background_color = image_background_color
-        self.actions = _get_actions(actions)
+        self.actions = get_actions(actions)
 
 
 class ImageCarouselColumn(Base):
@@ -298,144 +276,10 @@ class ImageCarouselColumn(Base):
             Max: 1 MB
         :param action: Action when image is tapped
             Max: 5
-        :type action: T <= :py:class:`linebot.models.template.TemplateAction`
+        :type action: T <= :py:class:`linebot.models.actions.Action`
         :param kwargs:
         """
         super(ImageCarouselColumn, self).__init__(**kwargs)
 
         self.image_url = image_url
-        self.action = _get_action(action)
-
-
-class TemplateAction(with_metaclass(ABCMeta, Base)):
-    """Abstract Base Class of TemplateAction."""
-
-    def __init__(self, **kwargs):
-        """__init__ method.
-
-        :param kwargs:
-        """
-        super(TemplateAction, self).__init__(**kwargs)
-
-        self.type = None
-
-
-class PostbackTemplateAction(TemplateAction):
-    """PostbackTemplateAction.
-
-    https://devdocs.line.me/en/#template-messages
-
-    When this action is tapped, a postback event is returned
-    via webhook with the specified string in the data field.
-
-    If you have included the text field,
-    the string in the text field is sent as a message from the user.
-    """
-
-    def __init__(self, label=None, data=None, text=None, **kwargs):
-        """__init__ method.
-
-        :param str label: Label for the action.
-            Max: 20 characters
-        :param str data: String returned via webhook in the postback.data property
-            of the postback event.
-            Max: 300 characters
-        :param str text: Text sent when the action is performed.
-            Max: 300 characters
-        :param kwargs:
-        """
-        super(PostbackTemplateAction, self).__init__(**kwargs)
-
-        self.type = 'postback'
-        self.label = label
-        self.data = data
-        self.text = text
-
-
-class MessageTemplateAction(TemplateAction):
-    """MessageTemplateAction.
-
-    https://devdocs.line.me/en/#template-messages
-
-    When this action is tapped,
-    the string in the text field is sent as a message from the user.
-    """
-
-    def __init__(self, label=None, text=None, **kwargs):
-        """__init__ method.
-
-        :param str label: Label for the action.
-            Max: 20 characters
-        :param str text: Text sent when the action is performed.
-            Max: 300 characters
-        :param kwargs:
-        """
-        super(MessageTemplateAction, self).__init__(**kwargs)
-
-        self.type = 'message'
-        self.label = label
-        self.text = text
-
-
-class URITemplateAction(TemplateAction):
-    """URITemplateAction.
-
-    https://devdocs.line.me/en/#template-messages
-
-    When this action is tapped, the URI specified in the uri field is opened.
-    """
-
-    def __init__(self, label=None, uri=None, **kwargs):
-        """__init__ method.
-
-        :param str label: Label for the action
-            Max: 20 characters
-        :param str uri: URI opened when the action is performed.
-            http, https, tel
-        :param kwargs:
-        """
-        super(URITemplateAction, self).__init__(**kwargs)
-
-        self.type = 'uri'
-        self.label = label
-        self.uri = uri
-
-
-class DatetimePickerTemplateAction(TemplateAction):
-    """DatetimePickerTemplateAction.
-
-    https://devdocs.line.me/en/#template-messages
-
-    When this action is tapped, a postback event is returned via webhook
-    with the date and time selected by the user from the date and time selection dialog.
-    """
-
-    def __init__(self, label=None, data=None, mode=None,
-                 initial=None, max=None, min=None, **kwargs):
-        """__init__ method.
-
-        :param str label: Label for the action
-            Max: 20 characters
-        :param str data: String returned via webhook
-            in the postback.data property of the postback event
-            Max: 300 characters
-        :param str mode: 	Action mode
-            date: Pick date
-            time: Pick time
-            datetime: Pick date and time
-        :param str initial: Initial value of date or time
-        :param str max: Largest date or time value that can be selected.
-            Must be greater than the min value.
-        :param str min: Smallest date or time value that can be selected.
-            Must be less than the max value.
-        :param kwargs:
-        """
-        super(DatetimePickerTemplateAction, self).__init__(**kwargs)
-
-        self.type = 'datetimepicker'
-        self.label = label
-        self.data = data
-        self.mode = mode
-        self.initial = initial
-        self.max = max
-        self.min = min
+        self.action = get_action(action)


Test patch:
diff --git a/tests/api/test_rich_menu.py b/tests/api/test_rich_menu.py
index a7cc8c8..3654a24 100644
--- a/tests/api/test_rich_menu.py
+++ b/tests/api/test_rich_menu.py
@@ -23,12 +23,11 @@ from linebot import (
 )
 from linebot.models import (
     URITemplateAction,
-    RichMenu, RichMenuBound, RichMenuArea
+    RichMenu, RichMenuSize, RichMenuArea, RichMenuBounds
 )
 
 
 class TestLineBotApi(unittest.TestCase):
-
     maxDiff = None
 
     def setUp(self):
@@ -37,91 +36,139 @@ class TestLineBotApi(unittest.TestCase):
         self.rich_menu_id = 'richmenu-0000000000'
         self.user_id = 'userid'
         self.rich_menu = RichMenu(
-                size=RichMenuBound(
-                    width=2500,
-                    height=1686
-                ),
-                selected=False,
-                name="nice richmenu",
-                chatBarText="touch me",
-                areas=[
-                    RichMenuArea(
-                        RichMenuBound(
-                            x=0,
-                            y=0,
-                            width=833,
-                            height=843
-                        ),
-                        URITemplateAction(
-                            uri='line://nv/location'
-                        )
+            size=RichMenuSize(
+                width=2500,
+                height=1686
+            ),
+            selected=False,
+            name="nice richmenu",
+            chatBarText="touch me",
+            areas=[
+                RichMenuArea(
+                    RichMenuBounds(
+                        x=0,
+                        y=0,
+                        width=833,
+                        height=843
+                    ),
+                    URITemplateAction(
+                        uri='line://nv/location'
                     )
-                ]
-            )
+                )
+            ]
+        )
 
     @responses.activate
-    def test_delete_rich_menu(self):
+    def test_get_rich_menu(self):
         responses.add(
-            responses.DELETE,
-            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/richmenu/{rich_menu_id}'.format(
-                rich_menu_id=self.rich_menu_id
-            ),
-            json={}, status=200
+            responses.GET,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/richmenu/rich_menu_id',
+            json={
+                "richMenuId": "rich_menu_id",
+                "size": {
+                    "width": 2500,
+                    "height": 1686
+                },
+                "selected": False,
+                "name": "name",
+                "chatBarText": "chatBarText",
+                "areas": [
+                    {
+                        "bounds": {
+                            "x": 0,
+                            "y": 0,
+                            "width": 2500,
+                            "height": 1686
+                        },
+                        "action": {
+                            "type": "postback",
+                            "data": "action=buy&itemid=123"
+                        }
+                    }
+                ]
+            },
+            status=200
         )
 
-        self.tested.delete_rich_menu(self.rich_menu_id)
+        rich_menu = self.tested.get_rich_menu('rich_menu_id')
+        print(rich_menu)
 
         request = responses.calls[0].request
-        self.assertEqual(request.method, 'DELETE')
+        self.assertEqual(request.method, 'GET')
         self.assertEqual(
             request.url,
-            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/richmenu/{rich_menu_id}'.format(
-                rich_menu_id=self.rich_menu_id
-            )
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/richmenu/rich_menu_id'
         )
 
+        self.assertEqual(rich_menu.rich_menu_id, 'rich_menu_id')
+        self.assertEqual(rich_menu.size.width, 2500)
+        self.assertEqual(rich_menu.size.height, 1686)
+        self.assertEqual(rich_menu.selected, False)
+        self.assertEqual(rich_menu.name, 'name')
+        self.assertEqual(rich_menu.chat_bar_text, 'chatBarText')
+        self.assertEqual(rich_menu.areas[0].bounds.x, 0)
+        self.assertEqual(rich_menu.areas[0].bounds.y, 0)
+        self.assertEqual(rich_menu.areas[0].bounds.width, 2500)
+        self.assertEqual(rich_menu.areas[0].bounds.height, 1686)
+        self.assertEqual(rich_menu.areas[0].action.type, 'postback')
+        self.assertEqual(rich_menu.areas[0].action.data, 'action=buy&itemid=123')
+
     @responses.activate
-    def test_link_rich_menu_to_user(self):
+    def test_create_rich_menu(self):
         responses.add(
             responses.POST,
-            LineBotApi.DEFAULT_API_ENDPOINT +
-            '/v2/bot/user/{user_id}/richmenu/{rich_menu_id}'.format(
-                user_id=self.user_id,
-                rich_menu_id=self.rich_menu_id
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/richmenu',
+            json={"richMenuId": "richMenuId"}, status=200
+        )
+
+        rich_menu = RichMenu(
+            size=RichMenuSize(
+                width=2500,
+                height=1686
             ),
-            json={}, status=200
+            selected=False,
+            name="nice richmenu",
+            chatBarText="touch me",
+            areas=[
+                RichMenuArea(
+                    RichMenuBounds(
+                        x=0,
+                        y=0,
+                        width=833,
+                        height=843
+                    ),
+                    URITemplateAction(
+                        uri='line://nv/location'
+                    )
+                )
+            ]
         )
 
-        self.tested.link_rich_menu_to_user(self.user_id, self.rich_menu_id)
+        result = self.tested.create_rich_menu(rich_menu)
 
         request = responses.calls[0].request
         self.assertEqual(request.method, 'POST')
         self.assertEqual(
             request.url,
-            LineBotApi.DEFAULT_API_ENDPOINT +
-            '/v2/bot/user/{user_id}/richmenu/{rich_menu_id}'.format(
-                user_id=self.user_id,
-                rich_menu_id=self.rich_menu_id
-            )
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/richmenu'
         )
+        self.assertEqual(result, "richMenuId")
 
     @responses.activate
-    def test_unlink_rich_menu_from_user(self):
+    def test_delete_rich_menu(self):
         responses.add(
             responses.DELETE,
-            LineBotApi.DEFAULT_API_ENDPOINT +
-            '/v2/bot/user/{user_id}/richmenu'.format(user_id=self.user_id),
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/richmenu/rich_menu_id',
             json={}, status=200
         )
 
-        self.tested.unlink_rich_menu_from_user(self.user_id)
+        self.tested.delete_rich_menu('rich_menu_id')
 
         request = responses.calls[0].request
         self.assertEqual(request.method, 'DELETE')
         self.assertEqual(
             request.url,
-            LineBotApi.DEFAULT_API_ENDPOINT +
-            '/v2/bot/user/{user_id}/richmenu'.format(user_id=self.user_id)
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/richmenu/rich_menu_id'
         )
 
     @responses.activate
@@ -129,53 +176,112 @@ class TestLineBotApi(unittest.TestCase):
         responses.add(
             responses.GET,
             LineBotApi.DEFAULT_API_ENDPOINT +
-            '/v2/bot/user/{user_id}/richmenu'.format(user_id=self.user_id),
-            json={}, status=200
+            '/v2/bot/user/user_id/richmenu',
+            json={"richMenuId": "richMenuId"}, status=200
         )
 
-        self.tested.get_rich_menu_id_of_user(self.user_id)
+        result = self.tested.get_rich_menu_id_of_user('user_id')
 
         request = responses.calls[0].request
         self.assertEqual(request.method, 'GET')
         self.assertEqual(
             request.url,
-            LineBotApi.DEFAULT_API_ENDPOINT +
-            '/v2/bot/user/{user_id}/richmenu'.format(user_id=self.user_id)
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/user/user_id/richmenu'
         )
+        self.assertEqual(result, "richMenuId")
 
     @responses.activate
-    def test_get_rich_menu_list(self):
+    def test_link_rich_menu_to_user(self):
         responses.add(
-            responses.GET,
-            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/richmenu/list',
-            json={'richmenus': []}, status=200
+            responses.POST,
+            LineBotApi.DEFAULT_API_ENDPOINT +
+            '/v2/bot/user/user_id/richmenu/rich_menu_id',
+            json={}, status=200
         )
 
-        self.tested.get_rich_menu_list()
+        self.tested.link_rich_menu_to_user('user_id', 'rich_menu_id')
 
         request = responses.calls[0].request
-        self.assertEqual(request.method, 'GET')
+        self.assertEqual(request.method, 'POST')
         self.assertEqual(
             request.url,
-            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/richmenu/list'
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/user/user_id/richmenu/rich_menu_id'
         )
 
     @responses.activate
-    def test_create_rich_menu(self):
+    def test_unlink_rich_menu_from_user(self):
         responses.add(
-            responses.POST,
-            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/richmenu',
+            responses.DELETE,
+            LineBotApi.DEFAULT_API_ENDPOINT +
+            '/v2/bot/user/user_id/richmenu',
             json={}, status=200
         )
 
-        self.tested.create_rich_menu(self.rich_menu)
+        self.tested.unlink_rich_menu_from_user('user_id')
 
         request = responses.calls[0].request
-        self.assertEqual(request.method, 'POST')
+        self.assertEqual(request.method, 'DELETE')
         self.assertEqual(
             request.url,
-            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/richmenu'
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/user/user_id/richmenu'
+        )
+
+    @responses.activate
+    def test_get_rich_menu_list(self):
+        responses.add(
+            responses.GET,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/richmenu/list',
+            json={
+                "richmenus": [
+                    {
+                        "richMenuId": "rich_menu_id",
+                        "size": {
+                            "width": 2500,
+                            "height": 1686
+                        },
+                        "selected": False,
+                        "name": "name",
+                        "chatBarText": "chatBarText",
+                        "areas": [
+                            {
+                                "bounds": {
+                                    "x": 0,
+                                    "y": 0,
+                                    "width": 2500,
+                                    "height": 1686
+                                },
+                                "action": {
+                                    "type": "postback",
+                                    "data": "action=buy&itemid=123"
+                                }
+                            }
+                        ]
+                    }
+                ]
+            },
+            status=200
+        )
+
+        rich_menus = self.tested.get_rich_menu_list()
+
+        request = responses.calls[0].request
+        self.assertEqual(request.method, 'GET')
+        self.assertEqual(
+            request.url,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/richmenu/list'
         )
+        self.assertEqual(rich_menus[0].rich_menu_id, 'rich_menu_id')
+        self.assertEqual(rich_menus[0].size.width, 2500)
+        self.assertEqual(rich_menus[0].size.height, 1686)
+        self.assertEqual(rich_menus[0].selected, False)
+        self.assertEqual(rich_menus[0].name, 'name')
+        self.assertEqual(rich_menus[0].chat_bar_text, 'chatBarText')
+        self.assertEqual(rich_menus[0].areas[0].bounds.x, 0)
+        self.assertEqual(rich_menus[0].areas[0].bounds.y, 0)
+        self.assertEqual(rich_menus[0].areas[0].bounds.width, 2500)
+        self.assertEqual(rich_menus[0].areas[0].bounds.height, 1686)
+        self.assertEqual(rich_menus[0].areas[0].action.type, 'postback')
+        self.assertEqual(rich_menus[0].areas[0].action.data, 'action=buy&itemid=123')
 
 
 if __name__ == '__main__':
diff --git a/tests/api/test_send_template_message.py b/tests/api/test_send_template_message.py
index 37e84fe..4e42c85 100644
--- a/tests/api/test_send_template_message.py
+++ b/tests/api/test_send_template_message.py
@@ -24,15 +24,14 @@ from linebot import (
 )
 from linebot.models import (
     TemplateSendMessage, ButtonsTemplate,
-    PostbackTemplateAction, MessageTemplateAction,
-    URITemplateAction, DatetimePickerTemplateAction,
+    PostbackAction, MessageAction,
+    URIAction, DatetimePickerAction,
     ConfirmTemplate, CarouselTemplate, CarouselColumn,
     ImageCarouselTemplate, ImageCarouselColumn
 )
 
 
 class TestLineBotApi(unittest.TestCase):
-
     maxDiff = None
 
     def setUp(self):
@@ -44,14 +43,14 @@ class TestLineBotApi(unittest.TestCase):
                 thumbnail_image_url='https://example.com/image.jpg',
                 title='Menu', text='Please select',
                 actions=[
-                    PostbackTemplateAction(
+                    PostbackAction(
                         label='postback', text='postback text',
                         data='action=buy&itemid=1'
                     ),
-                    MessageTemplateAction(
+                    MessageAction(
                         label='message', text='message text'
                     ),
-                    URITemplateAction(
+                    URIAction(
                         label='uri', uri='http://example.com/'
                     )
                 ]
@@ -96,11 +95,11 @@ class TestLineBotApi(unittest.TestCase):
             template=ConfirmTemplate(
                 text='Are you sure?',
                 actions=[
-                    PostbackTemplateAction(
+                    PostbackAction(
                         label='postback', text='postback text',
                         data='action=buy&itemid=1'
                     ),
-                    MessageTemplateAction(
+                    MessageAction(
                         label='message', text='message text'
                     )
                 ]
@@ -138,14 +137,14 @@ class TestLineBotApi(unittest.TestCase):
                                             '/item1.jpg',
                         title='this is menu1', text='description1',
                         actions=[
-                            PostbackTemplateAction(
+                            PostbackAction(
                                 label='postback1', text='postback text1',
                                 data='action=buy&itemid=1'
                             ),
-                            MessageTemplateAction(
+                            MessageAction(
                                 label='message1', text='message text1'
                             ),
-                            URITemplateAction(
+                            URIAction(
                                 label='uri1',
                                 uri='http://example.com/1'
                             )
@@ -157,14 +156,14 @@ class TestLineBotApi(unittest.TestCase):
                         image_background_color='#000000',
                         title='this is menu2', text='description2',
                         actions=[
-                            PostbackTemplateAction(
+                            PostbackAction(
                                 label='postback2', text='postback text2',
                                 data='action=buy&itemid=2'
                             ),
-                            MessageTemplateAction(
+                            MessageAction(
                                 label='message2', text='message text2'
                             ),
-                            URITemplateAction(
+                            URIAction(
                                 label='uri2',
                                 uri='http://example.com/2'
                             )
@@ -175,7 +174,7 @@ class TestLineBotApi(unittest.TestCase):
                                             '/item3.jpg',
                         title='this is menu3', text='description3',
                         actions=[
-                            DatetimePickerTemplateAction(
+                            DatetimePickerAction(
                                 label="datetime picker date",
                                 data="action=sell&itemid=2&mode=date",
                                 mode="date",
@@ -183,7 +182,7 @@ class TestLineBotApi(unittest.TestCase):
                                 min="2011-06-23",
                                 max="2017-09-08"
                             ),
-                            DatetimePickerTemplateAction(
+                            DatetimePickerAction(
                                 label="datetime picker time",
                                 data="action=sell&itemid=2&mode=time",
                                 mode="time",
@@ -191,7 +190,7 @@ class TestLineBotApi(unittest.TestCase):
                                 min="00:00",
                                 max="23:59"
                             ),
-                            DatetimePickerTemplateAction(
+                            DatetimePickerAction(
                                 label="datetime picker datetime",
                                 data="action=sell&itemid=2&mode=datetime",
                                 mode="datetime",
@@ -310,7 +309,7 @@ class TestLineBotApi(unittest.TestCase):
                     ImageCarouselColumn(
                         image_url='https://example.com/'
                                   'item1.jpg',
-                        action=PostbackTemplateAction(
+                        action=PostbackAction(
                             label='postback1',
                             data='action=buy&itemid=1'
                         )
@@ -318,7 +317,7 @@ class TestLineBotApi(unittest.TestCase):
                     ImageCarouselColumn(
                         image_url='https://example.com'
                                   '/item2.jpg',
-                        action=MessageTemplateAction(
+                        action=MessageAction(
                             label='message2',
                             text='message text2'
                         )
@@ -326,7 +325,7 @@ class TestLineBotApi(unittest.TestCase):
                     ImageCarouselColumn(
                         image_url='https://example.com/'
                                   'item3.jpg',
-                        action=URITemplateAction(
+                        action=URIAction(
                             label='uri1',
                             uri='https://example.com/1'
                         )