Quick Start

Welcome to acre Access Control™ API

Use this Quick Start guide to step through the process of provisioning a Standard instance and performing common access control operations. This guide provides both C# and cURL examples so you can follow along in your preferred development environment.

What You’ll Build: A basic access control system with people, credentials, readers, and access levels

What You’ll Learn

The guide will walk you through the following tasks:

  • Setup for Development - Install required tools and packages
  • Verify Connectivity - Confirm that your workstation can reach the API server
  • Authentication - Login to your instance with administrator credentials
  • Create an Access Level - Define access permissions
  • Create a Schedule - Set time-based access rules for weekday 9am-5pm access
  • Create a Badge Type - Configure employee credential defaults
  • Add People - Create cardholders individually and in batches
  • Assign Cards - Issue credentials to people
  • Add Hardware - Configure a door with a two-reader panel
  • Link Components - Connect readers to access levels
  • Test & Verify - Simulate card reads and query event history
  • Modify Data - Update existing person records

Prerequisites

Before you begin, ensure you have the following:

Required Knowledge

  • Basic understanding of REST APIs and HTTP methods (GET, POST, PUT, DELETE)
  • Familiarity with JSON data format
  • Experience with either C# (.NET) or command-line tools (cURL)
  • Basic understanding of access control concepts (users, permissions, credentials)

Required Resources

Developer Account: You should have received Credentials containing:

📧 Don’t have an account or credentials? Contact support@acresecurity.com or get in touch with your RSM

Development Environment (Choose One Path)

  • Visual Studio 2019 or later OR Visual Studio Code with C# extension
  • .NET 8.0 SDK or later (Download here)
  • NuGet Package Manager (included with Visual Studio)

Option B: Command-Line Development (cURL Examples)

  • cURL installed and accessible from command line (Download here)
  • jq for JSON formatting - optional but recommended (Download here)
  • Text editor or API testing tool (Postman, Insomnia, etc.)

Network Requirements



Setup for Development

Let’s configure your development environment to use the acre Access Control API. The setup process differs depending on whether you’re using C# (.NET) or cURL.

Step 1: Configure NuGet Package Sources (C# Only)

If you’re following the C# examples, you’ll need to add the acre Security NuGet package source.

Using Visual Studio

  1. Open Visual Studio
  2. Navigate to Tools → NuGet Package Manager → Package Manager Settings
  3. Select Package Sources from the left menu
  4. Click the + button to add a new source
  5. Configure the acre Security source:
    • Name: acre Security
    • Source: https://nuget-secure.feenics.com/nuget
  6. Click Update, then OK

Using .NET CLI

dotnet nuget add source https://nuget-secure.feenics.com/nuget --name "acre Security"

Using NuGet.config File

Create or edit NuGet.config in your project root:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="acre Security" value="https://nuget-secure.feenics.com/nuget" />
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
  </packageSources>
</configuration>

Step 2: Create Your Project (C# Only)

Using Visual Studio

  1. Select File → New → Project
  2. Choose Console App (.NET 8.0 or later)
  3. Name it (e.g., “AcreApiQuickStart”)
  4. Click Create

Using .NET CLI

mkdir AcreApiQuickStart
cd AcreApiQuickStart
dotnet new console

Step 3: Install Required Packages

The acre Access Control API requires several NuGet packages. The wrapper library will automatically install most dependencies.

Core Packages (Required for C#)

Install these packages using your preferred method:

Using Visual Studio:

  1. Right-click on your project
  2. Select Manage NuGet Packages
  3. Search for and install each package below

Using .NET CLI:

# Install the acre API wrapper and model
dotnet add package Feenics.Keep.WebApi.Model.Standard
dotnet add package Feenics.Keep.WebApi.Wrapper.Standard

Using Package Manager Console:

Install-Package Feenics.Keep.WebApi.Model.Standard
Install-Package Feenics.Keep.WebApi.Wrapper.Standard

Package Details

Core API Packages:

  • Feenics.Keep.WebApi.Model.Standard - Data models and entities
  • Feenics.Keep.WebApi.Wrapper.Standard - High-level API wrapper

Dependencies (automatically installed):

  • MongoDB.Bson - Binary JSON serialization
  • Flurl - Fluent URL builder
  • Flurl.Http - HTTP client library
  • Newtonsoft.Json - JSON serialization
  • Newtonsoft.Json.Bson - BSON support
  • Nito.AsyncEx - Async/await helpers

Optional Packages (install only if needed):

  • CsvHelper - For batch CSV import operations
  • MQTTnet - For real-time event subscriptions via MQTT
  • MQTTnet.Extensions.ManagedClient - Managed MQTT client

Step 4: Verify Installation (C# Only)

Create a simple test to verify packages are installed correctly:

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

class Program
{
    static void Main(string[] args)
    {
        var client = new Client("https://api.us.acresecurity.cloud");
        Console.WriteLine("✓ Packages installed successfully!");
        Console.WriteLine($"  Client initialized with base URL: {client.BaseUrl}");
    }
}

Run the project to confirm:

dotnet run

Expected output:

✓ Packages installed successfully!
  Client initialized with base URL: https://api.us.acresecurity.cloud

Troubleshooting Setup

Issue Possible Cause Solution
“Unable to load package source” Network access blocked Check firewall/proxy settings for nuget-secure.feenics.com
“Package not found” Credentials not configured Verify developer account is active, contact support
“Version conflict” errors Incompatible .NET version Ensure you’re using .NET 8.0 or later
“Unable to resolve dependency” Missing nuget.org source Add nuget.org as package source

Verify Server Connectivity

Before authenticating, let’s verify your workstation can reach the acre Access Control API servers. The /api/sysinfo endpoint is a public (unauthenticated) endpoint that provides system information.

Understanding the SysInfo Endpoint

Endpoint: GET https://api.us.acresecurity.cloud/api/sysinfo

Authentication: None required (public endpoint)

Purpose:

  • Verify network connectivity to the API
  • Check API version currently deployed
  • Confirm load balancing is working
  • Validate your clock synchronization with server time

Response Fields:

  • ServerTime - Current UTC time on the server (useful for clock sync verification)
  • Version - API version currently deployed
  • ServerId - Unique identifier of the specific server that handled your request
  • $type - Full type name for deserialization

Example in C#

using Feenics.Keep.WebApi.Wrapper;
using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        // Initialize the client with base URL and user agent
        var client = new Client(
            "https://api.us.acresecurity.cloud", 
            userAgent: "QuickStartApp/1.0"
        );
        
        Console.WriteLine("Connecting to acre Access Control API...");
        
        // Get system information (no authentication required)
        var sysInfo = await client.GetSysInfo();
        
        Console.WriteLine("✓ Successfully connected to acre Access Control API");
        Console.WriteLine($"  Server Time (UTC): {sysInfo.ServerTime}");
        Console.WriteLine($"  API Version:       {sysInfo.Version}");
        Console.WriteLine($"  Server ID:         {sysInfo.ServerId}");
        
        // Verify clock synchronization
        var timeDiff = DateTime.UtcNow - sysInfo.ServerTime;
        Console.WriteLine($"  Clock Difference:  {timeDiff.TotalSeconds:F1} seconds");
        
        if (Math.Abs(timeDiff.TotalSeconds) > 300) // 5 minutes
        {
            Console.WriteLine("  ⚠️  WARNING: Local clock differs by more than 5 minutes!");
            Console.WriteLine("     This may cause authentication issues.");
        }
    }
}

Example in cURL

# Basic request
curl -s https://api.us.acresecurity.cloud/api/sysinfo

# With pretty-print formatting (requires jq)
curl -s https://api.us.acresecurity.cloud/api/sysinfo | jq .

# Alternative formatting with json_pp (usually pre-installed)
curl -s https://api.us.acresecurity.cloud/api/sysinfo | json_pp

Expected Response

{
  "$type": "Feenics.Keep.WebApi.Model.SysInfo, Feenics.Keep.WebApi.Model",
  "Version": "25.12.14.0",
  "ServerId": "01e16dae017e4062a7d401cfe771dfc8",
  "ServerTime": "2026-01-26T19:04:24.2101341Z",
  "EventPublisherUrl": "wss://events.us.acresecurity.cloud",
  "FitScriptEngineUrl": "fits.us.acresecurity.cloud",
  "LicenseServerUrl": "licenseserver.us.acresecurity.cloud",
  "UapBrokerUrl": "mqtt.us.acresecurity.cloud",
  "FargoConnectApiUrl": "fargoconnect.us.acresecurity.cloud",
  "AacClientUrl": null,
  "GalleryIsEnabled": true,
  "ReleaseNotes": [
    {
      "$type": "Feenics.Keep.WebApi.Model.ReleaseNote, Feenics.Keep.WebApi.Model",
      "Name": "API",
      "Url": "https://acre.my.site.com/knowledgearticles/s/article/acre-Access-Control-Release-Notes"
    },
    // Other links
  ]
}

Testing Load Balancing

The acre Access Control API runs on multiple servers behind a load balancer. Each request may be handled by a different server.

Run the cURL command multiple times and observe the ServerId field changing:

# Run 5 times and extract just the ServerId
for i in {1..5}; do
  echo "Request $i:"
  curl -s https://api.us.acresecurity.cloud/api/sysinfo | jq -r '.ServerId'
done

Expected behavior: You should see different ServerId values, confirming requests are distributed across multiple servers for high availability.

Constants for This Guide

Throughout this guide, we’ll use the following example constants. Replace these with your actual values from your Developer Welcome Letter:

Name Example Value Description
BaseAddress https://api.us.acresecurity.cloud The HTTPS endpoint of the acre Access Control service
InstanceName QuickStart Your instance name (case-sensitive) - find this in your welcome letter
Username admin Your administrator username
Password adminpass Your administrator password

💡 Tip: Store these values as constants or environment variables in your application rather than hardcoding them.


Authentication & Login

acre Access Control uses OAuth 2.0 with JWT (JSON Web Tokens) for authentication. Understanding token management is crucial for building robust integrations.

Understanding the Authentication Flow

┌─────────────┐                                    ┌──────────────┐
│  Your App   │                                    │   acre API   │
└──────┬──────┘                                    └──────┬───────┘
       │                                                  │
       │  1. POST /token (username + password)           │
       │─────────────────────────────────────────────────>│
       │                                                  │
       │  2. Returns: access_token + refresh_token       │
       │<─────────────────────────────────────────────────│
       │                                                  │
       │  3. Subsequent API calls with Bearer token      │
       │─────────────────────────────────────────────────>│
       │                                                  │
       │  4. Token expires after 24 hours                │
       │                                                  │
       │  5. POST /token (refresh_token)                 │
       │─────────────────────────────────────────────────>│
       │                                                  │
       │  6. Returns: new access_token + refresh_token   │
       │<─────────────────────────────────────────────────│

Key Authentication Concepts

  • Access Token - Short-lived JWT token (valid for 24 hours) used in API requests
  • Refresh Token - Long-lived token used to obtain new access tokens without re-entering credentials
  • Bearer Authentication - Access token is sent in the Authorization: Bearer <token> header
  • Instance Scope - Authentication is scoped to a specific instance
  • Automatic Refresh - The C# wrapper automatically refreshes tokens when needed

Initial Login

Example in C#

using Feenics.Keep.WebApi.Wrapper;
using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        // Configuration - replace with your actual values
        const string baseUrl = "https://api.us.acresecurity.cloud";
        const string instanceName = "QuickStart";  // From your welcome letter
        const string username = "admin";            // Your username
        const string password = "your-password";    // Your password
        
        // Create client with a descriptive user agent
        var client = new Client(baseUrl, userAgent: "QuickStartApp/1.0");
        
        Console.WriteLine($"Logging in to instance '{instanceName}'...");
        
        // Attempt login - returns tuple with success status and error details
        var (isLoggedIn, loginError, loginErrorMsg) = await client.LoginAsync(
            instanceName, 
            username, 
            password
        );
        
        if (!isLoggedIn)
        {
            Console.WriteLine("❌ Login failed!");
            Console.WriteLine($"   Error Code: {loginError}");
            Console.WriteLine($"   Message: {loginErrorMsg}");
            
            // Provide helpful troubleshooting tips
            if (loginError?.Contains("invalid_grant") == true)
            {
                Console.WriteLine("\n💡 Tip: Check your username and password");
            }
            else if (loginError?.Contains("instance") == true)
            {
                Console.WriteLine("\n💡 Tip: Verify your instance name (case-sensitive)");
            }
            
            return; // Exit if login fails
        }
        
        Console.WriteLine("✓ Login successful!");
        Console.WriteLine($"  Instance: {instanceName}");
        Console.WriteLine($"  User: {username}");
        
        // The access token is now stored in the client object
        // and will be automatically included in all subsequent API calls
        
        // Get current user information to verify authentication
        var currentUser = await client.GetCurrentUserAsync();
        Console.WriteLine($"  User Key: {currentUser.Key}");
        Console.WriteLine($"  Full Name: {currentUser.CommonName}");
        
        // Get current instance information
        var currentInstance = await client.GetCurrentInstanceAsync();
        Console.WriteLine($"  Instance Key: {currentInstance.Key}");
    }
}

Example in cURL

When using cURL, you need to manually manage tokens. Here’s how to login and store the token:

# Store your credentials as variables for security
INSTANCE="QuickStart"
USERNAME="admin"
PASSWORD="your-password"

# Request access token
curl -X POST https://api.us.acresecurity.cloud/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d "grant_type=password" \
  -d "client_id=consoleApp" \
  -d "client_secret=consoleSecret" \
  -d "username=${USERNAME}" \
  -d "password=${PASSWORD}" \
  -d "instance=${INSTANCE}" \
  -d "sendonetimepassword=false" \
  | jq .

The above commands return JSON structured data like this:

{
  "userName": "QuickStart\\admin",
  "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjhkY2U5YTA2YTg1NzEzNjMzYmI4NGMyN2EwZWQyNTY5IiwidHlwIjoiSl...",
  "as:client_id": "consoleApp",
  "token_type": "bearer",
  "refresh_token": "18764039r94d936a710d8849",
  "expires_in": 86399,
  ".issued": "Wed, 21 Jan 2026 21:08:09 GMT",
  ".expires": "Thu, 22 Jan 2026 21:08:08 GMT",
  "instance": "54f2ca32bad37c2788b2827f"
}

Store the token for subsequent requests:

# Extract and save the access token to a variable
ACCESS_TOKEN=$(curl -s -X POST https://api.us.acresecurity.cloud/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d "grant_type=password&client_id=consoleApp&client_secret=consoleSecret&username=${USERNAME}&password=${PASSWORD}&instance=${INSTANCE}&sendonetimepassword=false" \
  | jq -r '.access_token')

echo "Token obtained successfully"
echo "Token preview: ${ACCESS_TOKEN:0:50}..."

# Test the token with an authenticated request
curl -X GET https://api.us.acresecurity.cloud/api/ \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  | jq .

Refreshing Access Tokens

Access tokens expire after 24 hours. Instead of logging in again, use the refresh token to obtain a new access token.

Example in C#

var refreshSuccess = await client.RefreshAsync();

if (refreshSuccess)
{
    Console.WriteLine("✓ Token refreshed successfully");
}
else
{
    Console.WriteLine("❌ Token refresh failed - re-authentication required");
    // Re-authenticate with username and password
    await client.LoginAsync(instanceName, username, password);
}

Example in cURL

# Use the refresh token from the initial login response
REFRESH_TOKEN="abc123ABC123"

# Request a new access token
NEW_ACCESS_TOKEN=$(curl -s -X POST https://api.us.acresecurity.cloud/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d "grant_type=refresh_token" \
  -d "client_id=consoleApp" \
  -d "client_secret=consoleSecret" \
  -d "refresh_token=${REFRESH_TOKEN}" \
  | jq -r '.access_token')

echo "New token obtained: ${NEW_ACCESS_TOKEN:0:50}..."

Understanding HTTP and Tokens

It’s important to remember that HTTP is a stateless, connection-less protocol. Unlike persistent database connections (ODBC, JDBC), there is no maintained session with the API server.

How Authentication Works:

  1. You POST credentials to /token endpoint
  2. Server validates and returns a JWT access token
  3. You include this token in the Authorization header of all subsequent requests
  4. Server validates the token on each request
  5. When the token expires (24 hours), use the refresh token to get a new one

With the C# Wrapper:

  • ✅ All token management is automatic
  • ✅ Provided Refresh method logic handles renewing tokens

With cURL:

  • ⚠️ You must manually manage tokens on requests
  • ⚠️ Track expiration and refresh before 24 hours
  • ⚠️ Include Authorization: Bearer <token> in every request

Troubleshooting Authentication

The acre Access Control API returns specific error codes to help diagnose authentication issues. These errors are returned in the response body as JSON with error and error_description fields.

Common Authentication Errors

Error Code HTTP Status Cause Solution
invalid_grant 400 Incorrect username or password, or SSO user attempting standard login Verify credentials in your welcome letter. SSO users must use SSO authentication
incorrect_password 400 Password is incorrect (Low security instances only) Re-enter password. Check for caps lock
incorrect_tfacode 400 Two-factor authentication code is incorrect Re-enter the 6-digit code from your authenticator app
user_notfound 400 Username does not exist (Low security instances only) Verify username spelling and instance name
user_disabled 400 User account has been disabled (Low/Medium security) Contact your administrator to re-enable account
user_lockedout 400 Account is locked after too many failed attempts (Low/Medium security) Wait 15 minutes or contact support to unlock
password_expired 400 User’s password has expired Change password using newpassword parameter or contact admin
new_password_required 400 User must change password on first login Include newpassword parameter in login request
one_time_password_required 400 User has two-factor authentication enabled Include onetimepassword parameter with 6-digit code
password_doesnot_meet_complexity_rule 400 New password doesn’t meet complexity requirements Use mix of uppercase, lowercase, numbers, special characters
password_doesnot_meet_minimum_length_rule 400 New password is too short Use at least 8 characters (or instance minimum)
instance_not_found 400 Instance name is incorrect or doesn’t exist Verify instance name (case-sensitive)
instance_disabled 400 Instance has been disabled Contact acre Security support
instance_missing_license 400 Instance does not have a valid license Contact your administrator or acre Security support
instance_license_tampered 400 Instance license signature is invalid Contact acre Security support immediately
instance_license_expired 400 Trial license has expired Contact sales to upgrade to full license
invalid_client 400 Wrong client_id or client_secret Use consoleApp / consoleSecret as defaults
unsupported_grant_type 400 Wrong grant_type parameter Use password for login, refresh_token for refresh
unauthorized 401 Missing or invalid token in API request Check Authorization: Bearer <token> header format
RefreshTokenTicketNotValid 400 Refresh token is invalid or expired Re-authenticate with username and password

Security Level Behavior

The API adapts error messages based on your instance’s security level setting:

  • High Security (Default): Returns generic invalid_grant for most authentication failures to prevent user enumeration
  • Medium Security: Returns specific errors like user_disabled and user_lockedout
  • Low Security: Returns detailed errors including incorrect_password, user_notfound, and incorrect_tfacode

Security Note: High security instances intentionally provide less detailed error information to prevent attackers from determining which usernames exist in the system.

Example Error Response

{
  "error": "invalid_grant",
  "error_description": "The email or password is incorrect"
}

Two-Factor Authentication (2FA)

If two-factor authentication is enabled for a user:

  1. First attempt without code:
curl -X POST https://api.us.acresecurity.cloud/token \
  -d "instance=QuickStart&username=admin&password=mypassword"

Response:

{
  "error": "one_time_password_required",
  "error_description": "User has two factor authentication turned on. Please authenticate with 'instance', 'username', 'password' and 'onetimepassword' values"
}
  1. Send one-time password via SMS (optional):
curl -X POST https://api.us.acresecurity.cloud/token \
  -d "instance=QuickStart&username=admin&password=mypassword&sendonetimepassword=true"
  1. Login with 2FA code:
curl -X POST https://api.us.acresecurity.cloud/token \
  -d "instance=QuickStart&username=admin&password=mypassword&onetimepassword=123456"

Troubleshooting Tips

Symptom Likely Cause Action
Error on first login Password change required Include newpassword parameter
Error after password change New password rejected Check complexity and length requirements
Intermittent token errors Token expiration Implement token refresh logic
“SSO user must login using SSO” Account configured for single sign-on Use SSO authentication endpoint instead
Generic “invalid_grant” High security instance Check all credentials carefully; detailed errors are hidden
Connection timeout Network/firewall issue Verify outbound HTTPS access to *.acresecurity.cloud

Next Steps: Building Your Access Control System

Now that you’re authenticated, you’re ready to configure your access control system. The following topics walk you through creating a complete working system:

Core Configuration

  1. Acquire Working Instance - Get your instance reference for API calls
  2. Create an Access Level - Define who can access what
  3. Add a Schedule - Set time-based access rules (e.g., weekdays 9am-5pm)
  4. Create a Badge Type - Define credential types and defaults

People & Credentials

  1. Adding a New Person - Create individual cardholders
  2. Assign Cards - Issue credentials to people
  3. Batch Add People - Import multiple people from CSV files

Hardware Configuration

  1. Add a Controller - Add door controllers to your system
  2. Add Reader - Configure card readers
  3. Add Peripherals - Add inputs/outputs for door sensors
  4. Link Reader and Access Level - Enable access at specific doors

Testing & Monitoring

  1. Simulate a Card Read - Test your configuration
  2. Query Event History - View access events and audit logs
  3. Subscribe to Events - Real-time event notifications via MQTT

Advanced Topics

  1. Modify Person - Update existing person records
  2. Reset/Change Password - Manage user passwords
  3. MongoDB Aggregates - Advanced data queries
  4. Origo and Keep - HID Origo mobile credentials integration

Complete Example Workflow

Here’s a simplified example showing the typical flow from authentication to granting access:

// 1. Login
var client = new Client("https://api.us.acresecurity.cloud", userAgent: "MyApp/1.0");
await client.LoginAsync("QuickStart", "admin", "password");

// 2. Get current instance
var instance = await client.GetCurrentInstanceAsync();

// 3. Create an access level
var accessLevel = await client.AddAccessLevelAsync(instance, new AccessLevelInfo 
{ 
    CommonName = "Employee Access" 
});

// 4. Create a schedule (weekdays 9-5)
var schedule = await client.AddScheduleAsync(instance, new ScheduleInfo 
{ 
    CommonName = "Business Hours",
    // ... schedule details ...
});

// 5. Add a person
var person = await client.AddPersonAsync(instance, new PersonInfo 
{
    GivenName = "John",
    Surname = "Doe",
    CommonName = "JohnDoe"
});

// 6. Link person to access level
await client.AssignConnectedObjectAsync(person, accessLevel, "AccessLevel", false);

// 7. Assign a card
person.CardAssignments = new[] 
{
    new CardAssignmentInfo 
    {
        EncodedCardNumber = 123456,
        DisplayCardNumber = "123456",
        ActiveOn = DateTime.UtcNow,
        ExpiresOn = DateTime.UtcNow.AddYears(1)
    }
};
await client.UpdatePersonAsync(person);

Console.WriteLine("✓ Person created and granted access!");

Additional Resources

Documentation

Support & Community


Summary

Congratulations! You’ve completed the Quick Start guide. You should now be able to:

✅ Set up your development environment with required packages
✅ Verify connectivity to the acre Access Control API
✅ Authenticate and manage tokens securely
✅ Understand the basic authentication flow
✅ Know where to find detailed documentation for next steps

What’s Next?

Start building your access control system by working through the Core Configuration guides listed above. Each guide provides detailed examples in both C# and cURL.

Happy coding! 🚀