User Documentation

PACS integration

ICAP can coordinate access data with connected Physical Access Control Systems (PACSs) through AIS. ICAP is the persistent system of record for the tenant's intended data: it can be the master for the data it owns across interconnected applications and PACSs. AIS performs the integration work; it can give applications a unified path to many PACSs, but it does not own or govern the canonical business data. Each PACS ultimately enforces its own capabilities.

Connect your ICAP tenant to AIS

PACS integration requires a two-way connection between the ICAP tenant and its HIS (AIS) tenant. ICAP calls the AIS tenant API to provision PACS data, and AIS calls the ICAP tenant's /pacsCallback endpoint to report results. Each direction uses its own technical user (client ID) registered in HID Authentication Service. Complete this setup once for each ICAP and AIS tenant pair, before you enable PACS integration.

Obtain these values from your HIS administrator:

  • ICAP API base URL and ICAP tenant ID

  • AIS API base URL and AIS tenant ID

  • ICAP technical-user ID: the user ICAP uses to call AIS

  • AIS technical-user ID: the user AIS uses to call ICAP

Steps 1 and 2 are performed in the AIS tenant by an AIS tenant administrator. Steps 3 and 4 are performed in the ICAP tenant by an ICAP tenant administrator.

  1. Allow ICAP to call AIS. In the AIS tenant, assign a role to the ICAP technical user with POST /ais/v1/tenant/{tenantId}/role/{roleId}/assignment (RoleAssign). Prefer a dedicated ICAP role that contains only the permissions ICAP needs. The predefined TenantAdministrator role also works, but it grants more access than ICAP requires.

  2. Register the ICAP callback URL in AIS. Add the ICAP tenant's callback endpoint to the AIS tenant callbackUris with PATCH /ais/v1/tenant/{tenantId} (TenantUpdate). The URL has the form https://<your-icap-host>/icap/v1/tenant/<icapTenantId>/pacsCallback.

  3. Allow AIS to call ICAP. In the ICAP tenant, assign the predefined PacsCallbackInvoker role to the AIS technical user with POST /role/{roleId}/assignment. The role grants PacsCallbackInvoke, the permission required by POST /pacsCallback. If the tenant was registered with pacsCallbackInvokerId, verify the existing assignment instead.

  4. Enable PACS integration. Set pacsIntegrationEnabled to true on the ICAP tenant with PATCH /icap/v1/tenant/{tenantId} (TenantUpdate). When it is enabled, ICAP verifies that AIS can retrieve the same tenant.

For step 2, read the AIS tenant first and keep its current callbackUris. The replace operation sets the whole list.

Bash
AIS_BASE_URL='https://<your-ais-host>/ais/v1/tenant/<aisTenantId>'
CALLBACK_URI='https://<your-icap-host>/icap/v1/tenant/<icapTenantId>/pacsCallback'

curl --fail-with-body --silent --show-error \
  --header "Authorization: Bearer $AIS_TOKEN" \
  "$AIS_BASE_URL"

curl --fail-with-body --silent --show-error \
  --request PATCH "$AIS_BASE_URL" \
  --header "Authorization: Bearer $AIS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data "[
    { \"op\": \"replace\", \"path\": \"/callbackUris\", \"value\": [\"<existing-callback-uri>\", \"$CALLBACK_URI\"] }
  ]"

Include every existing callbackUris entry that must stay registered. Omitting an entry stops AIS callbacks to that destination.

For step 3, find the PacsCallbackInvoker role ID with GET /role, then assign it to the AIS technical user:

Bash
ROLE_ID='<PacsCallbackInvoker role id>'

curl --fail-with-body --silent --show-error \
  --request POST "$BASE_URL/role/$ROLE_ID/assignment" \
  --header "Authorization: Bearer $TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{ "userId": "<ais-technical-user-id>" }'

For step 4, read the tenant to get its current version, then send that value in If-Match:

Bash
curl --fail-with-body --silent --show-error \
  --request PATCH "$BASE_URL" \
  --header "Authorization: Bearer $TOKEN" \
  --header 'Content-Type: application/json' \
  --header 'If-Match: <tenant-version>' \
  --data '[ { "op": "replace", "path": "/pacsIntegrationEnabled", "value": true } ]'

Symptom

What to check

Enabling pacsIntegrationEnabled is rejected

The ICAP technical user's role in the AIS tenant (step 1), the callback URL in callbackUris (step 2), the AIS technical user's PacsCallbackInvoker assignment (step 3), and that both tenant IDs belong to the same tenant pair.

PACS transactions stay pending or running

That the callback URL in callbackUris exactly matches the ICAP host and tenant ID (step 2), and that the AIS technical user holds PacsCallbackInvoker (step 3).

Treat technical-user credentials and tokens as secrets. Do not put them in callback URLs, source code, or logs.

Before you configure a PACS

Confirm that PACS integration is enabled for the tenant and that the PACS is supported and connected through your AIS integration of your tenant.

Registering an ICAP PACS record does not itself establish external connectivity.

Register a PACS through /pacs with its tenant-scoped pacsId, name, and optional configuration and mappings. Then use ICAP to list its discovered access units and card formats. These discovery results are the input for access-unit and card-type mappings.

Use this operational order for a new integration:

  1. Confirm that the ICAP tenant is connected to AIS, that PACS integration is enabled for the tenant, and that the user’s HIS tenant has connected the supported PACS.

  2. Register the ICAP PACS record with POST /pacs (PacsRegister). Use HIS (AIS) pacsId for the requets. A successful registration does not prove the external connection is usable.

  3. Read GET /pacs/{pacsId}/accessUnit and GET /pacs/{pacsId}/cardFormat (PacsCardFormatList) and retain the discovered identifiers.

  4. Map ICAP access units and card types only to those discovered identifiers. Test mappings in non-production before assigning physical credentials or production access.

  5. Select the identity and visitor propagation modes with the PACS administrator, then create a test identity or visitor assignment and monitor its transaction through completion.

Discover and map a PACS

The HIS tenant administrator must supply a PACS ID that is already connected through the HIS/AIS service. If it is not yet registered in ICAP, a caller with PacsRegister can register it with POST /pacs, supplying the required pacsId and name. Do not invent a PACS ID or register a production PACS merely to test this example.

List the available remote targets and formats. Both discovery calls require PacsCardFormatList permission in the current contract.

Bash
PACS_ID='<registered-pacs-id>'

curl --fail-with-body --silent --show-error \
  --header "Authorization: Bearer $TOKEN" \
  "$BASE_URL/pacs/$PACS_ID/accessUnit?limit=100"

curl --fail-with-body --silent --show-error \
  --header "Authorization: Bearer $TOKEN" \
  "$BASE_URL/pacs/$PACS_ID/cardFormat"

The access-unit response is paged; select an items[].id returned by this PACS. The card-format response contains the available formats and any format-specific constraints. For example:

JSON
{
  "items": [
    { "id": "<remoteAccessUnitId>", "name": "Level 3" }
  ],
  "limit": 100,
  "offset": 0,
  "total": 1
}

Create mapped business resources only with those returned values. This example creates an identity-eligible access unit and card type; replace the names and values with the selected discovery results.

Bash
REMOTE_ACCESS_UNIT_ID='<value from discovery>'
CARD_FORMAT='<value from discovery>'

curl --fail-with-body --silent --show-error \
  --request POST "$BASE_URL/accessUnit" \
  --header "Authorization: Bearer $TOKEN" \
  --header 'Content-Type: application/json' \
  --data "{
    \"name\": \"Level 3\",
    \"eligibleFor\": \"identity\",
    \"pacsMappings\": [
      { \"pacsId\": \"$PACS_ID\", \"accessUnitId\": \"$REMOTE_ACCESS_UNIT_ID\" }
    ]
  }"

curl --fail-with-body --silent --show-error \
  --request POST "$BASE_URL/cardType" \
  --header "Authorization: Bearer $TOKEN" \
  --header 'Content-Type: application/json' \
  --data "{
    \"name\": \"Employee PACS card\",
    \"eligibleFor\": \"identity\",
    \"pacsFormatMappings\": { \"$PACS_ID\": \"$CARD_FORMAT\" }
  }"

The create responses contain the ICAP resource IDs and version. Keep both values: later mapped-resource PATCH or removal needs the current version. A successful mapping only establishes ICAP's intended configuration; test an assignment and monitor its PACS transaction before relying on a door outcome.

Propagation modes

PACS configuration can set separate propagation modes for identities and visitors:

Mode

Intended behavior

off

Do not propagate this category.

mirror

Propagate eligible data without requiring a selected credential and access unit.

jit

Just In Time. Propagate when eligible data includes both a PACS-mapped credential and PACS-mapped access unit.

master

Use the PACS as the configured source for periodic import of that category.

Choose modes with the data owner and PACS administrator. jit is useful when provisioning should follow a complete access assignment; mirror can suit a PACS that needs person records before access is assigned. In master mode, the selected PACS—not ICAP—is the configured source for the imported category. Do not describe ICAP as the master for data governed by that import configuration.

Mapping and constraints

Map ICAP access units to discovered remote access units, and map card types to compatible PACS card formats. Optional attribute mappings copy selected identity, visitor, card-credential, or PIN-credential values between ICAP and AIS integration data.

Map identity and visitor attributes

Attribute mappings are configured on each PACS record in mappings. In each mapping block, the property name is a source JSONPath on the ICAP record and the value is the destination JSONPath in the AIS attributes for that PACS.

On the destination side, $.ext.<fieldName> addresses an extension field registered for that PACS in HIS, while $.self.<fieldName> addresses a native field registered for that PACS in HIS. On the ICAP source side, use $.extensionFields.<fieldName> for an ICAP extension field and $.<nativeFieldName> for an ICAP native attribute, such as $.firstName or $.lastName.

The following example sends both kinds of values: an identity's native first name and employee number, plus a visitor's native last name and sponsor:

JSON
{
  "mappings": {
    "identity": {
      "$.firstName": "$.self.firstName",
      "$.extensionFields.employeeNumber": "$.ext.employeeNumber"
    },
    "visitor": {
      "$.lastName": "$.self.lastName",
      "$.extensionFields.sponsor": "$.ext.sponsor"
    },
    "cardCredential": {},
    "pinCredential": {}
  }
}

In these JSONPaths, $ means the current object: the ICAP identity or visitor on the left, and the outgoing AIS attributes object on the right. extensionFields stores ICAP tenant-defined fields. ext is the AIS extension-attributes object used in this example, not a reserved ICAP field. Confirm destination objects and attributes with the PACS administrator.

To send values, employeeNumber must exist in the identity extensionFields and sponsor in the visitor extensionFields. Destination paths must match PACS-registered attributes. The identity block syncs identities; visitor syncs visitors with visit assignments. There is no visit block: visits provide context, not mapping sources.

Use valid JSONPaths that start with $.. ICAP validates syntax when saving the PACS configuration, but not source or destination existence or type compatibility. Mappings copy values as-is; they cannot format, convert, combine, or split them. Avoid duplicate destinations, and do not map ICAP-managed metadata such as IDs, versions, or audit timestamps.

Mappings supplement standard outbound person attributes; they do not select credentials or access units. Map only PACS-approved, supported attributes. If the PACS does not support the relevant extension fields, it can omit those mapped values.

A PACS can advertise limits such as unsupported credential types, photos, PINs, or field values. ICAP adapts outbound data to the configured and discovered capabilities, but an integration still requires testing in the intended PACS environment.

Monitor and recover downstream work

Changes that require PACS work can create PACS transactions. They are asynchronous: a successful ICAP API response confirms ICAP accepted the change, not that every downstream PACS has completed it.

Use GET /pacsTransaction to inspect transactions. Filter by PACS, entity, related entity, or operation as needed, and retain correlation data in your application so support teams can trace an outcome. Build workflow status around the transaction result rather than assuming immediate physical-access availability.

For a person or visitor change, start with GET /pacsTransaction?entityId=<identityId-or-visitorId>. Narrow further with pacsId, relatedEntityId, or one of the contract's operation values if necessary. Each returned transaction includes its PACS ID, entity IDs, status, result timestamp, and traceId.

Transaction status

Operational response

pending or running

Keep the requested physical-access state pending and poll or reconcile within the agreed operational window.

success

Mark the downstream operation complete for that PACS.

failed, partial, unsupported, unknown, or cancelled

Do not claim physical access is available. Inspect the PACS configuration, discovered mappings, selected credential and access unit, and transaction trace before changing or retrying the ICAP state.

For a failed or partial transaction, record the tenant ID, PACS ID, entity ID, related entity ID, operation, status, traceId, request time, and safe application correlation ID. Give those values to the PACS or HIS support owner together with the intended business outcome. Do not blindly resubmit a create or assignment: first determine whether ICAP's intended state already exists and whether the PACS needs a configuration correction. Re-test the corrected flow in a non-production tenant where available.

Operate safely

Update and deregister PACS records using their current version with If-Match. Review mappings after PACS configuration changes. The API reference lists the available management and discovery endpoints.