diff --git a/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/SignupRequest.cs b/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/SignupRequest.cs
new file mode 100644
index 0000000..d050adf
--- /dev/null
+++ b/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/SignupRequest.cs
@@ -0,0 +1,40 @@
+using MessagePack;
+using System.Text.Json.Serialization;
+
+namespace SVSim.EmulatedEntrypoint.Models.Dtos.Requests;
+
+///
+/// POST /tool/signup request body. Spec:
+/// docs/api-spec/endpoints/pre-login/tool-signup.md. Client source:
+/// Shadowverse_Code_2026-05-23/Cute/SignUpTask.cs (LoginPostParams).
+///
+/// All fields are device telemetry; the server doesn't use them in v1 but still binds them so
+/// the request shape matches the spec exactly.
+///
+[MessagePackObject]
+public class SignupRequest
+{
+ [JsonPropertyName("device_name")]
+ [Key("device_name")]
+ public string DeviceName { get; set; } = "";
+
+ [JsonPropertyName("client_type")]
+ [Key("client_type")]
+ public string ClientType { get; set; } = "";
+
+ [JsonPropertyName("os_version")]
+ [Key("os_version")]
+ public string OsVersion { get; set; } = "";
+
+ [JsonPropertyName("app_version")]
+ [Key("app_version")]
+ public string AppVersion { get; set; } = "";
+
+ [JsonPropertyName("resource_version")]
+ [Key("resource_version")]
+ public string ResourceVersion { get; set; } = "";
+
+ [JsonPropertyName("carrier")]
+ [Key("carrier")]
+ public string Carrier { get; set; } = "";
+}
diff --git a/SVSim.EmulatedEntrypoint/Models/Dtos/Responses/SignupResponse.cs b/SVSim.EmulatedEntrypoint/Models/Dtos/Responses/SignupResponse.cs
new file mode 100644
index 0000000..b42b94d
--- /dev/null
+++ b/SVSim.EmulatedEntrypoint/Models/Dtos/Responses/SignupResponse.cs
@@ -0,0 +1,10 @@
+namespace SVSim.EmulatedEntrypoint.Models.Dtos.Responses;
+
+///
+/// POST /tool/signup response. The interesting outputs (viewer_id, short_udid, udid) all
+/// live in data_headers; the data payload is empty. SignUpTask.Parse never
+/// reads data.
+///
+public class SignupResponse
+{
+}