diff --git a/discord/abc.py b/discord/abc.py
index 961545ed6..da1636f27 100644
--- a/discord/abc.py
+++ b/discord/abc.py
@@ -62,6 +62,7 @@ if TYPE_CHECKING:
     from .channel import CategoryChannel
     from .embeds import Embed
     from .message import Message, MessageReference
+    from .enums import InviteTarget
 
     SnowflakeTime = Union["Snowflake", datetime]
 
@@ -1013,6 +1014,9 @@ class GuildChannel:
         max_uses: int = 0,
         temporary: bool = False,
         unique: bool = True,
+        target_type: Optional[InviteTarget] = None,
+        target_user: Optional[User] = None,
+        target_application_id: Optional[int] = None
     ) -> Invite:
         """|coro|
 
@@ -1038,6 +1042,20 @@ class GuildChannel:
             invite.
         reason: Optional[:class:`str`]
             The reason for creating this invite. Shows up on the audit log.
+        target_type: Optional[:class:`InviteTarget`]
+            The type of target for the voice channel invite, if any.
+            
+            .. versionadded:: 2.0
+        
+        target_user: Optional[:class:`User`]
+            The user whose stream to display for this invite, required if `target_type` is `TargetType.stream`. The user must be streaming in the channel.
+
+            .. versionadded:: 2.0
+
+        target_application_id:: Optional[:class:`int`]
+            The id of the embedded application for the invite, required if `target_type` is `TargetType.embedded_application`.
+
+            .. versionadded:: 2.0
 
         Raises
         -------
@@ -1060,6 +1078,9 @@ class GuildChannel:
             max_uses=max_uses,
             temporary=temporary,
             unique=unique,
+            target_type=target_type.value if target_type else None,
+            target_user_id=target_user.id if target_user else None,
+            target_application_id=target_application_id
         )
         return Invite.from_incomplete(data=data, state=self._state)
 
diff --git a/discord/appinfo.py b/discord/appinfo.py
index 40a4e4029..a7f8da82f 100644
--- a/discord/appinfo.py
+++ b/discord/appinfo.py
@@ -22,13 +22,22 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 DEALINGS IN THE SOFTWARE.
 """
 
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Optional
+
 from . import utils
-from .user import User
 from .asset import Asset
-from .team import Team
+
+if TYPE_CHECKING:
+    from .guild import Guild
+    from .types.appinfo import AppInfo as AppInfoPayload, PartialAppInfo as PartialAppInfoPayload
+
+    from .state import ConnectionState
 
 __all__ = (
     'AppInfo',
+    'PartialAppInfo',
 )
 
 
@@ -49,7 +58,7 @@ class AppInfo:
 
         .. versionadded:: 1.3
 
-    description: Optional[:class:`str`]
+    description: :class:`str`
         The application description.
     bot_public: :class:`bool`
         Whether the bot can be invited by anyone or if it is locked
@@ -122,9 +131,10 @@ class AppInfo:
         'privacy_policy_url',
     )
 
-    def __init__(self, state, data):
-        self._state = state
+    def __init__(self, state, data: AppInfoPayload):
+        from .team import Team
 
+        self._state = state
         self.id = int(data['id'])
         self.name = data['name']
         self.description = data['description']
@@ -132,7 +142,7 @@ class AppInfo:
         self.rpc_origins = data['rpc_origins']
         self.bot_public = data['bot_public']
         self.bot_require_code_grant = data['bot_require_code_grant']
-        self.owner = User(state=self._state, data=data['owner'])
+        self.owner = state.store_user(data['owner'])
 
         team = data.get('team')
         self.team = Team(state, team) if team else None
@@ -148,7 +158,7 @@ class AppInfo:
         self.terms_of_service_url = data.get('terms_of_service_url')
         self.privacy_policy_url = data.get('privacy_policy_url')
 
-    def __repr__(self):
+    def __repr__(self) -> str:
         return (
             f'<{self.__class__.__name__} id={self.id} name={self.name!r} '
             f'description={self.description!r} public={self.bot_public} '
@@ -156,14 +166,14 @@ class AppInfo:
         )
 
     @property
-    def icon(self):
+    def icon(self) -> Optional[Asset]:
         """Optional[:class:`.Asset`]: Retrieves the application's icon asset, if any."""
         if self._icon is None:
             return None
         return Asset._from_icon(self._state, self.id, self._icon, path='app')
 
     @property
-    def cover_image(self):
+    def cover_image(self) -> Optional[Asset]:
         """Optional[:class:`.Asset`]: Retrieves the cover image on a store embed, if any.
 
         This is only available if the application is a game sold on Discord.
@@ -173,10 +183,61 @@ class AppInfo:
         return Asset._from_cover_image(self._state, self.id, self._cover_image)
 
     @property
-    def guild(self):
+    def guild(self) -> Optional[Guild]:
         """Optional[:class:`Guild`]: If this application is a game sold on Discord,
         this field will be the guild to which it has been linked
 
         .. versionadded:: 1.3
         """
-        return self._state._get_guild(int(self.guild_id))
+        return self._state._get_guild(self.guild_id)
+
+class PartialAppInfo:
+    """Represents a partial AppInfo given by :func:`~GuildChannel.create_invite`
+
+    .. versionadded:: 2.0
+
+    Attributes
+    -------------
+    id: :class:`int`
+        The application ID.
+    name: :class:`str`
+        The application name.
+    description: :class:`str`
+        The application description.
+    rpc_origins: Optional[List[:class:`str`]]
+        A list of RPC origin URLs, if RPC is enabled.
+    summary: :class:`str`
+        If this application is a game sold on Discord,
+        this field will be the summary field for the store page of its primary SKU.
+    verify_key: :class:`str`
+        The hex encoded key for verification in interactions and the
+        GameSDK's `GetTicket <https://discord.com/developers/docs/game-sdk/applications#getticket>`_.
+    terms_of_service_url: Optional[:class:`str`]
+        The application's terms of service URL, if set.
+    privacy_policy_url: Optional[:class:`str`]
+        The application's privacy policy URL, if set.
+    """
+
+    __slots__ = ('_state', 'id', 'name', 'description', 'rpc_origins', 'summary', 'verify_key', 'terms_of_service_url', 'privacy_policy_url', '_icon')
+
+    def __init__(self, *, state: ConnectionState, data: PartialAppInfoPayload):
+        self._state = state
+        self.id = int(data['id'])
+        self.name = data['name']
+        self._icon = data.get('icon')
+        self.description = data['description']
+        self.rpc_origins = data.get('rpc_origins')
+        self.summary = data['summary']
+        self.verify_key = data['verify_key']
+        self.terms_of_service_url = data.get('terms_of_service_url')
+        self.privacy_policy_url = data.get('privacy_policy_url')
+
+    def __repr__(self) -> str:
+        return f'<{self.__class__.__name__} id={self.id} name={self.name!r} description={self.description!r}>'
+
+    @property
+    def icon(self) -> Optional[Asset]:
+        """Optional[:class:`.Asset`]: Retrieves the application's icon asset, if any."""
+        if self._icon is None:
+            return None
+        return Asset._from_icon(self._state, self.id, self._icon, path='app')
diff --git a/discord/enums.py b/discord/enums.py
index fa86767db..aaa59b25b 100644
--- a/discord/enums.py
+++ b/discord/enums.py
@@ -431,7 +431,7 @@ class StickerType(Enum):
 
 class InviteTarget(Enum):
     unknown = 0
-    stream  = 1
+    stream = 1
     embedded_application = 2
 
 class InteractionType(Enum):
diff --git a/discord/http.py b/discord/http.py
index 67529495b..c14cc8d49 100644
--- a/discord/http.py
+++ b/discord/http.py
@@ -981,6 +981,9 @@ class HTTPClient:
         max_uses: int = 0,
         temporary: bool = False,
         unique: bool = True,
+        target_type: Optional[int] = None,
+        target_user_id: Optional[int] = None,
+        target_application_id: Optional[int] = None
     ) -> Response[invite.Invite]:
         r = Route('POST', '/channels/{channel_id}/invites', channel_id=channel_id)
         payload = {
@@ -990,6 +993,15 @@ class HTTPClient:
             'unique': unique,
         }
 
+        if target_type:
+            payload['target_type'] = target_type
+
+        if target_user_id:
+            payload['target_user_id'] = target_user_id
+
+        if target_application_id:
+            payload['target_application_id'] = str(target_application_id)
+
         return self.request(r, reason=reason, json=payload)
 
     def get_invite(self, invite_id, *, with_counts=True, with_expiration=True):
diff --git a/discord/invite.py b/discord/invite.py
index 213ef5a44..8e60d1e8b 100644
--- a/discord/invite.py
+++ b/discord/invite.py
@@ -30,6 +30,7 @@ from .utils import parse_time, snowflake_time, _get_as_snowflake
 from .object import Object
 from .mixins import Hashable
 from .enums import ChannelType, VerificationLevel, InviteTarget, try_enum
+from .appinfo import PartialAppInfo
 
 __all__ = (
     'PartialInviteChannel',
@@ -277,12 +278,18 @@ class Invite(Hashable):
 
     channel: Union[:class:`abc.GuildChannel`, :class:`Object`, :class:`PartialInviteChannel`]
         The channel the invite is for.
+    target_type: :class:`InviteTarget`
+        The type of target for the voice channel invite.
+        
+        .. versionadded:: 2.0
+    
     target_user: Optional[:class:`User`]
-        The target of this invite in the case of stream invites.
+        The user whose stream to display for this invite, if any.
 
         .. versionadded:: 2.0
-    target_type: :class:`InviteTarget`
-        The invite's target type.
+
+    target_application: Optional[:class:`PartialAppInfo`]
+        The embedded application the invite targets, if any.
 
         .. versionadded:: 2.0
     """
@@ -303,6 +310,7 @@ class Invite(Hashable):
         '_state',
         'approximate_member_count',
         'approximate_presence_count',
+        'target_application',
         'expires_at',
     )
 
@@ -328,7 +336,11 @@ class Invite(Hashable):
         self.channel = data.get('channel')
         target_user_data = data.get('target_user')
         self.target_user = None if target_user_data is None else self._state.store_user(target_user_data)
-        self.target_type = try_enum(InviteTarget, data.get('target_type', 0))
+
+        self.target_type = try_enum(InviteTarget, data.get("target_type", 0))
+
+        application = data.get('target_application')
+        self.target_application = PartialAppInfo(data=application, state=state) if application else None
 
     @classmethod
     def from_incomplete(cls, *, state, data):
diff --git a/discord/team.py b/discord/team.py
index 5e47770b0..94cf6e59d 100644
--- a/discord/team.py
+++ b/discord/team.py
@@ -22,11 +22,21 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 DEALINGS IN THE SOFTWARE.
 """
 
+from __future__ import annotations
+
 from . import utils
 from .user import BaseUser
 from .asset import Asset
 from .enums import TeamMembershipState, try_enum
 
+from typing import TYPE_CHECKING, Optional
+
+if TYPE_CHECKING:
+    from .types.team import (
+        Team as TeamPayload,
+        TeamMember as TeamMemberPayload,
+    )
+
 __all__ = (
     'Team',
     'TeamMember',
@@ -52,7 +62,7 @@ class Team:
 
     __slots__ = ('_state', 'id', 'name', '_icon', 'owner_id', 'members')
 
-    def __init__(self, state, data):
+    def __init__(self, state, data: TeamPayload):
         self._state = state
 
         self.id = int(data['id'])
@@ -61,18 +71,18 @@ class Team:
         self.owner_id = utils._get_as_snowflake(data, 'owner_user_id')
         self.members = [TeamMember(self, self._state, member) for member in data['members']]
 
-    def __repr__(self):
+    def __repr__(self) -> str:
         return f'<{self.__class__.__name__} id={self.id} name={self.name}>'
 
     @property
-    def icon(self):
+    def icon(self) -> Optional[Asset]:
         """Optional[:class:`.Asset`]: Retrieves the team's icon asset, if any."""
         if self._icon is None:
             return None
         return Asset._from_icon(self._state, self.id, self._icon, path='team')
 
     @property
-    def owner(self):
+    def owner(self) -> Optional[TeamMember]:
         """Optional[:class:`TeamMember`]: The team's owner."""
         return utils.get(self.members, id=self.owner_id)
 
@@ -120,13 +130,13 @@ class TeamMember(BaseUser):
 
     __slots__ = BaseUser.__slots__ + ('team', 'membership_state', 'permissions')
 
-    def __init__(self, team, state, data):
+    def __init__(self, team: Team, state, data: TeamMemberPayload):
         self.team = team
         self.membership_state = try_enum(TeamMembershipState, data['membership_state'])
         self.permissions = data['permissions']
         super().__init__(state=state, data=data['user'])
 
-    def __repr__(self):
+    def __repr__(self) -> str:
         return (
             f'<{self.__class__.__name__} id={self.id} name={self.name!r} '
             f'discriminator={self.discriminator!r} membership_state={self.membership_state!r}>'
diff --git a/discord/types/appinfo.py b/discord/types/appinfo.py
new file mode 100644
index 000000000..d223837fa
--- /dev/null
+++ b/discord/types/appinfo.py
@@ -0,0 +1,66 @@
+"""
+The MIT License (MIT)
+
+Copyright (c) 2015-present Rapptz
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+"""
+
+from __future__ import annotations
+
+from typing import TypedDict, List, Optional
+
+from .user import User
+from .team import Team
+from .snowflake import Snowflake
+
+class BaseAppInfo(TypedDict):
+    id: Snowflake
+    name: str
+    verify_key: str
+    icon: Optional[str]
+    summary: str
+    description: str
+
+class _AppInfoOptional(TypedDict, total=False):
+    team: Team
+    guild_id: Snowflake
+    primary_sku_id: Snowflake
+    slug: str
+    terms_of_service_url: str
+    privacy_policy_url: str
+    hook: bool
+    max_participants: int
+
+class AppInfo(BaseAppInfo, _AppInfoOptional):
+    rpc_origins: List[str]
+    owner: User
+    bot_public: bool
+    bot_require_code_grant: bool
+
+class _PartialAppInfoOptional(TypedDict, total=False):
+    rpc_origins: List[str]
+    cover_image: str
+    hook: bool
+    terms_of_service_url: str
+    privacy_policy_url: str
+    max_participants: int
+
+class PartialAppInfo(_PartialAppInfoOptional, BaseAppInfo):
+    pass
diff --git a/discord/types/invite.py b/discord/types/invite.py
index 25466158b..3760f0fab 100644
--- a/discord/types/invite.py
+++ b/discord/types/invite.py
@@ -29,15 +29,17 @@ from typing import Literal, TypedDict
 from .guild import InviteGuild, _GuildPreviewUnique
 from .channel import PartialChannel
 from .user import PartialUser
+from .appinfo import PartialAppInfo
 
-TargetUserType = Literal[1]
+InviteTargetType = Literal[1, 2]
 
 
 class _InviteOptional(TypedDict, total=False):
     guild: InviteGuild
     inviter: PartialUser
     target_user: PartialUser
-    target_user_type: TargetUserType
+    target_type: InviteTargetType
+    target_application: PartialAppInfo
 
 
 class _InviteMetadata(TypedDict, total=False):
diff --git a/discord/types/team.py b/discord/types/team.py
new file mode 100644
index 000000000..e8cd524f8
--- /dev/null
+++ b/discord/types/team.py
@@ -0,0 +1,43 @@
+"""
+The MIT License (MIT)
+
+Copyright (c) 2015-present Rapptz
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+"""
+
+from __future__ import annotations
+
+from typing import TypedDict, List
+
+from .user import PartialUser
+from .snowflake import Snowflake
+
+class TeamMember(TypedDict):
+    user: PartialUser
+    membership_state: int
+    permissions: List[str]
+    team_id: Snowflake
+
+class Team(TypedDict):
+    id: Snowflake
+    name: str
+    owner_id: Snowflake
+    members: List[TeamMember]
+    icon: str
diff --git a/docs/api.rst b/docs/api.rst
index 62764a23d..649e8d339 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -64,6 +64,14 @@ AppInfo
 .. autoclass:: AppInfo()
     :members:
 
+PartialAppInfo
+~~~~~~~~~~~~~~~
+
+.. attributetable:: PartialAppInfo
+
+.. autoclass:: PartialAppInfo()
+    :members:
+
 Team
 ~~~~~
 
@@ -2076,7 +2084,7 @@ of :class:`enum.Enum`.
 
 .. class:: InviteTarget
 
-    Represents the type of target an invite contains.
+    Represents the invite type for voice channel invites.
 
     .. versionadded:: 2.0
 
@@ -2086,11 +2094,11 @@ of :class:`enum.Enum`.
 
     .. attribute:: stream
 
-        The invite targets a stream.
+        A stream invite that targets a user.
 
     .. attribute:: embedded_application
 
-        The invite targets an embedded application activity.
+        A stream invite that targets an embedded application.
 
 .. class:: VideoQualityMode
 
@@ -2106,6 +2114,7 @@ of :class:`enum.Enum`.
 
         Represents full camera video quality.
 
+
 Async Iterator
 ----------------