diff --git a/Project.App/Project.Api/DTOs/BlackjackActionDTO.cs b/Project.App/Project.Api/DTOs/BlackjackActionDTO.cs
new file mode 100644
index 0000000..2e29b8d
--- /dev/null
+++ b/Project.App/Project.Api/DTOs/BlackjackActionDTO.cs
@@ -0,0 +1,45 @@
+using System.Text.Json;
+
+namespace Project.Api.DTOs;
+
+///
+/// The base class for all blackjack-specific action DTOs.
+///
+public abstract record BlackjackActionDTO : GameActionDTO;
+
+public record BetAction(long Amount) : BlackjackActionDTO;
+
+public record HitAction : BlackjackActionDTO;
+
+public record StandAction : BlackjackActionDTO;
+
+public record DoubleAction : BlackjackActionDTO;
+
+public record SplitAction : BlackjackActionDTO;
+
+public record SurrenderAction : BlackjackActionDTO;
+
+public static class JsonElementExtensions
+{
+ ///
+ /// Extension method to deserialize a from a .
+ /// Any errors thrown during deserialization will be passed to the caller.
+ ///
+ public static BlackjackActionDTO ToBlackjackAction(this JsonElement element, string action)
+ {
+ return (
+ action switch
+ {
+ "bet" => element.Deserialize(),
+ "hit" => element.Deserialize(),
+ "stand" => element.Deserialize(),
+ "double" => element.Deserialize(),
+ "split" => element.Deserialize(),
+ "surrender" => (BlackjackActionDTO?)element.Deserialize(),
+ _ => throw new NotSupportedException(
+ $"Action '{action}' is not a valid action for Blackjack."
+ ),
+ }
+ ) ?? throw new InvalidOperationException($"Could not deserialize action {action}.");
+ }
+}
diff --git a/Project.App/Project.Api/DTOs/GameActionDTO.cs b/Project.App/Project.Api/DTOs/GameActionDTO.cs
new file mode 100644
index 0000000..0f1f13f
--- /dev/null
+++ b/Project.App/Project.Api/DTOs/GameActionDTO.cs
@@ -0,0 +1,6 @@
+namespace Project.Api.DTOs;
+
+///
+/// The base class for all game action DTOs. Does nothing.
+///
+public abstract record GameActionDTO;
diff --git a/Project.App/Project.Api/Services/BlackjackService.cs b/Project.App/Project.Api/Services/BlackjackService.cs
new file mode 100644
index 0000000..1c1861e
--- /dev/null
+++ b/Project.App/Project.Api/Services/BlackjackService.cs
@@ -0,0 +1,110 @@
+using System.Text.Json;
+using Project.Api.DTOs;
+using Project.Api.Services.Interface;
+
+namespace Project.Api.Services;
+
+/*
+
+set up deck API connection
+set up game configs
+
+loop
+ shuffle deck(?)
+
+ loop
+ if everyone has bet/left or time is up
+ break
+ end if
+ wait
+ end loop
+ deduct bets
+
+ deal 2 cards to each player
+ deal 2 cards to dealer (one hidden)
+
+ loop (foreach player)
+ loop
+ if hit
+ deal card
+ else if stand
+ break
+ end if
+ end loop
+ end loop
+
+ deal to dealer (hit until 17)
+ calculate scores
+ determine outcomes
+ distribute winnings
+end loop
+
+teardown
+close room
+
+*/
+
+#region Blackjack Game Stages
+
+// initial setup
+// initialize deck, set game configs
+public record BlackjackInitStage : BlackjackStage;
+
+// doing pre-round setup
+public record BlackjackSetupStage : BlackjackStage;
+
+// waiting for players to bet
+public record BlackjackBettingStage : BlackjackStage;
+
+// dealing
+public record BlackjackDealingStage : BlackjackStage;
+
+// player turn
+// TODO: figure out how turn order will work
+public record BlackjackPlayerActionStage(int Index) : BlackjackStage;
+
+// dealer turn and distribute winnings
+public record BlackjackFinishRoundStage : BlackjackStage;
+
+// teardown, close room
+public record BlackjackTeardownStage : BlackjackStage;
+
+#endregion
+
+public class BlackjackService : IBlackjackService
+{
+ public Task GetGamestateAsync(string gameId)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task PerformActionAsync(
+ string gameId,
+ string playerId,
+ string action,
+ JsonElement data
+ )
+ {
+ BlackjackActionDTO actionDTO = data.ToBlackjackAction(action);
+
+ switch (actionDTO)
+ {
+ case BetAction betAction:
+ throw new NotImplementedException();
+ case HitAction hitAction:
+ throw new NotImplementedException();
+ case StandAction standAction:
+ throw new NotImplementedException();
+ case DoubleAction doubleAction:
+ throw new NotImplementedException();
+ case SplitAction splitAction:
+ throw new NotImplementedException();
+ case SurrenderAction surrenderAction:
+ throw new NotImplementedException();
+ default:
+ throw new NotImplementedException();
+ }
+
+ throw new NotImplementedException();
+ }
+}
diff --git a/Project.App/Project.Api/Services/Interface/IBlackjackService.cs b/Project.App/Project.Api/Services/Interface/IBlackjackService.cs
index 86e9e6c..c4b4211 100644
--- a/Project.App/Project.Api/Services/Interface/IBlackjackService.cs
+++ b/Project.App/Project.Api/Services/Interface/IBlackjackService.cs
@@ -1,3 +1,13 @@
namespace Project.Api.Services.Interface;
-public interface IBlackjackService : IGameService { }
+public abstract record BlackjackStage : GameStage;
+
+public record BlackjackState : GameState
+{
+ public required List