General Methods


title: “General Methods Overview”

General methods are utility functions available on the Client class that work across all object types. They provide core functionality for searching, counting, aggregating, and managing objects in the acre Access Control API.


Method Categories

Category Description Key Methods
Search & Query Find objects using MongoDB queries SearchAsync, SearchOneAsync, GetByMonikerAsync
Object Retrieval Get objects by ID or href GetByIdsAsync, GetByHrefAsync
Aggregation Run MongoDB aggregation pipelines AggregateAsync, AggregateAsJsonAsync
Counting Count objects by type GetObjectCountsAsync
Encryption Encrypt/decrypt sensitive data EncryptData, DecryptData
Client Properties Access client configuration BaseAddress, TokenResponse, UserAgent
SAML/SSO Configure identity providers SetSamlIdentityProviderConfiguration

Return Types

Method Type Default Return
Search methods IEnumerable<BaseInfo> (cast to specific types)
Count methods long
Single object BaseInfo or specified generic <T>
Aggregation BsonDocument[] or string (JSON)

Tip: Use .OfType<T>() to filter search results to specific object types:

var people = (await client.SearchAsync(folder, query))
    .OfType<PersonInfo>()
    .ToList();

Object Type Names

When specifying object types in queries, use the type name without the “Info” suffix:

C# Class Type Name
[PersonInfo](/object-model/personinfo/) Person
[ControllerInfo](/object-model/controllerinfo/) Controller
ReaderInfo Reader
[AccessLevelInfo](/object-model/accesslevelinfo/) AccessLevel
[ScheduleInfo](/object-model/scheduleinfo/) Schedule
[BaseInfo](/object-model/baseinfo/) KeepObject

Quick Reference

Search for Objects

// Search with MongoDB-style query
var results = await client.SearchAsync(
    folder,
    "{ '_t': 'Person', 'Surname': 'Smith' }",
    includeChildFolders: true
);

// Search for exactly one object
var person = await client.SearchOneAsync<PersonInfo>(
    folder,
    "{ 'CommonName': 'John Smith' }"
);

Get by Identifier

// Get multiple objects by key
var objects = await client.GetByIdsAsync(new[] { key1, key2, key3 });

// Get by href path
var controller = await client.GetByHrefAsync<ControllerInfo>(
    "/api/f/folder-key/controllers/controller-key"
);

// Get by moniker
var eventType = await client.GetByMonikerAsync<EventTypeInfo>(
    "MercuryServiceEvents",
    "mercury:access-granted"
);

Count Objects

// Count all people in folder
var count = await client.GetObjectCountsAsync(folder, "Person");

// Count with child folders
var totalCount = await client.GetObjectCountsAsync(
    folder, 
    "Controller", 
    includeChildFolders: true
);

Aggregate Data

// Run aggregation pipeline
var pipeline = new BsonDocument[]
{
    new BsonDocument("$match", new BsonDocument("_t", "Person")),
    new BsonDocument("$group", new BsonDocument
    {
        ["_id"] = "$Department",
        ["count"] = new BsonDocument("$sum", 1)
    })
};

var results = await client.AggregateAsync(folder, "KeepObjects", pipeline);

Add Access Level Acre Intrusion Entry Item Async

Example in C#

// Returns: nothing
await client.AddAccessLevelAcreIntrusionEntryItemAsync(AccessLevelInfo accessLevel, AccessLevelAcreIntrusionEntryItem entryItem);

Overview of AddAccessLevelAcreIntrusionEntryItemAsync goes here.

Add Access Level Assa Abloy Entry Item Async

Example in C#

// Returns: nothing
await client.AddAccessLevelAssaAbloyEntryItemAsync(AccessLevelInfo accessLevel, AccessLevelAssaAbloyEntryItem entryItem);

Overview of AddAccessLevelAssaAbloyEntryItemAsync goes here.

Add Access Level Batch For Person Async

Example in C#

// Returns: nothing
await client.AddAccessLevelBatchForPersonAsync(PersonInfo person, ObjectLinkItem accessLevelLinkItems);

Overview of AddAccessLevelBatchForPersonAsync goes here.

Add Access Level Batch For Person Async

Example in C#

// Returns: nothing
await client.AddAccessLevelBatchForPersonAsync(String personHref, ObjectLinkItem accessLevelLinkItems, String batchLink);

Overview of AddAccessLevelBatchForPersonAsync goes here.

Add Access Level Elevator Entry Item Async

Example in C#

// Returns: nothing
await client.AddAccessLevelElevatorEntryItemAsync(AccessLevelInfo accessLevel, AccessLevelElevatorEntryItem entryItem);

Overview of AddAccessLevelElevatorEntryItemAsync goes here.

Add Access Level Entry Item Async

Example in C#

// Returns: nothing
await client.AddAccessLevelEntryItemAsync(AccessLevelInfo accessLevel, AccessLevelEntryItem entryItem);

Overview of AddAccessLevelEntryItemAsync goes here.

Add Access Level Group Batch For Person Async

Example in C#

// Returns: nothing
await client.AddAccessLevelGroupBatchForPersonAsync(PersonInfo person, ObjectLinkItem accessLevelGroupLinkItems);

Overview of AddAccessLevelGroupBatchForPersonAsync goes here.

Add Access Level Group Batch For Person Async

Example in C#

// Returns: nothing
await client.AddAccessLevelGroupBatchForPersonAsync(String personHref, ObjectLinkItem accessLevelGroupLinkItems, String batchLink);

Overview of AddAccessLevelGroupBatchForPersonAsync goes here.

Add Access Level Traka Entry Item Async

Example in C#

// Returns: nothing
await client.AddAccessLevelTrakaEntryItemAsync(AccessLevelInfo accessLevel, AccessLevelTrakaEntryItem entryItem);

Overview of AddAccessLevelTrakaEntryItemAsync goes here.

Add Acre Intrusion Panel Area Entry Item Async

Example in C#

// Returns: nothing
await client.AddAcreIntrusionPanelAreaEntryItemAsync(AcreIntrusionUserProfileInfo userProfile, AcreIntrusionPanelRelationEntryItem panelRelation, AcreIntrusionAreaEntryItem entryItem);

Overview of AddAcreIntrusionPanelAreaEntryItemAsync goes here.

Add Acre Intrusion Panel Relation Entry Item Async

Example in C#

// Returns: nothing
await client.AddAcreIntrusionPanelRelationEntryItemAsync(AcreIntrusionUserProfileInfo userProfile, AcreIntrusionPanelRelationEntryItem entryItem);

Overview of AddAcreIntrusionPanelRelationEntryItemAsync goes here.

Add Cardholder Group Access Right Item Async

Example in C#

// Returns: nothing
await client.AddCardholderGroupAccessRightItemAsync(CardholderGroupInfo cardholderGroup, CardholderGroupAccessRightItem entryItem);

Overview of AddCardholderGroupAccessRightItemAsync goes here.

Add Traka Item Async

Example in C#

// Returns: TrakaItemInfo
var trakaItemInfo = await client.AddTrakaItemAsync(FolderInfo folder, TrakaItemInfo item);

Overview of AddTrakaItemAsync goes here.

Assign Connected Object Async

Example in C#

// Returns: nothing
await client.AssignConnectedObjectAsync(String targetHref, String connectionLink, String connectedObjectKey, String relation, Boolean isOneToOne, Object meta, Boolean addAsTag);

Overview of AssignConnectedObjectAsync goes here.

Check Schedule Is Active Async

Example in C#

// Returns: ScheduleInfo
var scheduleInfo = await client.CheckScheduleIsActiveAsync(ScheduleInfo schedule);

Overview of CheckScheduleIsActiveAsync goes here.

Check Script Last Run Async

Example in C#

// Returns: Boolean
var item = await client.CheckScriptLastRunAsync(FitPackageInfo packageInfo, String scriptName, Int32 minTimeBetweenRunsInMilliseconds);

Overview of CheckScriptLastRunAsync goes here.

Clean Acre Intrusion Panel Monikers Async

Example in C#

// Returns: nothing
await client.CleanAcreIntrusionPanelMonikersAsync(AcreIntrusionPanelInfo acreIntrusionPanel);

Overview of CleanAcreIntrusionPanelMonikersAsync goes here.

Delete Access Level Acre Intrusion Entry Item Async

Example in C#

// Returns: nothing
await client.DeleteAccessLevelAcreIntrusionEntryItemAsync(AccessLevelInfo accessLevel, AccessLevelAcreIntrusionEntryItem entryItem);

Overview of DeleteAccessLevelAcreIntrusionEntryItemAsync goes here.

Delete Access Level Assa Abloy Entry Item Async

Example in C#

// Returns: nothing
await client.DeleteAccessLevelAssaAbloyEntryItemAsync(AccessLevelInfo accessLevel, AccessLevelAssaAbloyEntryItem entryItem);

Overview of DeleteAccessLevelAssaAbloyEntryItemAsync goes here.

Delete Access Level Elevator Entry Item Async

Example in C#

// Returns: nothing
await client.DeleteAccessLevelElevatorEntryItemAsync(AccessLevelInfo accessLevel, AccessLevelElevatorEntryItem entryItem);

Overview of DeleteAccessLevelElevatorEntryItemAsync goes here.

Delete Access Level Entry Item Async

Example in C#

// Returns: nothing
await client.DeleteAccessLevelEntryItemAsync(AccessLevelInfo accessLevel, AccessLevelEntryItem entryItem);

Overview of DeleteAccessLevelEntryItemAsync goes here.

Delete Access Level Traka Entry Item Async

Example in C#

// Returns: nothing
await client.DeleteAccessLevelTrakaEntryItemAsync(AccessLevelInfo accessLevel, AccessLevelTrakaEntryItem entryItem);

Overview of DeleteAccessLevelTrakaEntryItemAsync goes here.

Delete Acre Intrusion Panel Area Entry Item Async

Example in C#

// Returns: nothing
await client.DeleteAcreIntrusionPanelAreaEntryItemAsync(AcreIntrusionUserProfileInfo userProfile, AcreIntrusionPanelRelationEntryItem panelRelation, AcreIntrusionAreaEntryItem entryItem);

Overview of DeleteAcreIntrusionPanelAreaEntryItemAsync goes here.

Delete Acre Intrusion Panel Relation Entry Item Async

Example in C#

// Returns: nothing
await client.DeleteAcreIntrusionPanelRelationEntryItemAsync(AcreIntrusionUserProfileInfo userProfile, AcreIntrusionPanelRelationEntryItem entryItem);

Overview of DeleteAcreIntrusionPanelRelationEntryItemAsync goes here.

Delete Cardholder Group Access Right Item Item Async

Example in C#

// Returns: nothing
await client.DeleteCardholderGroupAccessRightItemItemAsync(CardholderGroupInfo cardholderGroup, CardholderGroupAccessRightItem entryItem);

Overview of DeleteCardholderGroupAccessRightItemItemAsync goes here.

Delete Icons Async

Example in C#

// Returns: nothing
await client.DeleteIconsAsync(FolderInfo folder, String tag);

Overview of DeleteIconsAsync goes here.

Delete Traka Item Async

Example in C#

// Returns: nothing
await client.DeleteTrakaItemAsync(TrakaItemInfo item);

Overview of DeleteTrakaItemAsync goes here.

Delete Wallet Credential Async

Example in C#

// Returns: nothing
await client.DeleteWalletCredentialAsync(WalletGroupInfo walletGroup, WavelynxCardDeleteRequest deleteRequest);

Overview of DeleteWalletCredentialAsync goes here.

Disable Active Cards Async

Example in C#

// Returns: ExtendCardExpiryResponse
var extendCardExpiryResponse = await client.DisableActiveCardsAsync(FolderInfo folder, String query, Boolean trialRun);

Overview of DisableActiveCardsAsync goes here.

End Batch

Example in C#

// Returns: nothing
await client.EndBatch(InstanceInfo instance);

Overview of EndBatch goes here.

Equals

Example in C#

// Returns: Boolean
var item = client.Equals(Object obj);

The Equals method determines whether the specified object is equal to the current Client instance. This is a standard .NET object comparison method inherited from System.Object.

Method Signature

public override bool Equals(object obj)

Description

The Equals method provides object equality comparison for the Client class. This method is inherited from the base Object class and can be used to:

  • Compare Instances: Determine if two Client references point to the same instance
  • Collection Operations: Used internally by collections for equality checks
  • Conditional Logic: Compare objects in if statements or LINQ queries

Usage Example

using Feenics.Keep.WebApi.Wrapper;

// Create two client instances
var client1 = new Client("https://keep.feenics.com");
var client2 = new Client("https://keep.feenics.com");
var client3 = client1;

// Compare instances
bool areEqual1 = client1.Equals(client2);  // false - different instances
bool areEqual2 = client1.Equals(client3);  // true - same reference
bool areEqual3 = client1.Equals(null);     // false - comparing to null

Console.WriteLine($"client1 equals client2: {areEqual1}");
Console.WriteLine($"client1 equals client3: {areEqual2}");
Console.WriteLine($"client1 equals null: {areEqual3}");

Parameters

Parameter Type Description
obj object The object to compare with the current instance

Return Value

Type Description
bool true if the specified object is equal to the current instance; otherwise, false

Important Notes

💡 Reference Equality: By default, Equals compares object references, not the values of properties like BaseAddress or configuration settings.

💡 Null Safety: Calling Equals(null) always returns false and does not throw an exception.

Best Practices

  1. Use Reference Comparison: For Client objects, reference comparison is typically what you want
  2. Consider Purpose: If you need value-based comparison, compare specific properties instead
  3. Null Checks: Always safe to call even with null parameter

Alternative Comparison

// If you need to compare based on configuration
bool sameServer = client1.BaseAddress == client2.BaseAddress;
bool sameUser = client1.TokenResponse?.UserId == client2.TokenResponse?.UserId;
  • GetHashCode - Get the hash code for the object
  • GetType - Get the runtime type of the object
  • ToString - Get a string representation of the object

Extend Expired Cards Async

Example in C#

// Returns: ExtendCardExpiryResponse
var extendCardExpiryResponse = await client.ExtendExpiredCardsAsync(FolderInfo folder, DateTime expiredFrom, DateTime expiryEnd, DateTime newExpiresOn, Boolean trialRun);

Overview of ExtendExpiredCardsAsync goes here.

Get Base Address

Example in C#

// Returns: String
var item = client.BaseAddress;

title: “BaseAddress Property”

Returns the base URL of the acre Access Control API that the client is connected to.


Property

string BaseAddress { get; }

Returns

The API base URL as a string (e.g., https://api.us.acresecurity.cloud).


Example

C# Wrapper

var client = new Client(
    "https://api.us.acresecurity.cloud",
    clientId,
    clientSecret
);

await client.AuthenticateAsync();

// Get the base address
Console.WriteLine($"Connected to: {client.BaseAddress}");
// Output: Connected to: https://api.us.acresecurity.cloud

Use Cases

Use Case Description
Logging Log which environment is being used
Multi-environment Verify correct environment connection
URL construction Build full URLs for direct HTTP calls

Get Bytes Transferred

Example in C#

// Returns: Int64
var item = client.BytesTransferred;

Overview of get_BytesTransferred goes here.

Get Call Elapsed

Example in C#

// Returns: Int64
var item = client.CallElapsed;

Overview of get_CallElapsed goes here.

Get Client App Id

Example in C#

// Returns: String
var item = client.ClientAppId;

The ClientAppId property returns the unique identifier for the client application making API requests. This ID is used by the Keep API to identify and track requests from specific client applications.

Property Signature

public string ClientAppId { get; set; }

Description

The ClientAppId property provides access to the application identifier that is included in API request headers. This identifier helps the Keep API:

  • Track API Usage: Monitor which applications are making requests
  • Audit Logging: Associate actions with specific client applications
  • Rate Limiting: Apply application-specific rate limits if configured
  • Analytics: Gather usage statistics per application

Usage Example

using Feenics.Keep.WebApi.Wrapper;

// Create and configure the client
var client = new Client("https://keep.feenics.com");
await client.OpenAsync("username", "password", "my-client-app");

// Retrieve the current Client App ID
string appId = client.ClientAppId;
Console.WriteLine($"Current Client App ID: {appId}");

// The ClientAppId is typically set during authentication
// but can be modified if needed
client.ClientAppId = "updated-client-app-id";

Return Value

Type Description
string The client application identifier currently configured on the wrapper

Best Practices

  1. Use Descriptive IDs: Choose meaningful application identifiers that help with tracking and debugging
  2. Consistency: Use the same ClientAppId across sessions for the same application
  3. Versioning: Consider including version information (e.g., “MyApp-v2.1”)

Get Device Id

Example in C#

// Returns: String
var item = client.DeviceId;

The DeviceId property returns the unique identifier for the device making API requests. This ID helps the Keep API distinguish between different devices or installations of the same client application.

Property Signature

public string DeviceId { get; set; }

Description

The DeviceId property provides access to the device identifier that is included in API request headers. This identifier is particularly useful for:

  • Multi-Device Support: Track requests from different devices using the same account
  • Session Management: Identify which device initiated a particular session
  • Push Notifications: Route notifications to the correct device
  • Security Auditing: Track actions to specific devices for security reviews

Usage Example

using Feenics.Keep.WebApi.Wrapper;

// Create and configure the client
var client = new Client("https://keep.feenics.com");

// Set a unique device identifier before authentication
client.DeviceId = Guid.NewGuid().ToString();

await client.OpenAsync("username", "password", "my-client-app");

// Retrieve the current Device ID
string deviceId = client.DeviceId;
Console.WriteLine($"Current Device ID: {deviceId}");

Mobile Application Example

// For mobile applications, use a persistent device identifier
public async Task InitializeClientAsync()
{
    var client = new Client("https://keep.feenics.com");
    
    // Use a stored device ID or generate a new one
    string deviceId = await SecureStorage.GetAsync("device_id");
    if (string.IsNullOrEmpty(deviceId))
    {
        deviceId = Guid.NewGuid().ToString();
        await SecureStorage.SetAsync("device_id", deviceId);
    }
    
    client.DeviceId = deviceId;
    
    // Now authenticate
    await client.OpenAsync("username", "password", "mobile-app");
}

Return Value

Type Description
string The device identifier currently configured on the wrapper

Best Practices

  1. Persistence: Store the DeviceId persistently so the same device is consistently identified
  2. Uniqueness: Use GUIDs or other unique identifiers to ensure each device has a distinct ID
  3. Privacy: Don’t use hardware identifiers that could be used for tracking without consent

Get Flurl Client

Example in C#

// Returns: FlurlClient
var flurlClient = client.FlurlClient;

The FlurlClient property provides access to the underlying Flurl HTTP client used by the wrapper for all API communications. This allows advanced users to customize HTTP behavior or access low-level HTTP features.

Property Signature

public IFlurlClient FlurlClient { get; }

Description

The Keep API Wrapper uses Flurl as its HTTP client library. The FlurlClient property exposes this underlying client, enabling:

  • Custom HTTP Configuration: Modify timeouts, headers, or other HTTP settings
  • Request/Response Interception: Add custom handlers for logging or modification
  • Advanced HTTP Features: Access features not exposed by the wrapper directly
  • Debugging: Inspect or log raw HTTP traffic

Usage Example

using Feenics.Keep.WebApi.Wrapper;
using Flurl.Http;

// Create the wrapper client
var client = new Client("https://keep.feenics.com");
await client.OpenAsync("username", "password", "my-app");

// Access the underlying Flurl client
IFlurlClient flurlClient = client.FlurlClient;

// Configure custom timeout
flurlClient.WithTimeout(TimeSpan.FromSeconds(60));

// Add custom headers for all requests
flurlClient.WithHeader("X-Custom-Header", "CustomValue");

Advanced Configuration Example

using Feenics.Keep.WebApi.Wrapper;
using Flurl.Http;
using Flurl.Http.Configuration;

var client = new Client("https://keep.feenics.com");
await client.OpenAsync("username", "password", "my-app");

// Configure advanced HTTP settings
var flurlClient = client.FlurlClient;

// Add request/response logging
flurlClient.BeforeCall(call => 
{
    Console.WriteLine($"Request: {call.Request.Verb} {call.Request.Url}");
});

flurlClient.AfterCall(call => 
{
    Console.WriteLine($"Response: {call.Response?.StatusCode}");
});

// Handle errors globally
flurlClient.OnError(call =>
{
    Console.WriteLine($"Error: {call.Exception?.Message}");
    call.ExceptionHandled = true; // Prevent exception from bubbling up
});

Return Value

Type Description
IFlurlClient The Flurl HTTP client instance used for API requests

Important Notes

⚠️ Caution: Modifying the FlurlClient can affect the behavior of all wrapper methods. Make changes carefully and test thoroughly.

💡 Tip: For most use cases, the wrapper’s built-in methods are sufficient. Only access FlurlClient when you need advanced HTTP customization.

Common Use Cases

Use Case Configuration
Increase timeout flurlClient.WithTimeout(TimeSpan.FromMinutes(5))
Add proxy flurlClient.Settings.HttpClientFactory = new ProxyHttpClientFactory()
Custom logging Use BeforeCall and AfterCall handlers
Retry logic Implement using OnError handler

Get Token Response

Example in C#

// Returns: TokenResponse
var tokenResponse = client.TokenResponse;

title: “TokenResponse Property”

Returns the current OAuth token response containing the access token, refresh token, and expiration information.


Property

TokenResponse TokenResponse { get; set; }

TokenResponse Structure

Property Type Description
access_token string Bearer token for API authentication
refresh_token string Token for obtaining new access tokens
expires_in int Seconds until token expiration
token_type string Always “Bearer”

Examples

C# Wrapper

// Check current token
var token = client.TokenResponse;
Console.WriteLine($"Token expires in: {token.expires_in} seconds");

// Create new client with existing token
var existingToken = new TokenResponse 
{ 
    access_token = "existing-token-value" 
};

var newClient = new Client(
    "https://api.acresecurity.cloud",
    existingToken,
    userAgent: "MyApp/1.0"
);

Use Cases

Use Case Description
Token reuse Pass token to another client instance
Debugging Inspect token for troubleshooting
Token refresh Check expiration before calls

Get User Agent

Example in C#

// Returns: String
var item = client.UserAgent;

The UserAgent property returns the user agent string that is sent with all API requests. This string identifies the client application, version, and platform making requests to the Keep API.

Property Signature

public string UserAgent { get; }

Description

The UserAgent property provides access to the user agent header value included in all HTTP requests. This identifier helps with:

  • Request Identification: Identify the type of client making requests
  • Compatibility: Allow the server to tailor responses based on client capabilities
  • Debugging: Trace requests in server logs by client type
  • Analytics: Track API usage by client application and version

Usage Example

using Feenics.Keep.WebApi.Wrapper;

// Create and authenticate the client
var client = new Client("https://keep.feenics.com");
await client.OpenAsync("username", "password", "my-app");

// Retrieve the user agent string
string userAgent = client.UserAgent;
Console.WriteLine($"User Agent: {userAgent}");

// Example output: "Keep.WebApi.Wrapper/2.0.0 (Windows NT 10.0; .NET 6.0)"

User Agent Format

The user agent typically follows this format:

{ApplicationName}/{Version} ({Platform}; {Framework})

Components

Component Description Example
Application Name Name of the wrapper library Keep.WebApi.Wrapper
Version Version of the wrapper 2.0.0
Platform Operating system information Windows NT 10.0, iOS 16.0
Framework Runtime framework .NET 6.0, Xamarin.iOS

Platform Examples

// Windows Desktop Application
// "Keep.WebApi.Wrapper/2.0.0 (Windows NT 10.0; .NET 6.0)"

// iOS Mobile Application
// "Keep.WebApi.Wrapper/2.0.0 (iOS 16.0; Xamarin.iOS)"

// Android Mobile Application
// "Keep.WebApi.Wrapper/2.0.0 (Android 13; Xamarin.Android)"

// macOS Application
// "Keep.WebApi.Wrapper/2.0.0 (macOS 13.0; .NET 6.0)"

// Linux Server
// "Keep.WebApi.Wrapper/2.0.0 (Linux; .NET 6.0)"

Debugging with User Agent

using Feenics.Keep.WebApi.Wrapper;

public async Task DiagnoseConnectionAsync(Client client)
{
    Console.WriteLine("=== Connection Diagnostics ===");
    Console.WriteLine($"Base Address: {client.BaseAddress}");
    Console.WriteLine($"User Agent: {client.UserAgent}");
    Console.WriteLine($"Client App ID: {client.ClientAppId}");
    Console.WriteLine($"Device ID: {client.DeviceId}");
    
    // Test connection
    try
    {
        var instances = await client.GetInstancesAsync();
        Console.WriteLine($"Connected successfully. Found {instances.Count()} instances.");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Connection failed: {ex.Message}");
    }
}

Return Value

Type Description
string The user agent string identifying the client application and platform

Best Practices

  1. Don’t Modify: The UserAgent is automatically set by the wrapper and should not typically be changed
  2. Use for Diagnostics: Helpful when troubleshooting connection issues
  3. Log for Support: Include in support tickets to help identify client environment

Get All Installed Bulk Action Object Types

Example in C#

// Returns: IEnumerable<String>
var item = await client.GetAllInstalledBulkActionObjectTypes(FolderInfo folder);

Overview of GetAllInstalledBulkActionObjectTypes goes here.

Get Asc1400 Ports Async

Example in C#

// Returns: IEnumerable<SmartControllerPortItem>
var smartControllerPortItem = await client.GetAsc1400PortsAsync(Asc1400Info controller);

Overview of GetAsc1400PortsAsync goes here.

Get Cabinets For Traka Service Async

Example in C#

// Returns: IEnumerable<TrakaCabinetInfo>
var trakaCabinetInfo = await client.GetCabinetsForTrakaServiceAsync(TrakaServiceInfo service);

Overview of GetCabinetsForTrakaServiceAsync goes here.

Get Hash Code

Example in C#

// Returns: Int32
var item = client.GetHashCode();

The GetHashCode method returns a hash code for the current Client instance. This is a standard .NET method inherited from System.Object that is used for hash-based collection operations.

Method Signature

public override int GetHashCode()

Description

The GetHashCode method generates a numeric hash value that represents the current object. This hash code is used by:

  • Hash-Based Collections: Dictionary<TKey, TValue>, HashSet<T>, and Hashtable use hash codes for efficient lookups
  • Equality Operations: Works in conjunction with Equals for object comparison
  • Caching: Hash codes can be used as cache keys

Usage Example

using Feenics.Keep.WebApi.Wrapper;

// Create a client instance
var client = new Client("https://keep.feenics.com");
await client.OpenAsync("username", "password", "my-app");

// Get the hash code
int hashCode = client.GetHashCode();
Console.WriteLine($"Client hash code: {hashCode}");

// Example: Using client as dictionary key
var clientData = new Dictionary<Client, string>();
clientData[client] = "Primary Connection";

// Retrieve using the same reference
string data = clientData[client];
Console.WriteLine($"Data: {data}");

Return Value

Type Description
int A 32-bit signed integer hash code representing the object

Hash Code Characteristics

Characteristic Description
Consistency Same object returns same hash code during its lifetime
Not Unique Different objects may have the same hash code (collision)
Reference-Based Default implementation is based on object reference
Session-Specific Hash codes may differ between application runs

Important Notes

⚠️ Not for Persistence: Hash codes should not be stored or used across application sessions

⚠️ Collision Possible: Two different objects may return the same hash code

💡 Equality Contract: If Equals returns true for two objects, they must have the same hash code

Best Practices

  1. Don’t Persist: Never save hash codes to databases or files
  2. Don’t Compare: Use Equals for object comparison, not hash codes
  3. Collection Use: Safe to use Client objects as dictionary keys (reference-based)

Example: Client Tracking

using Feenics.Keep.WebApi.Wrapper;

public class ClientConnectionPool
{
    private readonly HashSet<Client> _activeClients = new HashSet<Client>();
    
    public void AddClient(Client client)
    {
        // HashSet uses GetHashCode internally
        _activeClients.Add(client);
    }
    
    public bool IsClientActive(Client client)
    {
        // Lookup uses GetHashCode for efficiency
        return _activeClients.Contains(client);
    }
    
    public void RemoveClient(Client client)
    {
        _activeClients.Remove(client);
    }
}
  • Equals - Compare objects for equality
  • GetType - Get the runtime type of the object
  • ToString - Get a string representation of the object

Get Marketplace UIPoints Async

Example in C#

// Returns: MarketplaceUIPointsResponse
var item = await client.GetMarketplaceUIPointsAsync(FolderInfo folder);

Overview of GetMarketplaceUIPointsAsync goes here.

Get Next Available Card Number Async

Example in C#

// Returns: Int64
var item = await client.GetNextAvailableCardNumberAsync(FolderInfo folder, Int64 startingValue);

Overview of GetNextAvailableCardNumberAsync goes here.

Get Nonce Async

Example in C#

// Returns: String
var item = await client.GetNonceAsync(PersonInfo person);

Overview of GetNonceAsync goes here.

Get Random40 Bit Card Number

Example in C#

// Returns: Int64
var item = await client.GetRandom40BitCardNumber();

Overview of GetRandom40BitCardNumber goes here.

Get Random Visit Code Async

Example in C#

// Returns: Int64
var item = await client.GetRandomVisitCodeAsync(FolderInfo folder);

Overview of GetRandomVisitCodeAsync goes here.

Get Read Notifications For User Async

Example in C#

// Returns: IEnumerable<NotificationInfo>
var notificationInfo = await client.GetReadNotificationsForUserAsync(FolderInfo folder, UserInfo user, DateTime beforeStartDate, DateTime beforeEndDate, Int32 skip, Int32 limit);

Overview of GetReadNotificationsForUserAsync goes here.

Get Smart Controller Port Definitions Async

Example in C#

// Returns: IEnumerable<SmartControllerPortItem>
var smartControllerPortItem = await client.GetSmartControllerPortDefinitionsAsync(AcreControllerInfo controllerInfo);

Overview of GetSmartControllerPortDefinitionsAsync goes here.

Get Smart Controller Port Definitions Async

Example in C#

// Returns: IEnumerable<SmartControllerPortItem>
var smartControllerPortItem = await client.GetSmartControllerPortDefinitionsAsync<T>();

Overview of GetSmartControllerPortDefinitionsAsync goes here.

Get Smart Controller Port Definitions Async

Example in C#

// Returns: IEnumerable<SmartControllerPortItem>
var smartControllerPortItem = await client.GetSmartControllerPortDefinitionsAsync(String controllerTypeInfoName);

Overview of GetSmartControllerPortDefinitionsAsync goes here.

Get Supported Reader Types

Example in C#

// Returns: IEnumerable<String>
var item = await client.GetSupportedReaderTypes<T>();

Overview of GetSupportedReaderTypes goes here.

Get Supported Reader Types

Example in C#

// Returns: IEnumerable<String>
var item = await client.GetSupportedReaderTypes(String readerProfileTypeName);

Overview of GetSupportedReaderTypes goes here.

Get Traka Item Async

Example in C#

// Returns: TrakaItemInfo
var trakaItemInfo = await client.GetTrakaItemAsync(FolderInfo folder, String itemId);

Overview of GetTrakaItemAsync goes here.

Get Traka Items Async

Example in C#

// Returns: IEnumerable<TrakaItemInfo>
var trakaItemInfo = await client.GetTrakaItemsAsync(FolderInfo folder);

Overview of GetTrakaItemsAsync goes here.

Get Type

Example in C#

// Returns: Type
var type = client.GetType();

The GetType method returns the runtime type of the current Client instance. This is a standard .NET method inherited from System.Object that provides reflection capabilities.

Method Signature

public Type GetType()

Description

The GetType method returns a Type object that represents the exact runtime type of the current instance. This is useful for:

  • Type Inspection: Examine the type hierarchy and implemented interfaces
  • Reflection: Access properties, methods, and attributes dynamically
  • Debugging: Log or display type information for diagnostics
  • Dynamic Operations: Perform type-based logic at runtime

Usage Example

using Feenics.Keep.WebApi.Wrapper;

// Create a client instance
var client = new Client("https://keep.feenics.com");

// Get the runtime type
Type clientType = client.GetType();

// Display type information
Console.WriteLine($"Type Name: {clientType.Name}");
Console.WriteLine($"Full Name: {clientType.FullName}");
Console.WriteLine($"Namespace: {clientType.Namespace}");
Console.WriteLine($"Assembly: {clientType.Assembly.GetName().Name}");

Example Output

Type Name: Client
Full Name: Feenics.Keep.WebApi.Wrapper.Client
Namespace: Feenics.Keep.WebApi.Wrapper
Assembly: Feenics.Keep.WebApi.Wrapper

Return Value

Type Description
Type A System.Type object representing the runtime type of the instance

Reflection Examples

using Feenics.Keep.WebApi.Wrapper;
using System.Reflection;

var client = new Client("https://keep.feenics.com");
Type clientType = client.GetType();

// List all public methods
Console.WriteLine("=== Public Methods ===");
foreach (MethodInfo method in clientType.GetMethods(BindingFlags.Public | BindingFlags.Instance))
{
    Console.WriteLine($"  {method.Name}");
}

// List all public properties
Console.WriteLine("\n=== Public Properties ===");
foreach (PropertyInfo prop in clientType.GetProperties())
{
    Console.WriteLine($"  {prop.Name}: {prop.PropertyType.Name}");
}

// Check for specific interface implementation
bool implementsDisposable = typeof(IDisposable).IsAssignableFrom(clientType);
Console.WriteLine($"\nImplements IDisposable: {implementsDisposable}");

Type Checking Example

using Feenics.Keep.WebApi.Wrapper;

public void ProcessObject(object obj)
{
    Type objType = obj.GetType();
    
    // Check if it's a Client
    if (objType == typeof(Client))
    {
        var client = (Client)obj;
        Console.WriteLine($"Processing Client for: {client.BaseAddress}");
    }
    
    // Alternative: Use pattern matching (preferred in modern C#)
    if (obj is Client typedClient)
    {
        Console.WriteLine($"Processing Client for: {typedClient.BaseAddress}");
    }
}

Dynamic Property Access

using Feenics.Keep.WebApi.Wrapper;

var client = new Client("https://keep.feenics.com");
await client.OpenAsync("username", "password", "my-app");

// Get property value dynamically
Type clientType = client.GetType();
PropertyInfo baseAddressProp = clientType.GetProperty("BaseAddress");

if (baseAddressProp != null)
{
    object value = baseAddressProp.GetValue(client);
    Console.WriteLine($"Base Address (via reflection): {value}");
}

Important Notes

💡 Runtime Type: Returns the actual runtime type, which may be a derived type

💡 Never Null: This method never returns null

💡 Performance: Reflection operations can be slower than direct property access

Best Practices

  1. Prefer Direct Access: Use properties and methods directly when possible
  2. Cache Type Objects: If using GetType repeatedly, cache the result
  3. Use Pattern Matching: For type checking, prefer is and switch patterns
  • Equals - Compare objects for equality
  • GetHashCode - Get the hash code for the object
  • ToString - Get a string representation of the object

Get Unread Notifications For User Async

Example in C#

// Returns: IEnumerable<NotificationInfo>
var notificationInfo = await client.GetUnreadNotificationsForUserAsync(FolderInfo folder, UserInfo user, DateTime beforeStartDate, DateTime beforeEndDate, Int32 skip, Int32 limit, DateTime afterStartDate, DateTime afterEndDate);

Overview of GetUnreadNotificationsForUserAsync goes here.

Initialize Reader

Example in C#

// Returns: nothing
await client.InitializeReader(MercuryReaderInfo reader);

Overview of InitializeReader goes here.

Leave Script Queue

Example in C#

// Returns: nothing
await client.LeaveScriptQueue(FolderInfo folder, String scriptQueueObjectId);

Overview of LeaveScriptQueue goes here.

Logout Async

Example in C#

// Returns: Boolean
var item = await client.LogoutAsync();

Overview of LogoutAsync goes here.

Mark All Notification As Read For User

Example in C#

// Returns: nothing
await client.MarkAllNotificationAsReadForUser(FolderInfo folder, UserInfo user);

Overview of MarkAllNotificationAsReadForUser goes here.

Mark Notification As Read For User

Example in C#

// Returns: nothing
await client.MarkNotificationAsReadForUser(FolderInfo folder, NotificationInfo notification, UserInfo user);

Overview of MarkNotificationAsReadForUser goes here.

Mark Notification As Unread For User

Example in C#

// Returns: nothing
await client.MarkNotificationAsUnreadForUser(FolderInfo folder, NotificationInfo notification, UserInfo user);

Overview of MarkNotificationAsUnreadForUser goes here.

Mark Person In Async

Example in C#

// Returns: Boolean
var item = await client.MarkPersonInAsync(PersonInfo person, String readerId);

Overview of MarkPersonInAsync goes here.

Mark Person Out Async

Example in C#

// Returns: Boolean
var item = await client.MarkPersonOutAsync(PersonInfo person, String readerId);

Overview of MarkPersonOutAsync goes here.

Patch Card Assignment Async

Example in C#

// Returns: nothing
await client.PatchCardAssignmentAsync(String personHref, String cardAssignmentKey, CardAssignmentInfo patchDoc, String encodedCardNumberStringOverride);

Overview of PatchCardAssignmentAsync goes here.

Patch With Query Params

Example in C#

// Returns: nothing
await client.PatchWithQueryParams(item patchDoc, Object queryParameters, String uriSegments);

Overview of PatchWithQueryParams goes here.

Post Corporate Card Async

Example in C#

// Returns: WalletVisitorCardResponse
var walletVisitorCardResponse = await client.PostCorporateCardAsync(WalletGroupInfo walletGroup, WalletCorporateCardRequest corporateCardRequest);

Overview of PostCorporateCardAsync goes here.

Post Visitor Card Async

Example in C#

// Returns: WalletVisitorCardResponse
var walletVisitorCardResponse = await client.PostVisitorCardAsync(WalletGroupInfo walletGroup, WalletVisitorCardRequest visitorCardRequest);

Overview of PostVisitorCardAsync goes here.

Remove Access Level Batch For Person Async

Example in C#

// Returns: nothing
await client.RemoveAccessLevelBatchForPersonAsync(PersonInfo person, ObjectLinkItem accessLevelLinkItems);

Overview of RemoveAccessLevelBatchForPersonAsync goes here.

Remove Access Level Batch For Person Async

Example in C#

// Returns: nothing
await client.RemoveAccessLevelBatchForPersonAsync(String personHref, ObjectLinkItem accessLevelLinkItems, String batchLink);

Overview of RemoveAccessLevelBatchForPersonAsync goes here.

Remove Access Level Group Batch For Person Async

Example in C#

// Returns: nothing
await client.RemoveAccessLevelGroupBatchForPersonAsync(PersonInfo person, ObjectLinkItem accessLevelGroupLinkItems);

Overview of RemoveAccessLevelGroupBatchForPersonAsync goes here.

Remove Access Level Group Batch For Person Async

Example in C#

// Returns: nothing
await client.RemoveAccessLevelGroupBatchForPersonAsync(String personHref, ObjectLinkItem accessLevelGroupLinkItems, String batchLink);

Overview of RemoveAccessLevelGroupBatchForPersonAsync goes here.

Remove Asc1400 Port Async

Example in C#

// Returns: nothing
await client.RemoveAsc1400PortAsync(Asc1400Info controllerInfo, Int32 port);

Overview of RemoveAsc1400PortAsync goes here.

Remove Connected Object Async

Example in C#

// Returns: nothing
await client.RemoveConnectedObjectAsync(String targetHref, String connectedObjectKey, String relation);

Overview of RemoveConnectedObjectAsync goes here.

Remove Tag2 Async

Example in C#

// Returns: nothing
await client.RemoveTag2Async(String itemHref, String tag);

Overview of RemoveTag2Async goes here.

Reset Acre Intrusion Panel Enc Key Async

Example in C#

// Returns: nothing
await client.ResetAcreIntrusionPanelEncKeyAsync(AcreIntrusionPanelInfo acreIntrusionPanel);

Overview of ResetAcreIntrusionPanelEncKeyAsync goes here.

Send Group To Wavelynx

Example in C#

// Returns: nothing
await client.SendGroupToWavelynx(FolderInfo folder, WalletGroupInfo item);

Overview of SendGroupToWavelynx goes here.

Send Mobile Invite Async

Example in C#

// Returns: Boolean
var item = await client.SendMobileInviteAsync(PersonInfo person, String messageTemplateKey);

Overview of SendMobileInviteAsync goes here.

Send Mobile Invite Async

Example in C#

// Returns: Boolean
var item = await client.SendMobileInviteAsync(String personHref, String messageTemplateKey, String inviteHref);

Overview of SendMobileInviteAsync goes here.

Set Client App Id

Example in C#

// Returns: nothing
client.ClientAppId = clientAppId;

The ClientAppId property setter allows you to configure the unique identifier for your client application. This ID is included in API request headers and helps the Keep API track and identify requests from your application.

Property Signature

public string ClientAppId { get; set; }

Description

Setting the ClientAppId establishes the application identity that will be associated with all subsequent API requests. This is important for:

  • Application Identification: Distinguish your application in logs and analytics
  • Audit Trails: Track which application performed specific actions
  • Support & Debugging: Easily identify request sources when troubleshooting
  • Usage Analytics: Monitor API usage per application

Usage Example

using Feenics.Keep.WebApi.Wrapper;

// Create the client
var client = new Client("https://keep.feenics.com");

// Set the Client App ID before authentication
client.ClientAppId = "MyAccessControlApp-v2.0";

// Authenticate
await client.OpenAsync("username", "password", "MyAccessControlApp-v2.0");

// The ClientAppId can also be updated after authentication if needed
client.ClientAppId = "MyAccessControlApp-v2.1-hotfix";
// Include application name and version
client.ClientAppId = "VisitorManagement-v1.5";

// Include environment for development/testing
client.ClientAppId = "CardholderSync-v3.0-dev";

// Include organization for multi-tenant scenarios
client.ClientAppId = "AcmeCorp-BadgePrinter-v1.0";

Parameter

Parameter Type Description
value string The application identifier to associate with API requests

Best Practices

  1. Set Before Authentication: Configure the ClientAppId before calling OpenAsync()
  2. Include Version Numbers: Makes it easier to track issues to specific releases
  3. Be Consistent: Use the same format across all your applications
  4. Avoid Sensitive Data: Don’t include passwords, keys, or personal information

Common Patterns

// Pattern 1: Simple application name
client.ClientAppId = "MobileCredentialApp";

// Pattern 2: Name with version
client.ClientAppId = "AccessExpert-iOS-v4.2.1";

// Pattern 3: Organization and application
client.ClientAppId = "Feenics-IntegrationService-v2.0";

// Pattern 4: Environment-aware
string env = Environment.GetEnvironmentVariable("APP_ENV") ?? "prod";
client.ClientAppId = $"CardholderSync-v1.0-{env}";

Set Device Id

Example in C#

// Returns: nothing
client.DeviceId = deviceId;

The DeviceId property setter allows you to configure the unique identifier for the device making API requests. This ID helps distinguish between different devices or installations of your application.

Property Signature

public string DeviceId { get; set; }

Description

Setting the DeviceId establishes the device identity that will be associated with all subsequent API requests. This is particularly important for:

  • Multi-Device Scenarios: Track which device is making requests
  • Push Notifications: Route notifications to the correct device
  • Session Management: Identify device-specific sessions
  • Security Auditing: Track actions to specific devices

Usage Example

using Feenics.Keep.WebApi.Wrapper;

// Create the client
var client = new Client("https://keep.feenics.com");

// Generate or retrieve a unique device identifier
string deviceId = Guid.NewGuid().ToString();

// Set the Device ID before authentication
client.DeviceId = deviceId;

// Authenticate
await client.OpenAsync("username", "password", "my-app");

Persistent Device ID Example

using Feenics.Keep.WebApi.Wrapper;

public class DeviceManager
{
    private const string DeviceIdKey = "keep_device_id";
    
    public async Task<Client> CreateAuthenticatedClientAsync(string baseUrl, string username, string password)
    {
        var client = new Client(baseUrl);
        
        // Retrieve or create a persistent device ID
        string deviceId = await GetOrCreateDeviceIdAsync();
        client.DeviceId = deviceId;
        
        await client.OpenAsync(username, password, "my-app");
        return client;
    }
    
    private async Task<string> GetOrCreateDeviceIdAsync()
    {
        // Try to retrieve existing device ID
        string deviceId = Preferences.Get(DeviceIdKey, null);
        
        if (string.IsNullOrEmpty(deviceId))
        {
            // Generate new device ID and store it
            deviceId = Guid.NewGuid().ToString();
            Preferences.Set(DeviceIdKey, deviceId);
        }
        
        return deviceId;
    }
}

Parameter

Parameter Type Description
value string The unique identifier for the device making API requests

Device ID Formats

// Format 1: GUID (recommended)
client.DeviceId = Guid.NewGuid().ToString();
// Example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"

// Format 2: Custom format with device info
client.DeviceId = $"iOS-{deviceModel}-{Guid.NewGuid():N}";
// Example: "iOS-iPhone14-a1b2c3d4e5f67890abcdef1234567890"

// Format 3: Hash-based (for privacy)
client.DeviceId = ComputeSha256Hash(uniqueDeviceInfo);

Best Practices

  1. Persist the Device ID: Store it securely so the same device is consistently identified across app restarts
  2. Generate Once: Create the device ID on first run and reuse it
  3. Use Unique Values: GUIDs or similar unique identifiers prevent collisions
  4. Consider Privacy: Don’t use hardware identifiers that could track users without consent
  5. Set Before Auth: Configure the DeviceId before calling OpenAsync()

Platform-Specific Examples

// iOS/macOS - Use Keychain for secure storage
client.DeviceId = await SecureStorage.GetAsync("device_id") 
    ?? await GenerateAndStoreDeviceIdAsync();

// Android - Use EncryptedSharedPreferences
client.DeviceId = encryptedPrefs.GetString("device_id", null)
    ?? GenerateAndStoreDeviceId();

// Desktop - Use local app data
client.DeviceId = File.Exists(deviceIdPath) 
    ? File.ReadAllText(deviceIdPath)
    : GenerateAndStoreDeviceId(deviceIdPath);

Set Token Response

Example in C#

// Returns: nothing
client.TokenResponse = tokenResponse;

The TokenResponse property setter allows you to manually configure authentication token information on the wrapper client. This is useful for scenarios where you need to restore a session or use tokens obtained through alternative authentication flows.

Property Signature

public TokenResponse TokenResponse { get; set; }

Description

Setting the TokenResponse allows you to:

  • Restore Sessions: Resume an authenticated session without re-authenticating
  • Token Sharing: Share authentication between multiple client instances
  • Custom Auth Flows: Use tokens obtained through external authentication mechanisms
  • Session Persistence: Store and restore sessions across application restarts

Usage Example

using Feenics.Keep.WebApi.Wrapper;

// Scenario: Restore a previously saved session
var client = new Client("https://keep.feenics.com");

// Load saved token response from secure storage
TokenResponse savedToken = await LoadTokenFromSecureStorageAsync();

// Set the token response to restore the session
client.TokenResponse = savedToken;

// Now you can make authenticated API calls without re-authenticating
var instances = await client.GetInstancesAsync();

Session Persistence Example

using Feenics.Keep.WebApi.Wrapper;
using System.Text.Json;

public class SessionManager
{
    private const string TokenKey = "keep_auth_token";
    
    // Save session for later restoration
    public async Task SaveSessionAsync(Client client)
    {
        if (client.TokenResponse != null)
        {
            string tokenJson = JsonSerializer.Serialize(client.TokenResponse);
            await SecureStorage.SetAsync(TokenKey, tokenJson);
        }
    }
    
    // Restore a saved session
    public async Task<Client> RestoreSessionAsync(string baseUrl)
    {
        var client = new Client(baseUrl);
        
        string tokenJson = await SecureStorage.GetAsync(TokenKey);
        if (!string.IsNullOrEmpty(tokenJson))
        {
            var savedToken = JsonSerializer.Deserialize<TokenResponse>(tokenJson);
            
            // Check if token is still valid
            if (savedToken.ExpiresAt > DateTime.UtcNow)
            {
                client.TokenResponse = savedToken;
                return client;
            }
        }
        
        // Token expired or not found - need to re-authenticate
        return null;
    }
}

TokenResponse Properties

Property Type Description
AccessToken string The JWT access token for API authentication
RefreshToken string Token used to obtain new access tokens
ExpiresIn int Token lifetime in seconds
ExpiresAt DateTime Absolute expiration time of the token
TokenType string Type of token (typically “Bearer”)

Token Refresh Example

using Feenics.Keep.WebApi.Wrapper;

public class TokenRefreshHandler
{
    private readonly Client _client;
    
    public TokenRefreshHandler(Client client)
    {
        _client = client;
    }
    
    public async Task EnsureValidTokenAsync()
    {
        var token = _client.TokenResponse;
        
        // Check if token needs refresh (e.g., within 5 minutes of expiry)
        if (token != null && token.ExpiresAt <= DateTime.UtcNow.AddMinutes(5))
        {
            // Refresh the token
            var newToken = await _client.RefreshTokenAsync();
            
            // The wrapper automatically updates TokenResponse after refresh
            Console.WriteLine($"Token refreshed. New expiry: {_client.TokenResponse.ExpiresAt}");
        }
    }
}

Important Notes

⚠️ Security: Always store TokenResponse securely (encrypted storage, keychain, etc.)

⚠️ Expiration: Check token expiration before using a restored session

💡 Tip: The wrapper automatically manages tokens during normal authentication. Only use this setter for advanced scenarios.

Best Practices

  1. Secure Storage: Never store tokens in plain text
  2. Validate Before Use: Check ExpiresAt before restoring a session
  3. Handle Refresh: Implement token refresh logic for long-running applications
  4. Clear on Logout: Set to null when logging out to ensure clean state

Set Access Level Batch For Person Async

Example in C#

// Returns: nothing
await client.SetAccessLevelBatchForPersonAsync(PersonInfo person, ObjectLinkItem accessLevelLinkItems);

Overview of SetAccessLevelBatchForPersonAsync goes here.

Set Access Level Batch For Person Async

Example in C#

// Returns: nothing
await client.SetAccessLevelBatchForPersonAsync(String personHref, ObjectLinkItem accessLevelLinkItems, String batchLink);

Overview of SetAccessLevelBatchForPersonAsync goes here.

Set Access Level Batch For Person By Hrefs Async

Example in C#

// Returns: nothing
await client.SetAccessLevelBatchForPersonByHrefsAsync(PersonInfo person, String accessLevelHrefs);

Overview of SetAccessLevelBatchForPersonByHrefsAsync goes here.

Set Access Level Group Batch For Person Async

Example in C#

// Returns: nothing
await client.SetAccessLevelGroupBatchForPersonAsync(PersonInfo person, ObjectLinkItem accessLevelGroupLinkItems);

Overview of SetAccessLevelGroupBatchForPersonAsync goes here.

Set Access Level Group Batch For Person Async

Example in C#

// Returns: nothing
await client.SetAccessLevelGroupBatchForPersonAsync(String personHref, ObjectLinkItem accessLevelGroupLinkItems, String batchLink);

Overview of SetAccessLevelGroupBatchForPersonAsync goes here.

Set Asc1400 Port Async

Example in C#

// Returns: Asc1400Info
var asc1400Info = await client.SetAsc1400PortAsync(Asc1400Info controller, SmartControllerPortItem portItem);

Overview of SetAsc1400PortAsync goes here.

Set Asc1400 Port Async

Example in C#

// Returns: Asc1400Info
var asc1400Info = await client.SetAsc1400PortAsync(Asc1400Info controller, SmartControllerPortItem portItems);

Overview of SetAsc1400PortAsync goes here.

Set Icons Async

Example in C#

// Returns: IEnumerable<MarketplaceImageInfo>
var marketplaceImageInfo = await client.SetIconsAsync(FolderInfo folder, MarketplaceImageInfo icons);

Overview of SetIconsAsync goes here.

Set Instance Time Zone Async

Example in C#

// Returns: nothing
await client.SetInstanceTimeZoneAsync(InstanceInfo instance, String newTimeZone);

Overview of SetInstanceTimeZoneAsync goes here.

Set Is Disabled Async

Example in C#

// Returns: nothing
await client.SetIsDisabledAsync(CardAssignmentInfo cardAssignment, Boolean isDisabled);

Overview of SetIsDisabledAsync goes here.

Set Next Cron Job Run Async

Example in C#

// Returns: nothing
await client.SetNextCronJobRunAsync(CronJobInfo cronJob);

Overview of SetNextCronJobRunAsync goes here.

Start Batch

Example in C#

// Returns: nothing
await client.StartBatch(InstanceInfo instance);

Overview of StartBatch goes here.

To String

Example in C#

// Returns: String
var item = client.ToString();

The ToString method returns a string representation of the current Client instance. This is a standard .NET method inherited from System.Object that is applicable to all Wrapper (Client) methods. The BaseInfo model object also has a similar method.

Method Signature

public override string ToString()

Description

The ToString method provides a human-readable string representation of the object. This is useful for:

  • Debugging: Quick inspection of object state
  • Logging: Include object information in log messages
  • Display: Show object details in UI or console output
  • Diagnostics: Understand object configuration at a glance

Usage Example

using Feenics.Keep.WebApi.Wrapper;

// Create and configure a client
var client = new Client("https://keep.feenics.com");
await client.OpenAsync("username", "password", "my-app");

// Get string representation
string clientInfo = client.ToString();
Console.WriteLine(clientInfo);

// Use in string interpolation
Console.WriteLine($"Current client: {client}");

// Use in logging
logger.LogInformation("API Client initialized: {Client}", client);

Return Value

Type Description
string A string representation of the current object

BaseInfo ToString Example

The BaseInfo model objects also implement ToString for easy inspection:

using Feenics.Keep.WebApi.Wrapper;

var client = new Client("https://keep.feenics.com");
await client.OpenAsync("username", "password", "my-app");

// Get a cardholder
var cardholder = await client.SearchOneAsync<CardholderInfo>(
    instanceId, 
    "$filter=FirstName eq 'John'"
);

// Display cardholder information
Console.WriteLine($"Found: {cardholder}");

// Get an access level
var accessLevel = await client.SearchOneAsync<AccessLevelInfo>(
    instanceId,
    "$filter=CommonName eq 'Employee Access'"
);

Console.WriteLine($"Access Level: {accessLevel}");

Logging Example

using Feenics.Keep.WebApi.Wrapper;
using Microsoft.Extensions.Logging;

public class AccessControlService
{
    private readonly Client _client;
    private readonly ILogger<AccessControlService> _logger;
    
    public AccessControlService(Client client, ILogger<AccessControlService> logger)
    {
        _client = client;
        _logger = logger;
    }
    
    public async Task ProcessCardholderAsync(string cardholderId)
    {
        _logger.LogDebug("Using client: {Client}", _client);
        
        var cardholder = await _client.GetByKeyAsync<CardholderInfo>(cardholderId);
        _logger.LogInformation("Processing cardholder: {Cardholder}", cardholder);
        
        // Process cardholder...
    }
}

Debugging Example

using Feenics.Keep.WebApi.Wrapper;

public async Task DiagnoseAsync(Client client)
{
    Console.WriteLine("=== Client Diagnostics ===");
    Console.WriteLine($"Client: {client}");
    Console.WriteLine($"Type: {client.GetType().FullName}");
    Console.WriteLine($"Hash Code: {client.GetHashCode()}");
    
    // List some objects
    var instances = await client.GetInstancesAsync();
    Console.WriteLine("\n=== Instances ===");
    foreach (var instance in instances.Take(5))
    {
        Console.WriteLine($"  {instance}");
    }
}

Collection Display

using Feenics.Keep.WebApi.Wrapper;

var client = new Client("https://keep.feenics.com");
await client.OpenAsync("username", "password", "my-app");

// Search for cardholders
var cardholders = await client.SearchAsync<CardholderInfo>(
    instanceId,
    "$filter=Status eq 'Active'&$top=10"
);

// Display all using ToString
Console.WriteLine("Active Cardholders:");
foreach (var ch in cardholders)
{
    Console.WriteLine($"  - {ch}");
}

Important Notes

💡 Never Null: ToString should never return null (returns empty string if no meaningful representation)

💡 Override: The Client class overrides ToString to provide meaningful output

💡 Implicit Call: ToString is called automatically in string interpolation and concatenation

Best Practices

  1. Use for Debugging: Great for quick inspection during development
  2. Structured Logging: Use ToString in log messages for object context
  3. Don’t Parse: Don’t rely on ToString format for data extraction—use properties instead
  • Equals - Compare objects for equality
  • GetHashCode - Get the hash code for the object
  • GetType - Get the runtime type of the object

Update Acre Intrusion Panel Enc IVAsync

Example in C#

// Returns: nothing
await client.UpdateAcreIntrusionPanelEncIVAsync(AcreIntrusionPanelInfo acreIntrusionPanel, Byte EncIv);

Overview of UpdateAcreIntrusionPanelEncIVAsync goes here.

Update Acre Intrusion Panel Enc Key Async

Example in C#

// Returns: nothing
await client.UpdateAcreIntrusionPanelEncKeyAsync(AcreIntrusionPanelInfo acreIntrusionPanel, Byte EncKeyBin);

Overview of UpdateAcreIntrusionPanelEncKeyAsync goes here.

Update Device Status Properties Async

Example in C#

// Returns: BulkItemResult
var bulkItemResult = await client.UpdateDeviceStatusPropertiesAsync(FolderInfo folder, String deviceKey, Boolean propStatusValues, Int64 logId, Boolean suppressUpdateEvent);

Overview of UpdateDeviceStatusPropertiesAsync goes here.

Update Device Status Property Async

Example in C#

// Returns: BulkItemResult
var bulkItemResult = await client.UpdateDeviceStatusPropertyAsync(FolderInfo folder, String deviceKey, String prop, Boolean statusValue, Int64 logId, Boolean suppressUpdateEvent);

Overview of UpdateDeviceStatusPropertyAsync goes here.

Updated Led Configurations Async

Example in C#

// Returns: nothing
await client.UpdatedLedConfigurationsAsync(ControllerInfo controller, LedConfigurationInfo ledConfiguration);

Overview of UpdatedLedConfigurationsAsync goes here.

Update Marketplace Package Tags

Example in C#

// Returns: nothing
await client.UpdateMarketplacePackageTags(MarketplacePackageInfo item, String tags);

Overview of UpdateMarketplacePackageTags goes here.

Update Marketplace Package Version Tags

Example in C#

// Returns: nothing
await client.UpdateMarketplacePackageVersionTags(MarketplacePackageVersionInfo item, String tags);

Overview of UpdateMarketplacePackageVersionTags goes here.

Update Traka Ifob Positions Async

Example in C#

// Returns: Boolean
var item = await client.UpdateTrakaIfobPositionsAsync(TrakaIfobInfo ifob, Int32 currPosition);

Overview of UpdateTrakaIfobPositionsAsync goes here.

Update Traka Item Async

Example in C#

// Returns: nothing
await client.UpdateTrakaItemAsync(TrakaItemInfo item);

Overview of UpdateTrakaItemAsync goes here.

Wait In Script Queue

Example in C#

// Returns: String
var item = await client.WaitInScriptQueue(FolderInfo folder, String lockName, Boolean exitIfQueued, Int32 retryIntervalInMilliseconds, Int32 maxDelayInMilliseconds, Int32 persistenceInMilliseconds);

Overview of WaitInScriptQueue goes here.