diff --git a/BitwardenShared/Core/Auth/Models/API/CreateAccount/CreateAccountRequestModel.swift b/BitwardenShared/Core/Auth/Models/API/CreateAccount/CreateAccountRequestModel.swift
new file mode 100644
index 000000000..18f61dc92
--- /dev/null
+++ b/BitwardenShared/Core/Auth/Models/API/CreateAccount/CreateAccountRequestModel.swift
@@ -0,0 +1,57 @@
+import Foundation
+import Networking
+
+// MARK: - CreateAccountRequestModel
+
+/// The data to include in the body of a `CreateAccountRequest`.
+///
+struct CreateAccountRequestModel: Equatable {
+    // MARK: Properties
+
+    /// The captcha response used in validating a user for this request.
+    let captchaResponse: String? = nil
+
+    /// The user's email address.
+    let email: String
+
+    /// The type of kdf for this request.
+    let kdf: KdfType? = nil
+
+    /// The number of kdf iterations performed in this request.
+    let kdfIterations: Int? = nil
+
+    /// The kdf memory allocated for the computed password hash.
+    let kdfMemory: Int? = nil
+
+    /// The number of threads upon which the kdf iterations are performed.
+    let kdfParallelism: Int? = nil
+
+    /// The key used for this request.
+    let key: String? = nil
+
+    /// The keys used for this request.
+    let keys: KeysRequestModel? = nil
+
+    /// The master password hash used to authenticate a user.
+    let masterPasswordHash: String // swiftlint:disable:this inclusive_language
+
+    /// The master password hint.
+    let masterPasswordHint: String? = nil // swiftlint:disable:this inclusive_language
+
+    /// The user's name.
+    let name: String? = nil
+
+    /// The organization's user ID.
+    let organizationUserId: String? = nil
+
+    /// The token used when making this request.
+    let token: String? = nil
+}
+
+// MARK: JSONRequestBody
+
+extension CreateAccountRequestModel: JSONRequestBody {
+    static var encoder: JSONEncoder {
+        JSONEncoder()
+    }
+}
diff --git a/BitwardenShared/Core/Auth/Models/API/CreateAccount/CreateAccountResponseModel.swift b/BitwardenShared/Core/Auth/Models/API/CreateAccount/CreateAccountResponseModel.swift
new file mode 100644
index 000000000..6bac6db81
--- /dev/null
+++ b/BitwardenShared/Core/Auth/Models/API/CreateAccount/CreateAccountResponseModel.swift
@@ -0,0 +1,15 @@
+import Foundation
+import Networking
+
+// MARK: - CreateAccountResponseModel
+
+/// The response returned from the API upon creating an account.
+///
+struct CreateAccountResponseModel: JSONResponse {
+    static var decoder = JSONDecoder()
+
+    // MARK: Properties
+
+    /// The captcha bypass token returned in this response.
+    var captchaBypassToken: String?
+}
diff --git a/BitwardenShared/Core/Auth/Models/API/CreateAccount/CreateAccountResponseModelTests.swift b/BitwardenShared/Core/Auth/Models/API/CreateAccount/CreateAccountResponseModelTests.swift
new file mode 100644
index 000000000..6c18fdac4
--- /dev/null
+++ b/BitwardenShared/Core/Auth/Models/API/CreateAccount/CreateAccountResponseModelTests.swift
@@ -0,0 +1,21 @@
+import XCTest
+
+@testable import BitwardenShared
+
+// MARK: - CreateAccountResponseModelTests
+
+class CreateAccountResponseModelTests: BitwardenTestCase {
+    /// Tests that a response is initialized correctly.
+    func test_init() {
+        let subject = CreateAccountResponseModel(captchaBypassToken: "captchaBypassToken")
+        XCTAssertEqual(subject.captchaBypassToken, "captchaBypassToken")
+    }
+
+    /// Tests the successful decoding of a JSON response.
+    func test_decode_success() throws {
+        let json = APITestData.createAccountResponse.data
+        let decoder = JSONDecoder()
+        let subject = try decoder.decode(CreateAccountResponseModel.self, from: json)
+        XCTAssertEqual(subject.captchaBypassToken, "captchaBypassToken")
+    }
+}
diff --git a/BitwardenShared/Core/Auth/Models/API/CreateAccount/Fixtures/APITestData+CreateAccountRequest.swift b/BitwardenShared/Core/Auth/Models/API/CreateAccount/Fixtures/APITestData+CreateAccountRequest.swift
new file mode 100644
index 000000000..7dfb12d7d
--- /dev/null
+++ b/BitwardenShared/Core/Auth/Models/API/CreateAccount/Fixtures/APITestData+CreateAccountRequest.swift
@@ -0,0 +1,4 @@
+extension APITestData {
+    static let createAccountRequest = loadFromBundle(resource: "Request", extension: "json")
+    static let createAccountResponse = loadFromBundle(resource: "Success", extension: "json")
+}
diff --git a/BitwardenShared/Core/Auth/Models/API/CreateAccount/Fixtures/Request.json b/BitwardenShared/Core/Auth/Models/API/CreateAccount/Fixtures/Request.json
new file mode 100644
index 000000000..32c75525a
--- /dev/null
+++ b/BitwardenShared/Core/Auth/Models/API/CreateAccount/Fixtures/Request.json
@@ -0,0 +1,23 @@
+{
+    "name": "name",
+    "email": "email",
+    "masterPasswordHash": "masterPasswordHash",
+    "masterPasswordHint": "masterPasswordHint",
+    "captchaResponse": "captchaResponse",
+    "key": "key",
+    "keys": {
+        "publicKey": "publicKey",
+        "encryptedPrivateKey": "encryptedPrivateKey"
+    },
+    "token": "token",
+    "organizationUserId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
+    "kdf": 0,
+    "kdfIterations": 0,
+    "kdfMemory": 0,
+    "kdfParallelism": 0,
+    "referenceData": {
+        "additionalProp1": "string",
+        "additionalProp2": "string",
+        "additionalProp3": "string"
+    }
+}
diff --git a/BitwardenShared/Core/Auth/Models/API/CreateAccount/Fixtures/Success.json b/BitwardenShared/Core/Auth/Models/API/CreateAccount/Fixtures/Success.json
new file mode 100644
index 000000000..2da50ea69
--- /dev/null
+++ b/BitwardenShared/Core/Auth/Models/API/CreateAccount/Fixtures/Success.json
@@ -0,0 +1,4 @@
+{
+  "object": "object",
+  "captchaBypassToken": "captchaBypassToken"
+}
diff --git a/BitwardenShared/Core/Auth/Models/API/CreateAccount/KdfType.swift b/BitwardenShared/Core/Auth/Models/API/CreateAccount/KdfType.swift
new file mode 100644
index 000000000..3887cb25a
--- /dev/null
+++ b/BitwardenShared/Core/Auth/Models/API/CreateAccount/KdfType.swift
@@ -0,0 +1,11 @@
+// MARK: - KdfType
+
+/// The type of key derivation function.
+///
+enum KdfType: Int, Codable, Equatable {
+    /// The PBKDF2 SHA256 type.
+    case pbkdf2sha256 = 0
+
+    /// The Argon2id type.
+    case argon2id = 1
+}
diff --git a/BitwardenShared/Core/Auth/Models/API/CreateAccount/KeysRequestModel.swift b/BitwardenShared/Core/Auth/Models/API/CreateAccount/KeysRequestModel.swift
new file mode 100644
index 000000000..90ecdc5b4
--- /dev/null
+++ b/BitwardenShared/Core/Auth/Models/API/CreateAccount/KeysRequestModel.swift
@@ -0,0 +1,13 @@
+// MARK: - KeysRequestModel
+
+/// A model for keys used in the `CreateAccountRequest`.
+///
+struct KeysRequestModel: Codable, Equatable {
+    // MARK: Properties
+
+    /// The public key used in a `CreateAccountRequest`.
+    var publicKey: String?
+
+    /// The encrypted private key used in a `CreateAccountRequest`.
+    let encryptedPrivateKey: String
+}
diff --git a/BitwardenShared/Core/Auth/Services/API/AccountAPIService.swift b/BitwardenShared/Core/Auth/Services/API/AccountAPIService.swift
index 352fc6d45..b93be3dd9 100644
--- a/BitwardenShared/Core/Auth/Services/API/AccountAPIService.swift
+++ b/BitwardenShared/Core/Auth/Services/API/AccountAPIService.swift
@@ -1,5 +1,22 @@
+// MARK: - AccountAPIService
+
 /// A protocol for an API service used to make account requests.
 ///
-protocol AccountAPIService {}
+protocol AccountAPIService {
+    /// Creates an API call for when the user submits an account creation form.
+    ///
+    /// - Parameter body: The body to be included in the request.
+    ///
+    /// - Returns data returned from the `CreateAccountRequest`.
+    ///
+    func createNewAccount(body: CreateAccountRequestModel) async throws -> CreateAccountResponseModel
+}
+
+// MARK: - APIService
 
-extension APIService: AccountAPIService {}
+extension APIService: AccountAPIService {
+    func createNewAccount(body: CreateAccountRequestModel) async throws -> CreateAccountResponseModel {
+        let request = CreateAccountRequest(body: body)
+        return try await apiService.send(request)
+    }
+}
diff --git a/BitwardenShared/Core/Auth/Services/API/AccountAPIServiceTests.swift b/BitwardenShared/Core/Auth/Services/API/AccountAPIServiceTests.swift
new file mode 100644
index 000000000..c7d34b31f
--- /dev/null
+++ b/BitwardenShared/Core/Auth/Services/API/AccountAPIServiceTests.swift
@@ -0,0 +1,74 @@
+import XCTest
+
+@testable import BitwardenShared
+
+// MARK: - AccountAPIServiceTests
+
+class AccountAPIServiceTests: BitwardenTestCase {
+    // MARK: Properties
+
+    var client: MockHTTPClient!
+    var subject: APIService!
+
+    override func setUp() {
+        super.setUp()
+        client = MockHTTPClient()
+        subject = APIService(client: client)
+    }
+
+    override func tearDown() {
+        super.tearDown()
+        client = nil
+        subject = nil
+    }
+
+    // MARK: Account creation
+
+    /// `createNewAccount(email:masterPasswordHash)` throws an error if the request fails.
+    func test_create_account_httpFailure() async {
+        client.result = .httpFailure()
+
+        await assertAsyncThrows {
+            _ = try await subject.createNewAccount(
+                body: CreateAccountRequestModel(
+                    email: "example@email.com",
+                    masterPasswordHash: "1234"
+                )
+            )
+        }
+    }
+
+    /// `createNewAccount(email:masterPasswordHash)` throws a decoding error if the response is not the expected type.
+    func test_create_account_failure() async throws {
+        let resultData = APITestData(data: Data("this should fail".utf8))
+        client.result = .httpSuccess(testData: resultData)
+
+        await assertAsyncThrows {
+            _ = try await subject.createNewAccount(
+                body: CreateAccountRequestModel(
+                    email: "example@email.com",
+                    masterPasswordHash: "1234"
+                )
+            )
+        }
+    }
+
+    /// `createNewAccount(email:masterPasswordHash)` returns the correct value from the API with a successful request.
+    func test_create_account_success() async throws {
+        let resultData = APITestData.createAccountResponse
+        client.result = .httpSuccess(testData: resultData)
+
+        let successfulResponse = try await subject.createNewAccount(
+            body: CreateAccountRequestModel(
+                email: "example@email.com",
+                masterPasswordHash: "1234"
+            )
+        )
+
+        let request = try XCTUnwrap(client.requests.first)
+        XCTAssertEqual(request.method, .post)
+        XCTAssertEqual(request.url.relativePath, "/api/accounts/register")
+        XCTAssertEqual(successfulResponse.captchaBypassToken, "captchaBypassToken")
+        XCTAssertNotNil(request.body)
+    }
+}
diff --git a/BitwardenShared/Core/Auth/Services/API/CreateAccount/CreateAccountRequest.swift b/BitwardenShared/Core/Auth/Services/API/CreateAccount/CreateAccountRequest.swift
new file mode 100644
index 000000000..51d803360
--- /dev/null
+++ b/BitwardenShared/Core/Auth/Services/API/CreateAccount/CreateAccountRequest.swift
@@ -0,0 +1,28 @@
+import Foundation
+import Networking
+
+// MARK: - CreateAccountRequest
+
+/// The API request sent when submitting an account creation form.
+///
+struct CreateAccountRequest: Request {
+    typealias Response = CreateAccountResponseModel
+    typealias Body = CreateAccountRequestModel
+
+    /// The body of this request.
+    var body: CreateAccountRequestModel?
+
+    /// The HTTP method for this request.
+    let method: HTTPMethod = .post
+
+    /// The URL path for this request.
+    var path: String = "/accounts/register"
+
+    /// Creates a new `CreateAccountRequest` instance.
+    ///
+    /// - Parameter body: The body of the request.
+    ///
+    init(body: CreateAccountRequestModel) {
+        self.body = body
+    }
+}
diff --git a/BitwardenShared/Core/Auth/Services/API/CreateAccount/CreateAccountRequestTests.swift b/BitwardenShared/Core/Auth/Services/API/CreateAccount/CreateAccountRequestTests.swift
new file mode 100644
index 000000000..cb401fed1
--- /dev/null
+++ b/BitwardenShared/Core/Auth/Services/API/CreateAccount/CreateAccountRequestTests.swift
@@ -0,0 +1,54 @@
+import XCTest
+
+@testable import BitwardenShared
+
+// MARK: - CreateAccountRequestTests
+
+class CreateAccountRequestTests: BitwardenTestCase {
+    /// Validate that the method is correct.
+    func test_method() {
+        let subject = CreateAccountRequest(
+            body: CreateAccountRequestModel(
+                email: "email@example.com",
+                masterPasswordHash: "1234"
+            )
+        )
+        XCTAssertEqual(subject.method, .post)
+    }
+
+    /// Validate that the path is correct.
+    func test_path() {
+        let subject = CreateAccountRequest(
+            body: CreateAccountRequestModel(
+                email: "email@example.com",
+                masterPasswordHash: "1234"
+            )
+        )
+        XCTAssertEqual(subject.path, "/accounts/register")
+    }
+
+    /// Validate that the body is not nil.
+    func test_body() {
+        let subject = CreateAccountRequest(
+            body: CreateAccountRequestModel(
+                email: "email@example.com",
+                masterPasswordHash: "1234"
+            )
+        )
+        XCTAssertNotNil(subject.body)
+    }
+
+    // MARK: Init
+
+    /// Validate that the value provided to the init method is correct.
+    func test_init_body() {
+        let subject = CreateAccountRequest(
+            body: CreateAccountRequestModel(
+                email: "email@example.com",
+                masterPasswordHash: "1234"
+            )
+        )
+        XCTAssertEqual(subject.body?.email, "email@example.com")
+        XCTAssertEqual(subject.body?.masterPasswordHash, "1234")
+    }
+}