IdExchange 1.9.1
Breadcrumbs

Credential Lookup: Setup and User Guide

This guide explains the IDMS Credential Lookup feature: what it does, how to switch it on, who can use it, how to call it from another application, and how to check that it is running well. It is written for administrators who are new to the feature. You do not need to edit any configuration files.


1. Overview

Credential Lookup lets another application, such as a badge reader station or an access control system, find a person in IDMS from a single value it has scanned or typed, such as a badge barcode. It sends the value to IDMS and gets back, in one quick answer:

Returned

Meaning

First, middle and last name

The person's name, as stored in IDMS

Network user ID

The person's network or directory account ID

Request status

The status of the person's most recent credential request, for example APPROVED or ISSUED

Badge type

The credential type (policy) the person is assigned to

Matched field

Which field the value was found in, for example barCode


2. What it does and how it works

2.1 Searchable fields

The values you look up come from the questions on a credential type's intake form, for example a "Badge barcode" question. An administrator chooses which intake questions can be searched by ticking Searchable next to them. Each credential type has its own choices, so different credential types can be searched by different fields.

2.2 How a lookup finds the person

  1. When a person's answer to a searchable question is saved, IDMS creates a fingerprint of the value and stores it in a search index. The fingerprint is a one-way code made with a secret key, so the index never contains the readable value.

  2. When an application looks up a value, IDMS makes the fingerprint of that value and finds the matching entry in the index. This takes a few milliseconds, even with very large numbers of people.

  3. IDMS then reads the person's name, network user ID, latest request status and badge type, and returns them.

2.3 Things worth knowing

  • Exact match only. The value must match the stored answer exactly, except that spaces before and after the value are ignored and, for numbers, leading zeros are ignored (000123 matches 123). Partial or "starts with" searches are not supported.

  • Freshness. Answers are remembered for up to 60 seconds to keep lookups fast. A change in IDMS (for example a request moving to ISSUED) appears in lookups within 60 seconds.

  • Index upkeep is automatic. The index is updated whenever a person is enrolled, edited, moved to another credential type or expunged. When you tick Searchable on a credential type that already has people, IDMS indexes them in the background. A nightly job checks the whole index and repairs anything that is out of step (see section 7).

  • Privacy. Readable values are never stored in the index and never written to the log. Expunged people are removed from the index, so they cannot be found.

  • Duplicates. If two people have the same value in a searchable field, a lookup returns "ambiguous" (409) rather than guessing. The IDMS log names both people so you can correct the data.

  • Auditing. Every time someone ticks or unticks Searchable, IDMS writes an audit entry with the operator, credential type, field and change (audit transaction type SrchIdxCfg).


3. Configuration requirements

There is nothing to install and no configuration file to edit.

Requirement

Details

Calling account

An IDMS operator account with a client certificate and the BadgeLookup role (section 3.1, Step 2).

3.1 Setup steps

Step 1: Choose the searchable field (needs the SystemManager role)

  1. Go to Administration > Credential Types.

  2. Open the credential type (policy) whose people you want to find.

  3. In the Intake Form grid, find the question that holds the value, for example barCode.

  4. Tick Searchable for that question. Hover over the column heading for guidance.

  5. Save the credential type.

  6. Repeat for every credential type whose people should be found.

Notes:

  • Searchable can only be ticked for text fields (text box, text area, IDMS user ID). Files, PDFs, photos and signatures cannot be searched.

  • Choose fields whose values are unique to one person, such as a badge number. Do not make fields with only a few possible answers searchable (yes/no, department, and so on).

  • Existing people on that credential type are indexed in the background straight after you save. Large credential types can take a few minutes. The IDMS log shows when the background indexing starts and finishes.

Step 2: Create the account the calling application will use (needs the SystemManager role)

  1. Go to Administration > Operators and add an operator for the application, for example "Badge Station Service".

  2. Enter the Certificate Thumbprint of the client certificate the application will present.

  3. Assign the role BadgeLookup.

Give this account only the roles it needs. Use a separate account for each application so their traffic can be told apart in the logs.

Step 3: Give monitoring access (optional, needs the SystemManager role)

  1. Go to Administration > Operators and open each person who should see the Performance tab.

  2. Assign the role SystemMonitor. These people also need SystemManager, because the tab is on the Administration > System Connections page.

  3. If a monitoring dashboard will call the detailed status API, create a separate account for it with SystemMonitor, so it does not share the status call limit with people using the screen.

Step 4: Test it

Use the PowerShell sample in section 6.3 with a value you know exists. You should get 200 and the person's details.


4. Roles required

Role

Who gets it

What it allows

SystemManager

IDMS administrators

Ticking Searchable on credential types; creating operators and assigning roles; reaching Administration > System Connections; running the index jobs on demand

BadgeLookup

The account used by the calling application

Calling the lookup API (api/v2/lookup) and the basic status API (api/v2/status)

SystemMonitor

Administrators who watch performance, and monitoring dashboards

Seeing the Performance tab and calling the detailed status API (api/v2/status/detail)

Both new roles (BadgeLookup and SystemMonitor) are added to IDMS automatically when it starts. You only need to assign them.


5. Calling the lookup API

5.1 The basics

Every call needs a token. The application gets a token once, keeps it, and sends it with each lookup.

Step

Call

1. Get a token

POST <https://<server>>/WebApi/Token, presenting the client certificate. Body: grant_type=password&username=<any>&password=<any>. The certificate identifies the account.

2. Look up a value

GET <https://<server>>/WebApi/api/v2/lookup/<value>?attribute=<field name> with the header Authorization: Bearer <access_token>

3. Check health (optional)

GET <https://<server>>/WebApi/api/v2/status with the same header

  • <value> is the scanned value. URL-encode it if it can contain anything other than letters and numbers.

  • attribute is the intake field name (its dataName), for example barCode. It is optional but recommended: it makes the lookup faster and avoids ambiguous results. Without it, every searchable field is searched.

  • Tokens last 1 day. Request one token, reuse it for all lookups, and renew it every hour. Do not request a new token for every scan.

5.2 Answers you can get

A successful lookup (200 OK):

JSON
{
  "userId": 1000015058,
  "firstName": "Jane",
  "middleName": "A",
  "lastName": "Doe",
  "networkUserId": "jdoe01",
  "requestStatus": "APPROVED",
  "badgeType": "DCMLL",
  "matchedAttribute": "barCode",
  "asOf": "2026-10-12T14:03:22Z"
}

asOf is when the details were read from the database (up to 60 seconds earlier).

Code

Meaning

What the application should do

200

Exactly one person found

Use the details

400 InvalidValue

The value is blank or longer than 256 characters, or attribute is not a searchable field

Do not retry; fix the request

401

The token is missing or expired

Get a new token, then retry once

403

The account does not have the BadgeLookup role

Do not retry; ask the IDMS administrator

404 NotFound

No one has this value (also returned for values in the wrong format)

Do not retry; treat as "not found"

409 Ambiguous

More than one person has this value

Do not retry; report it to the IDMS administrator

429 TooManyRequests

This account is sending too fast

Wait the number of seconds in Retry-After (also retryAfterSeconds in the body), then retry

503 ServiceBusy

IDMS is busy or the database is slow

Wait the number of seconds in Retry-After, then retry

500 ServerError

Unexpected error

Retry later; give the correlationId from the body to support

Error bodies look like { "error": "NotFound" }. 429 and 503 bodies also include retryAfterSeconds.

Every answer includes a Server-Timing header showing how long IDMS took, for example db;dur=3.2, total;dur=5.1 (milliseconds).

5.3 Good practice for the calling application

  • Always wait for Retry-After on 429 and 503. Retrying immediately makes the overload worse.

  • Never retry 400, 403, 404 or 409. The answer will not change.

  • If many stations share one application, the application should call IDMS on their behalf and share the results, rather than each station calling separately. This also applies to the status API.

  • Optionally send an X-Station-Id header naming the station. IDMS can log it to help trace problems.


6. Sample API calls

Replace <https://idms.example.com/WebApi,> the certificate thumbprint and the values with your own.

6.1 PowerShell: get a token and look up a value

Works in Windows PowerShell 5.1 and PowerShell 7. The client certificate must be in the current user's certificate store.

PowerShell
$baseUrl    = "https://idms.example.com/WebApi"
$thumbprint = "<client certificate thumbprint>"
$cert       = Get-Item -Path (Join-Path "Cert:\CurrentUser\My" $thumbprint)
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

# 1. Get a token (once; reuse it and renew it hourly)
$token = Invoke-RestMethod -Method Post -Uri "$baseUrl/Token" -Certificate $cert `
    -ContentType "application/x-www-form-urlencoded" `
    -Body "grant_type=password&username=apiuser&password=unused"
$headers = @{ Authorization = "Bearer $($token.access_token)" }

# 2. Look up a badge barcode
$value = [uri]::EscapeDataString("1234567890")
try {
    $person = Invoke-RestMethod -Method Get -Uri "$baseUrl/api/v2/lookup/$($value)?attribute=barCode" `
        -Headers $headers -Certificate $cert
    "$($person.firstName) $($person.lastName): $($person.requestStatus), $($person.badgeType)"
}
catch {
    $code = [int]$_.Exception.Response.StatusCode
    "Lookup failed with HTTP $code"
}

6.2 PowerShell: check the status

PowerShell
# Basic status (role BadgeLookup): ok, degraded or unavailable
Invoke-RestMethod -Uri "$baseUrl/api/v2/status" -Headers $headers -Certificate $cert

# Detailed status (role SystemMonitor)
Invoke-RestMethod -Uri "$baseUrl/api/v2/status/detail" -Headers $headers -Certificate $cert |
    ConvertTo-Json -Depth 6

6.3 PowerShell: quick test with status code and timing

Use this in Step 4 of the setup to see exactly what IDMS returns, including errors.

PowerShell
$response = Invoke-WebRequest -Uri "$baseUrl/api/v2/lookup/1234567890?attribute=barCode" `
    -Headers $headers -Certificate $cert -UseBasicParsing -SkipHttpErrorCheck
"Status: $($response.StatusCode)"
"Timing: $($response.Headers['Server-Timing'])"
$response.Content

-SkipHttpErrorCheck needs PowerShell 7. In Windows PowerShell 5.1, remove it; error codes then appear as exceptions, as in 6.1.

6.4 curl (Windows)

The curl that comes with Windows can use a certificate from the Windows certificate store:

Bash
curl -s -X POST "https://idms.example.com/WebApi/Token" \
  --cert "CurrentUser\My\<thumbprint>" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=password&username=apiuser&password=unused"

curl -s -i "https://idms.example.com/WebApi/api/v2/lookup/1234567890?attribute=barCode" \
  --cert "CurrentUser\My\<thumbprint>" \
  -H "Authorization: Bearer <access_token>"

On Linux or macOS, use the certificate file instead, for example --cert-type P12 --cert client.pfx:<pfx password>.

6.5 C# (.NET): reuse one client and one token

C#
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

public sealed class CredentialLookupClient
{
    private readonly HttpClient _http;
    private string _token;
    private DateTime _tokenExpires = DateTime.MinValue;

    public CredentialLookupClient(string baseUrl, X509Certificate2 clientCertificate)
    {
        var handler = new HttpClientHandler();
        handler.ClientCertificates.Add(clientCertificate);
        _http = new HttpClient(handler) { BaseAddress = new Uri(baseUrl.TrimEnd('/') + "/") };
    }

    public async Task<string> LookupAsync(string value, string attribute = "barCode")
    {
        await EnsureTokenAsync();
        var request = new HttpRequestMessage(HttpMethod.Get,
            "api/v2/lookup/" + Uri.EscapeDataString(value) + "?attribute=" + Uri.EscapeDataString(attribute));
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _token);

        HttpResponseMessage response = await _http.SendAsync(request);
        if (response.StatusCode == (HttpStatusCode)429 || response.StatusCode == HttpStatusCode.ServiceUnavailable)
        {
            TimeSpan wait = response.Headers.RetryAfter?.Delta ?? TimeSpan.FromSeconds(5);
            await Task.Delay(wait);   // wait as told, then let the caller try again
            return null;
        }
        if (response.StatusCode == HttpStatusCode.NotFound)
        {
            return null;              // not found: do not retry
        }
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync();   // JSON with the person's details
    }

    private async Task EnsureTokenAsync()
    {
        if (_token != null && DateTime.UtcNow < _tokenExpires)
        {
            return;
        }
        var body = new FormUrlEncodedContent(new[]
        {
            new System.Collections.Generic.KeyValuePair<string, string>("grant_type", "password"),
            new System.Collections.Generic.KeyValuePair<string, string>("username", "apiuser"),
            new System.Collections.Generic.KeyValuePair<string, string>("password", "unused")
        });
        HttpResponseMessage response = await _http.PostAsync("Token", body);
        response.EnsureSuccessStatusCode();
        dynamic json = Newtonsoft.Json.JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
        _token = (string)json.access_token;
        _tokenExpires = DateTime.UtcNow.AddHours(1);   // renew hourly
    }
}

Create one CredentialLookupClient when the application starts and use it for every scan.


7. Background jobs (Job Scheduler)

Credential Lookup uses two background tasks. Neither needs setting up.

7.1 Background indexing (runs on its own)

When someone ticks Searchable on a credential type and saves, IDMS indexes that credential type's existing people in the background. It works in small batches with short pauses so it does not slow IDMS down. When someone unticks Searchable, IDMS removes that field's index entries for the credential type. Both are recorded in the IDMS log.

7.2 Nightly check and repair: SearchableIndexReconciliationJobManager

Item

Details

What it does

Checks the whole search index against the IDMS records. It removes entries for people who were deleted, moved to another credential type, or whose field is no longer searchable, and adds or fixes entries that are missing or out of date.

When it runs

Every day at 3:30 am (server time).

Where to see it

Administration > Scheduling, Job Scheduling tab. It is listed by name, with its state and the result of its last run.

Set up needed

None. Unlike most IDMS jobs, it is switched on automatically.

Several IDMS servers

Safe. Only one server runs it at a time; the others skip that night's run.

Pause or resume it: on the Job Scheduling tab, use the pause or play button on the job's row.

Change when it runs: click the cog button on the job's row and change the schedule. The schedule uses Quartz cron format (seconds, minutes, hours, day of month, month, day of week):

Schedule

Cron value

Every day at 3:30 am (default)

0 30 3 * * ?

Every day at 1:00 am

0 0 1 * * ?

Every Sunday at 2:00 am

0 0 2 ? * SUN

Choose a quiet time. The job reads every person on credential types with a searchable field, so on large systems it can take a while.

Run it now: a SystemManager account can start it straight away with POST <https://<server>>/WebApi/api/SearchableIndex/StartReconciliation. To index a single credential type again, use POST <https://<server>>/WebApi/api/SearchableIndex/StartBackfill?policyKey=<credential type key>. Both return straight away; the work continues in the background and is logged.

7.3 External systems health check: HealthCheckerJobManager

The External systems card on the Performance tab shows the latest result of the existing IDMS health check job. That job is installed paused. If the card says the check hasn't run, resume HealthCheckerJobManager on the Job Scheduling tab. It does not affect lookups.


8. Monitoring performance

8.1 The Performance tab

Go to Administration > System Connections and open the Performance tab. You need the SystemManager and SystemMonitor roles.

  • The figures refresh every 20 seconds while the tab is open. Use Refresh for an immediate update, or Pause to stop.

  • Each card has an (i) button at its top right. Click it for a plain explanation of the card.

Card

What it tells you

Status banner

OK (green), Degraded (amber, with the reasons listed) or Unavailable (red). Also shows which server answered and how fresh the figures are.

Badge lookups

Lookups in the last minute; how many are being worked on now ("Busy N of 64"); how many were turned away

Response time

Typical and slowest-5% answer times for the last minute and last 5 minutes; average database time

Database

Whether the IDMS database is reachable, and how long a quick check takes

Server

Processor use of IDMS and of the whole server; web server connections

External systems

Summary of the IDMS external-system health check

Trend

A chart of the last 40 refreshes (about 13 minutes): lookups per minute and slowest-5% response time

When to act:

You see

What it means

What to do

Degraded: slowest 5% over 500 ms

Lookups are getting slow

Check the Database and Server cards. Look for other heavy work on the server or database.

Degraded: lookup slots busy over 75%

Many lookups at once

Usually a traffic peak. If it lasts, the calling application may not be waiting for Retry-After.

Degraded: database check over 1 s

The database is slow

Check the database server.

Unavailable

IDMS cannot reach its database

Check the database server and the IDMS log straight away.

"Turned away" above 0

Lookups were refused with 429 or 503

Check that the calling application waits for Retry-After.

If you run several IDMS servers behind a load balancer, each server has its own figures. The banner shows which server answered.

8.2 Status APIs for dashboards

API

Role

Returns

GET api/v2/status

BadgeLookup

{ "status": "ok", "asOf": "..." }. status is ok, degraded or unavailable.

GET api/v2/status/detail

SystemMonitor

All the figures on the Performance tab, as JSON

  • The figures are measured every 10 seconds, so calling more often gives the same answer.

  • Each account may call each status API 6 times a minute. More calls get 429. Poll every 20 to 30 seconds.

8.3 The IDMS log

By default the IDMS WebApi log is c:\\temp\\idexchangeWebApi.txt on the IDMS server. Useful lines:

Log line

Meaning

lookup summary (last minute)

Written once a minute while there is lookup traffic: counts per answer, response times and the busiest accounts

searchable index reconciliation finished

The nightly check finished, with counts of entries added and removed

Backfill started / finished

Background indexing after Searchable was ticked

Duplicate warning

Two people have the same value in a searchable field. Both IDs are listed.

Status changes and database check failures

Logged once when they happen, and again when they recover

Readable lookup values are never written to the log.

8.4 Built-in limits

These protect IDMS from overload. They suit most sites and do not need changing.

Limit

Default

Lookups per second per account

100 (short bursts up to 200)

Lookups worked on at the same time (all accounts)

64

Status API calls per minute, per account and API

6

Failed (unauthorised) requests per second from one address before it is refused

20

"Not found" answers per minute before an account is slowed for 5 minutes as possible guessing

300, when most of its lookups are "not found"

Longest value accepted

256 characters

How long answers are remembered

60 seconds

If your traffic needs different limits, they can be overridden in Web.config. See the separate note "Badge Lookup: Optional Rate-Limit Settings" before changing them.


9. Troubleshooting

Problem

Likely cause

Fix

Every lookup returns 404

Searchable isn't ticked for the field, or attribute names a different field

Check the credential type's Intake Form. Check the field name (dataName) matches attribute exactly.

A person who should be found returns 404

Their credential type has no searchable field, or their answer is different from the scanned value

Check the person's credential type and their answer to the field. Run the reconciliation job if you suspect the index is out of date.

400 InvalidValue

attribute is not searchable on any credential type, or the value is blank or too long

Correct the field name or the value

401

The token expired or wasn't sent

Get a new token; renew it hourly

403

The account lacks BadgeLookup (lookups and basic status) or SystemMonitor (detailed status)

Assign the role in Administration > Operators

409 Ambiguous

Two people share the value

Check the IDMS log for the duplicate warning and correct one person's record

Many 429s

The application is sending faster than its limit, or not waiting for Retry-After

Make the application wait as told; reuse one token

503s

IDMS is very busy or the database is slow

Check the Performance tab and the database server

The Performance tab is missing

The operator lacks SystemMonitor

Assign the role, then sign out and back in

External systems says the check hasn't run

HealthCheckerJobManager is paused

Resume it on the Job Scheduling tab (optional)

Web server connections says "not available"

The IDMS application pool account isn't in the Windows Performance Monitor Users group

Optional: add it to the group and recycle the application pool