diff --git a/src/TriunniaLabs.Arch.Sample.Server/Controllers/ApplicationApiSampleController.cs b/src/TriunniaLabs.Arch.Sample.Server/Controllers/ApplicationApiSampleController.cs
new file mode 100644
index 0000000..746550b
--- /dev/null
+++ b/src/TriunniaLabs.Arch.Sample.Server/Controllers/ApplicationApiSampleController.cs
@@ -0,0 +1,89 @@
+using TriunniaLabs.Arch.Api.Application.Client;
+using TriunniaLabs.Arch.Microservice;
+using TriunniaLabs.Memory.Protected;
+
+namespace TriunniaLabs.Arch.Sample.Server
+{
+ ///
+ /// A controller that shows how to work the Application Api.
+ ///
+ ///
+ /// Generally, working with the Application Api occurs transparently within your app and you won't need to contact it directly.
+ /// But if you ever do, here is its functionality.
+ ///
+ public class ApplicationApiSampleController : ArchControllerBase
+ {
+ // Services
+ private readonly IApplicationClient _applicationClient;
+ private readonly IApplicationPermissionClient _applicationPermissionClient;
+ private readonly IApplicationGuardianClient _applcationGuardianClient;
+ private readonly ICapabilitiesClient _capabilitiesClient;
+
+ ///
+ /// Constructor.
+ ///
+ /// Reference to the microservice context.
+ /// Reference to the Application client.
+ /// Reference to the Application Permission client.
+ /// Reference to the Application Guardian client.
+ /// Reference to the Capabilities client.
+ public ApplicationApiSampleController(IMicroserviceContext microserviceContext,
+ IApplicationClient applicationClient,
+ IApplicationPermissionClient applicationPermissionClient,
+ IApplicationGuardianClient applicationGuardianClient,
+ ICapabilitiesClient capabilitiesClient)
+ : base(microserviceContext)
+ {
+ _applicationClient = applicationClient ?? throw new ArgumentNullException(nameof(applicationClient));
+ _applicationPermissionClient = applicationPermissionClient ?? throw new ArgumentNullException(nameof(applicationPermissionClient));
+ _applcationGuardianClient = applicationGuardianClient ?? throw new ArgumentNullException(nameof(applicationGuardianClient));
+ _capabilitiesClient = capabilitiesClient ?? throw new ArgumentNullException(nameof(capabilitiesClient));
+ }
+
+ ///
+ /// A sample method that shows how to work with the Keys Api.
+ ///
+ internal async Task SampleAsync()
+ {
+ var apiName = "SampleServer".AsProtected();
+
+ // Create a new application
+ var applicationId = await _applicationClient.CreateApplicationAsync();
+
+ // Delete an application
+ await _applicationClient.DeleteApplicationAsync(applicationId);
+
+
+ // Grant access to the application for the specified microservice/server/whatever
+ var accessResponse = await _applicationPermissionClient.GrantAccessAsync(applicationId, apiName);
+
+ // Validate whether the microservice has access to the application
+ // If this fails, a 424 Failed Dependency will be issued by Arch middleware
+ var validated = await _applicationPermissionClient.ValidateAccessAsync(applicationId, apiName, accessResponse.ApiKey);
+
+ // Revoke access from the application for the specified microservice
+ await _applicationPermissionClient.RevokeAccessAsync(applicationId, apiName);
+
+
+ // Sets any special capabilites the application may be using
+ await _capabilitiesClient.SetCapabilitiesAsync(new Capabilities { HardwareSecurityModule = true });
+
+ // Gets the capabilities for the application
+ var capabilities = await _capabilitiesClient.GetCapabilitiesAsync();
+
+
+ // When using a Hardware Security Module, gets the status of the guardian system
+ var guardianResponse = await _applcationGuardianClient.GetStatusAsync();
+
+ // When using a Hardware Security Module, authorizes startup of the application and retrieves the Bootstrap Key from the HSM.
+ // Arch will not start unless this call succeeds if using a Hardware Security Module.
+ var authKeyId = ((ushort)1).AsProtected();
+ var response = await _applcationGuardianClient.AuthorizeAsync("accessToken".AsProtected(), authKeyId, "password".AsProtected());
+
+ // Gets the Bootstrap Key. Used by some encryption algorithms when a Hardware Security Module is supported.
+ // Values encrypted with the Bootstrap Key cannot be decrypted unless it is successfully retrieved from the HSM.
+ var bootstrapResponse = await _applcationGuardianClient.GetBootstrapAsync();
+ Protected bootstrapKey = bootstrapResponse.BootstrapKey; // Encrypted in-memory until actually required
+ }
+ }
+}
diff --git a/src/TriunniaLabs.Arch.Sample.Server/Controllers/EmailApiSampleController.cs b/src/TriunniaLabs.Arch.Sample.Server/Controllers/EmailApiSampleController.cs
new file mode 100644
index 0000000..b3fdec3
--- /dev/null
+++ b/src/TriunniaLabs.Arch.Sample.Server/Controllers/EmailApiSampleController.cs
@@ -0,0 +1,58 @@
+using TriunniaLabs.Arch.Api.Email.Client;
+using TriunniaLabs.Arch.Microservice;
+using TriunniaLabs.Memory.Protected;
+
+namespace TriunniaLabs.Arch.Sample.Server
+{
+ ///
+ /// A controller that shows how to work the Email Api.
+ ///
+ public class EmailApiSampleController : ArchControllerBase
+ {
+ // Services
+ private readonly IEmailApiClient _emailApiClient;
+
+ ///
+ /// Constructor.
+ ///
+ /// Reference to the microservice context.
+ /// Reference to the Tokens Api client.
+ public EmailApiSampleController(IMicroserviceContext microserviceContext, IEmailApiClient emailApiClient) : base(microserviceContext)
+ {
+ _emailApiClient = emailApiClient ?? throw new ArgumentNullException(nameof(emailApiClient));
+ }
+
+ ///
+ /// A sample method that shows how to work with the Email Api.
+ ///
+ internal async Task SampleAsync()
+ {
+ var encryptionKey = "SampleEncryptionKey".AsProtected(); // Per-row encryption key for the email address
+ var emailAddress = "sample@email.address".AsProtected(encryptionKey.GetDecryptedValue()); // Per-row encrypted email address
+ var ipAddress = IpAddress.AsProtected(); // User's ip address
+ var verifyToken = Guid.NewGuid().AsProtected(); // A verify token from the verification email
+
+ // Create a new email address in the system
+ var emailId = await _emailApiClient.CreateEmailAddressAsync(emailAddress, encryptionKey);
+
+ // Delete the specified email address
+ await _emailApiClient.DeleteEmailAddressAsync(emailId);
+
+ // Check whether the specified email address already exists in the system
+ var emailExists = _emailApiClient.HasEmailAddressAsync(emailAddress.Hash);
+
+ // Get the email address and associated metadata from the Email Api
+ var emailResponse = await _emailApiClient.GetEmailAddressAsync(emailAddress.Hash, encryptionKey); // Get by hash
+ emailResponse = await _emailApiClient.GetEmailAddressAsync(emailId, encryptionKey); // Get by Id
+
+ // Email verification procedure. This will send an email to the user with the verify token. Record its verification or abuse with the other methods.
+ await _emailApiClient.InitEmailVerifyAsync(emailId, encryptionKey, ipAddress);
+ var result = await _emailApiClient.CommitEmailVerifyAsync(verifyToken, ipAddress);
+ result = await _emailApiClient.ReportAbuseAsync(verifyToken);
+
+ // When using Postmark, receive their webhooks and forward to the Email Api with this call.
+ // The Email Api will take care of ban and bounce handling.
+ await _emailApiClient.RelayPostmarkWebhookAsync(new PostmarkWebhookRequest { });
+ }
+ }
+}
diff --git a/src/TriunniaLabs.Arch.Sample.Server/Controllers/KeysApiSampleController.cs b/src/TriunniaLabs.Arch.Sample.Server/Controllers/KeysApiSampleController.cs
new file mode 100644
index 0000000..122be20
--- /dev/null
+++ b/src/TriunniaLabs.Arch.Sample.Server/Controllers/KeysApiSampleController.cs
@@ -0,0 +1,48 @@
+using TriunniaLabs.Arch.Api.Keys.Client;
+using TriunniaLabs.Arch.Microservice;
+using TriunniaLabs.Memory.Protected;
+
+namespace TriunniaLabs.Arch.Sample.Server
+{
+ ///
+ /// A controller that shows how to work the Keys Api.
+ ///
+ public class KeysApiSampleController : ArchControllerBase
+ {
+ // Services
+ private readonly IKeysApiClient _keysApiClient;
+
+ ///
+ /// Constructor.
+ ///
+ /// Reference to the microservice context.
+ /// Reference to the Keys Api client.
+ public KeysApiSampleController(IMicroserviceContext microserviceContext, IKeysApiClient keysApiClient) : base(microserviceContext)
+ {
+ _keysApiClient = keysApiClient ?? throw new ArgumentNullException(nameof(keysApiClient));
+ }
+
+ ///
+ /// A sample method that shows how to work with the Keys Api.
+ ///
+ internal async Task SampleAsync()
+ {
+ var applicationId = MicroserviceContext.Settings.Application.ApplicationId; // Id of this application
+ var category = "MySampleCategory".AsProtected(); // Keys are grouped by category
+ var key = "SampleKey".AsProtected(); // The name of the key
+ var value = "SampleValue".AsProtected(); // The value stored in the key
+
+ // Create a new key/value in the category for the application
+ await _keysApiClient.CreateKeyAsync(applicationId, category, key, value);
+
+ // Update the value stored at the key in the category for the application
+ await _keysApiClient.UpdateKeyAsync(applicationId, category, key, "UpdatedValue".AsProtected());
+
+ // Get the value stored at the key in the category for the application
+ var updatedValue = await _keysApiClient.GetKeyValueAsync(applicationId, category, key);
+
+ // Delete the key/value pair in the category for the application
+ await _keysApiClient.DeleteKeyAsync(applicationId, category, key);
+ }
+ }
+}
diff --git a/src/TriunniaLabs.Arch.Sample.Server/Controllers/TokensApiSampleController.cs b/src/TriunniaLabs.Arch.Sample.Server/Controllers/TokensApiSampleController.cs
new file mode 100644
index 0000000..434a8ca
--- /dev/null
+++ b/src/TriunniaLabs.Arch.Sample.Server/Controllers/TokensApiSampleController.cs
@@ -0,0 +1,52 @@
+using TriunniaLabs.Arch.Api.Tokens.Client;
+using TriunniaLabs.Arch.Microservice;
+using TriunniaLabs.Memory.Protected;
+
+namespace TriunniaLabs.Arch.Sample.Server
+{
+ ///
+ /// A controller that shows how to work the Tokens Api.
+ ///
+ public class TokensApiSampleController : ArchControllerBase
+ {
+ // Services
+ private readonly ITokensApiClient _tokensApiClient;
+
+ ///
+ /// Constructor.
+ ///
+ /// Reference to the microservice context.
+ /// Reference to the Tokens Api client.
+ public TokensApiSampleController(IMicroserviceContext microserviceContext, ITokensApiClient tokensApiClient) : base(microserviceContext)
+ {
+ _tokensApiClient = tokensApiClient ?? throw new ArgumentNullException(nameof(tokensApiClient));
+ }
+
+ ///
+ /// A sample method that shows how to work with the Tokens Api.
+ ///
+ internal async Task SampleAsync()
+ {
+ var ownerId = Guid.NewGuid().ToString().AsProtected(); // Who owns the token. Can be UserId or something else.
+ var ownerType = 1.AsProtected(); // Type of owner. Developer-specified field.
+ var ownerIpAddress = IpAddress.AsProtected(); // Ip address of the owner of the token.
+ var tokenType = 1.AsProtected(); // The type of token this is. Developer-specified field.
+ var minutes = 15.AsProtected(); // How long the token is valid in the system before it expires.
+
+ // Create a new token of the specified type for the owner
+ var tokenId = await _tokensApiClient.CreateTokenAsync(ownerId, ownerType, ownerIpAddress, tokenType, minutes);
+
+ // Get token by Id and type
+ var token = await _tokensApiClient.GetTokenAsync(tokenId, tokenType);
+
+ // Get token by Id, type, and Ip address
+ token = await _tokensApiClient.GetTokenAsync(tokenId, tokenType, ownerIpAddress);
+
+ // Get token by owner
+ token = await _tokensApiClient.GetTokenAsync(ownerId, ownerType, tokenType);
+
+ // Delete the specified token
+ await _tokensApiClient.DeleteTokenAsync(tokenId, tokenType);
+ }
+ }
+}