diff --git a/SVSim.EmulatedEntrypoint/Models/Dtos/Common/Mission/BPMonthlyMissionDto.cs b/SVSim.EmulatedEntrypoint/Models/Dtos/Common/Mission/BPMonthlyMissionDto.cs
new file mode 100644
index 0000000..45e1711
--- /dev/null
+++ b/SVSim.EmulatedEntrypoint/Models/Dtos/Common/Mission/BPMonthlyMissionDto.cs
@@ -0,0 +1,31 @@
+using System.Text.Json.Serialization;
+using MessagePack;
+
+namespace SVSim.EmulatedEntrypoint.Models.Dtos.Common.Mission;
+
+///
+/// Inner reward block. STRING-typed on wire (capture confirms reward_type/reward_detail_id/
+/// reward_number all serialize as JSON strings here, unlike UserMission where they're int).
+///
+[MessagePackObject(keyAsPropertyName: true)]
+public class BPMonthlyMissionRewardInfoDto
+{
+ [Key(0)][JsonPropertyName("reward_type")] public string RewardType { get; set; } = "";
+ [Key(1)][JsonPropertyName("reward_detail_id")] public string RewardDetailId { get; set; } = "";
+ [Key(2)][JsonPropertyName("reward_number")] public string RewardNumber { get; set; } = "";
+}
+
+///
+/// One BP monthly mission. reward_info is OPTIONAL — capture shows "Play 5 Challenge matches"
+/// has no reward_info block (only BP points). Global WhenWritingNull policy omits when null.
+///
+[MessagePackObject(keyAsPropertyName: true)]
+public class BPMonthlyMissionDto
+{
+ [Key(0)][JsonPropertyName("name")] public string Name { get; set; } = "";
+ [Key(1)][JsonPropertyName("is_cleared")] public bool IsCleared { get; set; }
+ [Key(2)][JsonPropertyName("require_number")] public int RequireNumber { get; set; }
+ [Key(3)][JsonPropertyName("done_number")] public int DoneNumber { get; set; }
+ [Key(4)][JsonPropertyName("battle_pass_point")] public int BattlePassPoint { get; set; }
+ [Key(5)][JsonPropertyName("reward_info")] public BPMonthlyMissionRewardInfoDto? RewardInfo { get; set; }
+}
diff --git a/SVSim.EmulatedEntrypoint/Models/Dtos/Common/Mission/BPMonthlyMissionsDto.cs b/SVSim.EmulatedEntrypoint/Models/Dtos/Common/Mission/BPMonthlyMissionsDto.cs
new file mode 100644
index 0000000..27fc435
--- /dev/null
+++ b/SVSim.EmulatedEntrypoint/Models/Dtos/Common/Mission/BPMonthlyMissionsDto.cs
@@ -0,0 +1,17 @@
+using System.Text.Json.Serialization;
+using MessagePack;
+
+namespace SVSim.EmulatedEntrypoint.Models.Dtos.Common.Mission;
+
+///
+/// Outer block. Date strings use the capture's space-separated JST format
+/// ("2026-05-01 02:00:00"). The whole block is omitted from /mission/info when no monthly
+/// missions are seeded for the current month.
+///
+[MessagePackObject(keyAsPropertyName: true)]
+public class BPMonthlyMissionsDto
+{
+ [Key(0)][JsonPropertyName("start_date")] public string StartDate { get; set; } = "";
+ [Key(1)][JsonPropertyName("end_date")] public string EndDate { get; set; } = "";
+ [Key(2)][JsonPropertyName("mission_list")] public List MissionList { get; set; } = new();
+}
diff --git a/SVSim.EmulatedEntrypoint/Models/Dtos/Common/Mission/MissionInfoDataDto.cs b/SVSim.EmulatedEntrypoint/Models/Dtos/Common/Mission/MissionInfoDataDto.cs
new file mode 100644
index 0000000..b89128b
--- /dev/null
+++ b/SVSim.EmulatedEntrypoint/Models/Dtos/Common/Mission/MissionInfoDataDto.cs
@@ -0,0 +1,38 @@
+using System.Text.Json.Serialization;
+using MessagePack;
+
+namespace SVSim.EmulatedEntrypoint.Models.Dtos.Common.Mission;
+
+///
+/// Top-level payload for /mission/info responses (also reused by /mission/retire,
+/// /mission/change_receive_setting; /achievement/receive_reward adds reward_list +
+/// total_receive_count_list to this shape via inheritance).
+///
+/// CanChangeMissionTime is wire-required to be present (capture shows null when active).
+/// Override [JsonIgnore(Condition = Never)] per memory project_wire_null_policy.
+///
+[MessagePackObject(keyAsPropertyName: true)]
+public class MissionInfoDataDto
+{
+ [Key(0)][JsonPropertyName("user_mission_list")] public List UserMissionList { get; set; } = new();
+ [Key(1)][JsonPropertyName("is_change_mission")] public bool IsChangeMission { get; set; }
+
+ [Key(2)]
+ [JsonPropertyName("can_change_mission_time")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
+ public long? CanChangeMissionTime { get; set; }
+
+ [Key(3)][JsonPropertyName("is_change_receive_type")] public bool IsChangeReceiveType { get; set; }
+
+ [Key(4)]
+ [JsonPropertyName("can_change_receive_type_time")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
+ public long? CanChangeReceiveTypeTime { get; set; }
+
+ [Key(5)][JsonPropertyName("user_achievement_list")] public List UserAchievementList { get; set; } = new();
+ [Key(6)][JsonPropertyName("mission_receive_type")] public string MissionReceiveType { get; set; } = "0";
+
+ [Key(7)]
+ [JsonPropertyName("battle_pass_monthly_mission")]
+ public BPMonthlyMissionsDto? BattlePassMonthlyMission { get; set; }
+}
diff --git a/SVSim.EmulatedEntrypoint/Models/Dtos/Common/Mission/UserAchievementDto.cs b/SVSim.EmulatedEntrypoint/Models/Dtos/Common/Mission/UserAchievementDto.cs
new file mode 100644
index 0000000..b38cce2
--- /dev/null
+++ b/SVSim.EmulatedEntrypoint/Models/Dtos/Common/Mission/UserAchievementDto.cs
@@ -0,0 +1,28 @@
+using System.Text.Json.Serialization;
+using MessagePack;
+
+namespace SVSim.EmulatedEntrypoint.Models.Dtos.Common.Mission;
+
+///
+/// Wire shape of UserAchievement (per MissionInfoDetail.cs:98-116). ios/android are always
+/// empty strings in our world. max_level is computed from catalog (MAX(Level) per type).
+///
+[MessagePackObject(keyAsPropertyName: true)]
+public class UserAchievementDto
+{
+ [Key(0)][JsonPropertyName("achievement_type")] public int AchievementType { get; set; }
+ [Key(1)][JsonPropertyName("achievement_status")] public int AchievementStatus { get; set; }
+ [Key(2)][JsonPropertyName("level")] public int Level { get; set; }
+ [Key(3)][JsonPropertyName("now_achieved_level")] public int NowAchievedLevel { get; set; }
+ [Key(4)][JsonPropertyName("result_announce_saw_level")] public int ResultAnnounceSawLevel { get; set; }
+ [Key(5)][JsonPropertyName("total_count")] public int TotalCount { get; set; }
+ [Key(6)][JsonPropertyName("achievement_name")] public string AchievementName { get; set; } = "";
+ [Key(7)][JsonPropertyName("require_number")] public int RequireNumber { get; set; }
+ [Key(8)][JsonPropertyName("reward_type")] public int RewardType { get; set; }
+ [Key(9)][JsonPropertyName("reward_detail_id")] public long RewardDetailId { get; set; }
+ [Key(10)][JsonPropertyName("reward_number")] public int RewardNumber { get; set; }
+ [Key(11)][JsonPropertyName("max_level")] public int MaxLevel { get; set; }
+ [Key(12)][JsonPropertyName("order_num")] public int OrderNum { get; set; }
+ [Key(13)][JsonPropertyName("ios")] public string Ios { get; set; } = "";
+ [Key(14)][JsonPropertyName("android")] public string Android { get; set; } = "";
+}
diff --git a/SVSim.EmulatedEntrypoint/Models/Dtos/Common/Mission/UserMissionDto.cs b/SVSim.EmulatedEntrypoint/Models/Dtos/Common/Mission/UserMissionDto.cs
new file mode 100644
index 0000000..33c642f
--- /dev/null
+++ b/SVSim.EmulatedEntrypoint/Models/Dtos/Common/Mission/UserMissionDto.cs
@@ -0,0 +1,29 @@
+using System.Text.Json.Serialization;
+using MessagePack;
+
+namespace SVSim.EmulatedEntrypoint.Models.Dtos.Common.Mission;
+
+///
+/// Wire shape of UserMission (per MissionInfoDetail.cs:75-95). lot_type and battle_pass_point
+/// are STRING-typed on wire (client uses .ToInt() but emits as string in capture). All other
+/// scalar fields are int. end_time omitted when null per UserMission.Parse() optional read.
+///
+[MessagePackObject(keyAsPropertyName: true)]
+public class UserMissionDto
+{
+ [Key(0)][JsonPropertyName("id")] public long Id { get; set; }
+ [Key(1)][JsonPropertyName("mission_id")] public int MissionId { get; set; }
+ [Key(2)][JsonPropertyName("total_count")] public int TotalCount { get; set; }
+ [Key(3)][JsonPropertyName("mission_status")] public int MissionStatus { get; set; }
+ [Key(4)][JsonPropertyName("display_order")] public int DisplayOrder { get; set; }
+ [Key(5)][JsonPropertyName("mission_name")] public string MissionName { get; set; } = "";
+ [Key(6)][JsonPropertyName("lot_type")] public string LotType { get; set; } = "";
+ [Key(7)][JsonPropertyName("battle_pass_point")] public string BattlePassPoint { get; set; } = "";
+ [Key(8)][JsonPropertyName("require_number")] public int RequireNumber { get; set; }
+ [Key(9)][JsonPropertyName("reward_type")] public int RewardType { get; set; }
+ [Key(10)][JsonPropertyName("reward_detail_id")] public long RewardDetailId { get; set; }
+ [Key(11)][JsonPropertyName("reward_number")] public int RewardNumber { get; set; }
+ [Key(12)][JsonPropertyName("default_flag")] public bool DefaultFlag { get; set; }
+ [Key(13)][JsonPropertyName("start_time")] public long StartTime { get; set; }
+ [Key(14)][JsonPropertyName("end_time")] public long? EndTime { get; set; }
+}