Assigning Cards to a Person

Card assignments represent physical credentials (access cards, key fobs, mobile credentials) issued to people. This guide shows you how to assign, manage, and troubleshoot card assignments.


Overview

What is a Card Assignment?

A card assignment links a physical or virtual credential to a person in the system. The card number is what readers recognize when a cardholder presents their credential.

Property Description Required
EncodedCardNumber The binary number stored on the card ✅ Yes
DisplayCardNumber Human-readable card number (usually same as encoded) ✅ Yes
ActiveOn Date when card becomes valid ✅ Yes
ExpiresOn Date when card expires ✅ Yes
PinCode PIN code for keypad readers (enables PIN-based entry modes) ❌ No
AntiPassbackExempt Bypass anti-passback rules ❌ No
ExtendedAccess Allow extended door hold time ❌ No
IsDisabled Temporarily disable the card ❌ No

Important Notes

⚠️ Cards are not Deleted: Once a card is entered into the system, it is not hard deleted by default—only disabled or reassigned. This maintains audit trail integrity. Optionally, you may enable the CleanExpiredCards option in InstanceSettings to hard delete after 30 days of a card’s expiration. 💡 Card Numbers Must Be Unique: Each active EncodedCardNumber can only be assigned to one person at a time.


Assign a Card to a Person

C# Example

// Assign a card with known card number
var cardAssignment = await client.AddCardAssignmentAsync(person, new CardAssignmentInfo
{
    DisplayCardNumber = "12345678",
    EncodedCardNumber = 12345678,
    ActiveOn = DateTime.UtcNow,
    ExpiresOn = DateTime.UtcNow.AddYears(1),
    AntiPassbackExempt = false,
    ExtendedAccess = false
});

Console.WriteLine($"Card {cardAssignment.DisplayCardNumber} assigned to {person.CommonName}");
Console.WriteLine($"Valid: {cardAssignment.ActiveOn:d} to {cardAssignment.ExpiresOn:d}");

cURL Example

curl -X POST \
  https://api.us.acresecurity.cloud/api/f/INSTANCE_KEY/people/PERSON_KEY/cards \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "$type": "Feenics.Keep.WebApi.Model.CardAssignmentInfo, Feenics.Keep.WebApi.Model",
    "EncodedCardNumber": 12345678,
    "DisplayCardNumber": "12345678",
    "ActiveOn": "2024-01-01T00:00:00Z",
    "ExpiresOn": "2025-01-01T00:00:00Z",
    "AntiPassbackExempt": false,
    "ExtendedAccess": false,
    "IsDisabled": false
  }'

Card with PIN Code

For readers with keypads, you can assign a PIN code to enable PIN-based authentication. Readers may be configured to accept:

  • PIN Only: User enters only their PIN (no card required)
  • Card Only: User presents only their card (no PIN required)
  • Card AND PIN: User must present card and enter PIN (two-factor authentication)
  • Card OR PIN: User can present either card or PIN

C# Example

var cardAssignment = await client.AddCardAssignmentAsync(person, new CardAssignmentInfo
{
    DisplayCardNumber = "12345678",
    EncodedCardNumber = 12345678,
    PinCode = "1234", // 4-digit PIN for keypad readers
    ActiveOn = DateTime.UtcNow,
    ExpiresOn = DateTime.UtcNow.AddYears(1)
});

Console.WriteLine($"Card with PIN assigned. PIN: {cardAssignment.PinCode}");

⚠️ PIN Uniqueness: PIN codes must be unique within an instance unless overwritten via InstanceSettings. Use GetRandomPinAsync to help with uniqueness. 💡 Reader Configuration: The reader’s configuration determines which entry mode(s) are allowed (PIN only, card only, card+PIN, or card/PIN).


Assign Card During Person Creation

You can include card assignments when creating a new person.

C# Example

var person = await client.AddPersonAsync(currentInstance, new PersonInfo
{
    CommonName = "Jane Smith",
    GivenName = "Jane",
    Surname = "Smith",
    CardAssignments = new CardAssignmentInfo[]
    {
        new CardAssignmentInfo
        {
            DisplayCardNumber = "87654321",
            EncodedCardNumber = 87654321,
            ActiveOn = DateTime.UtcNow,
            ExpiresOn = DateTime.UtcNow.AddYears(2)
        }
    }
});

Console.WriteLine($"Created {person.CommonName} with card {person.CardAssignments[0].DisplayCardNumber}");

Manage Existing Cards

Get All Cards for a Person

var person = (await client.SearchAsync(currentInstance, $"{{\\"_t\\":\\"Person\\",\\"_id\\":\\"{personKey}\\"}}"))
    .OfType<PersonInfo>().FirstOrDefault();

foreach (var card in person.CardAssignments)
{
    var status = card.IsDisabled ? "DISABLED" : 
                 (card.ExpiresOn < DateTime.UtcNow ? "EXPIRED" : "ACTIVE");
    
    Console.WriteLine($"Card: {card.DisplayCardNumber} - {status}");
    Console.WriteLine($"  Valid: {card.ActiveOn:d} to {card.ExpiresOn:d}");
}

Disable a Card

// Find the card assignment
var person = (await client.SearchAsync(currentInstance, $"{{\\"_t\\":\\"Person\\",\\"_id\\":\\"{personKey}\\"}}"))
    .OfType<PersonInfo>().FirstOrDefault();
var card = person.CardAssignments.FirstOrDefault(c => c.DisplayCardNumber == "12345678");

if (card != null)
{
    card.IsDisabled = true;
    await client.UpdateCardAssignmentAsync(person, card);
    Console.WriteLine($"Card {card.DisplayCardNumber} has been disabled");
}

Extend Card Expiration

var card = person.CardAssignments.First();
card.ExpiresOn = DateTime.UtcNow.AddYears(1); // Extend by 1 year

await client.UpdateCardAssignmentAsync(person, card);
Console.WriteLine($"Card expiration extended to {card.ExpiresOn:d}");

Bulk Card Operations

For updating many cards at once, use the bulk operations for better performance.

Extend Expiration in Bulk

// Extend all cards expiring in 30 days by 1 year
var result = await client.ExtendCardExpiry(
    currentInstance,
    expiresBefore: DateTime.UtcNow.AddDays(30),
    expiresAfter: DateTime.UtcNow,
    newExpiresOn: DateTime.UtcNow.AddYears(1),
    trialRun: false
);

Console.WriteLine($"Extended {result.CardsUpdated} cards");

See Bulk Card Operations for complete documentation.


Special Card Properties

Extended Access

Grant extra time for people who need longer door hold times (accessibility accommodation).

var card = new CardAssignmentInfo
{
    DisplayCardNumber = "11111111",
    EncodedCardNumber = 11111111,
    ExtendedAccess = true, // Door stays open longer
    ActiveOn = DateTime.UtcNow,
    ExpiresOn = DateTime.UtcNow.AddYears(1)
};

Anti-Passback Exempt

Bypass anti-passback rules for managers or maintenance staff.

var card = new CardAssignmentInfo
{
    DisplayCardNumber = "22222222",
    EncodedCardNumber = 22222222,
    AntiPassbackExempt = true, // Can badge in multiple times
    ActiveOn = DateTime.UtcNow,
    ExpiresOn = DateTime.UtcNow.AddYears(1)
};

Use Count Limits

Restrict the number of times a card can be used (visitor passes).

var card = new CardAssignmentInfo
{
    DisplayCardNumber = "VISITOR001",
    EncodedCardNumber = 99999001,
    OriginalUseCount = 10, // Maximum 10 uses
    CurrentUseCount = 0,
    ActiveOn = DateTime.UtcNow,
    ExpiresOn = DateTime.UtcNow.AddDays(1)
};

Best Practices

Practice Recommendation
Validate Card Numbers Ensure encoded number matches card format
Use Display Numbers Make display number human-readable if required
Track Card History Use events to audit card usage
Disable, Don’t Delete Disable lost cards immediately, can re-active if found later

Troubleshooting

Issue Cause Solution
CardIsAlreadyAssigned Card number in use by another person Disable old assignment first
DuplicatePinCode PIN already exists Use GetRandomPinAsync for unique PIN
Card not working Card disabled or expired Check IsDisabled and ExpiresOn

See Also