Skip to main content

Cisco Duo

Duo is where multi-factor authentication succeeds or fails, which makes its logs the record of who proved they were themselves, from what device and where — and, more usefully, who tried and could not. Fluency collects them by polling the Duo Admin API on a schedule with a read-only credential you create in the Duo Admin Panel.

Duo does not issue bearer tokens. An Admin API application gives you three values — an integration key, a secret key and an API hostname — and every request is signed with an HMAC of the secret key over the request's own contents. The practical consequence for you is that there is nothing to expire and nothing to refresh: the credential works until somebody resets it.

The setup has two halves:

  1. In Duo — add an Admin API application, check the permissions it needs, and copy its integration key, secret key and API hostname.
  2. In Fluency — install the Cisco Duo Admin API application template and paste those three values in.

What arrives

The credential reaches exactly what its permission checkboxes allow, so the boxes you check in step 3 decide the shape of the feed:

StreamEndpointPermissionContents
AuthenticationGET /admin/v2/logs/authenticationGrant read logEvery 2FA attempt: user, application, factor, result (success / denied / failure / error / fraud) and a reason from a controlled list of 51 — user_approved, user_marked_fraud, frequent_attempts, no_response, locked_out, location_restricted, out_of_date. Carries the access device (browser, OS, IP, city/state/country) and the approving device separately.
ActivityGET /admin/v2/logs/activityGrant read logAdministrative change history as structured actor / action / target records — role changes, bypass codes created and viewed, directory syncs, SSO configuration, policy edits, secrets revealed.
AdministratorGET /admin/v1/logs/administratorGrant read logThe older flat view of the same administrative actions. Superseded by Activity; see Under the hood.
TelephonyGET /admin/v2/logs/telephonyGrant read logSMS and voice-call events with the credits each consumed — the feed that shows toll fraud as spend before it shows as compromise.
Offline enrollmentGET /admin/v1/logs/offline_enrollmentGrant read logOffline-access enrollment for Duo Authentication for Windows Logon.
Trust MonitorGET /admin/v1/trust_monitor/eventsGrant read logDuo's own anomaly surface — the events it thinks are worth a second look. Gated: Premier and Advantage accounts created before 29 September 2025. An account that postdates that cutoff does not get it whatever it pays, so an empty Trust Monitor stream is not a fault.
Account utilisationGET /admin/v1/info/*Grant read informationAccount edition, user and administrator counts, telephony credits remaining, authentication attempt counts by result.
Resource rosterGET /admin/v1/users, /phones, /groups, /adminsGrant resource - ReadUsers, phones, hardware tokens, groups and administrators, as record sets on SIEM → Resources rather than as events.
The permission you leave unchecked decides which half of the integration works

The template declares a CiscoDuo resource group, so the install produces a Duo card on SIEM → Resources as well as an event index. Those two halves are gated by different permissions, and this is where least-privilege advice quietly costs you something.

  • Every log endpoint in the table above is covered by Grant read log — one checkbox, all six streams.
  • Nothing in the roster is. Duo's user, phone, group and administrator endpoints require Grant resource - Read, which is a separate checkbox in a separate group.

So an application granted only Grant read log collects events perfectly and leaves the Resources card empty, and nothing about that reads as a permission failure — the events are arriving, so the integration looks healthy. It stays looking healthy until the first time someone needs to know which of your users has no phone enrolled.

The permission set this guide grants — Grant read information and Grant read log — is what the event feed needs. Add Grant resource - Read if you want the roster too. Duo's other SIEM integrations converge on the same three: Rapid7 InsightIDR asks for read information, read log and read resource, and Sumo Logic's Duo source asks for "read information, log, and resource".

Duo shows you 180 days, and your own account setting can make that less

Every log endpoint above serves the last 180 days and no more. That is a hard ceiling in the API, in the Admin Panel, and in exported reports alike — there is no parameter that reaches further back, and Duo does not offer an archive endpoint.

Underneath that ceiling sits a setting most people never look at. Settings → Logging → Delete logs after ___ days purges log entries in your Duo account entirely, and it accepts anything from 1 to 365 days. New accounts default to keeping logs indefinitely, so this only bites where somebody set it — but where somebody did, it is the number that matters, not 180.

Check it before you install, because it decides what an outage costs. If the collector is down for a week and your retention is set to 3 days, four of those days were purged at the source and are not recoverable from anywhere. Duo's own documentation is explicit that this setting does not extend the 180-day limit either — it can only shorten it.

Before you begin

RequirementDetail
Duo editionAdmin API is available to Duo Essentials, Duo Advantage and Duo Premier paying customers, and to new Advantage or Premier trials. It is not part of the free tier. If the Admin API card is missing from the Application Catalog in step 2, this is usually why.
Duo administrator roleOwner. Duo states that only administrators with the Owner role can create or modify an Admin API application. Other roles cannot see it, so this is not a step you can delegate to a read-only admin.
Where you workThe Duo Admin Panel at admin.duosecurity.com.
Log retentionSettings → Logging. Confirm the retention period before you install — see the warning above.

Part 1 — Cisco Duo

1. Open the Application Catalog

Sign in to the Duo Admin Panel as an Owner, then open Applications → Application Catalog.

Duo Admin Panel navigation with the Applications flyout open, showing Applications, Application Catalog and Authentication Proxy under Manage

2. Add the Admin API application

Search the catalog for admin api and add the card titled exactly Admin API, using the + Add button beneath it.

Duo Application Catalog filtered to "admin api", showing an Admin API card and a Cisco ISE Admin API card side by side

Two cards match "admin api" and only one of them is Duo's own API

The search returns Admin API and Cisco ISE Admin API. They sit next to each other, they are both Cisco, and only the first one is the programmatic interface to your Duo account — the second configures Duo protection for Cisco Identity Services Engine and issues a credential of a completely different type.

Duo has several other application types whose names end in "API" as well: Auth API, which verifies individual authentications and is the one people reach for by mistake, and Accounts API, which MSPs used to manage subaccounts and which Duo stopped allowing new instances of on 11 June 2026.

Getting this wrong does not look like getting it wrong. The keys are the same shape, the install accepts them, and the credential authenticates — Duo then answers 403 on every Admin API endpoint, with the documented meaning "the ikey was created for a different integration type." The application's own page is where to check: Application Type must read Admin API.

3. Grant the permissions

Scroll to Settings → Permissions on the new application's page and check:

  • Grant read information
  • Grant read log

Leave everything else unchecked.

Duo Admin API permissions list with Grant read information and Grant read log checked and all other permissions unchecked

Grant read log is the one that matters — Duo defines it as covering "authentication, offline access, telephony, and administrator action log information", which is every event stream in What arrives. Grant read information adds the account utilisation endpoints.

Add Grant resource - Read as well if you want the Duo roster on SIEM → Resources; see the caution above for what that buys and what its absence looks like.

Two of the unchecked boxes deserve to stay that way for a reason worth knowing:

  • Grant applications lets the credential "add, modify, and delete applications … including permissions on itself or other Admin API applications." An application holding it can grant itself every other permission on this list.
  • Grant set Admin API permissions does the same thing more directly, for other Admin API applications.

Either one turns a stolen log-reader into a full administrative credential, so neither belongs on a collector. Save the application settings when you are done.

4. Collect the credentials

The three values are in the Details section of the application's page.

Duo Admin API application page showing Application Type "Admin API" and a Details section with Integration key, Secret key and API hostname, each with a Copy button; the key values are redacted

ValueFormatGoes to
Integration key20 uppercase alphanumeric characters, beginning DIAdmin API Integration key
Secret key40 characters, masked in the panel until you use CopyAdmin API Secret key
API hostnameapi-XXXXXXXX.duosecurity.com — bare host, no https:// and no trailing pathAdmin API hostname
Unusually, you can come back for the secret key

Most vendors show a secret once and mask it forever. Duo does not: the Copy button beside Secret key keeps working for the life of the application, so mislaying it costs you a trip back to this page rather than a rotation.

The cost of that convenience is that the secret key is permanently readable by anyone who can reach this page — which is any Owner. Duo's own guidance under the field is "Don't write down your secret key or share it with anyone," and its documentation adds "Treat your secret key like a password." Treat Owner-role membership as equivalent to holding this credential.

An existing application can be found again later from Applications, where its Application Type column reads Admin API:

Duo Applications list with a Configured applications table showing an Admin API row whose Application Type is Admin API

Verify before you leave Duo

Duo signs requests rather than accepting a bearer token, so a one-line curl will not do it. This does, using nothing outside the Python standard library. Fill in the three values and run it:

import base64, email.utils, hashlib, hmac, json, urllib.error, urllib.request

IKEY = "<Integration key from step 4>"
SKEY = "<Secret key from step 4>"
HOST = "<API hostname from step 4>" # api-XXXXXXXX.duosecurity.com — no https://

def call(path):
date = email.utils.formatdate()
canon = "\n".join([date, "GET", HOST.lower(), path, ""])
sig = hmac.new(SKEY.encode(), canon.encode(), hashlib.sha1).hexdigest()
auth = base64.b64encode(f"{IKEY}:{sig}".encode()).decode()
req = urllib.request.Request(f"https://{HOST}{path}", headers={
"Date": date, "Authorization": f"Basic {auth}"})
try:
with urllib.request.urlopen(req) as r:
return r.status, json.load(r)
except urllib.error.HTTPError as e:
return e.code, json.load(e)

for path in ("/admin/v1/info/summary", "/admin/v1/logs/administrator"):
status, body = call(path)
print(f"{status} {path}\n {json.dumps(body)[:180]}")

The two calls test the two permissions separately — /info/summary needs Grant read information, /logs/administrator needs Grant read log — so a failure tells you which checkbox is missing rather than that something is wrong. A healthy run returns 200 twice, and /info/summary reports your account's edition, which is also the fastest way to confirm the Duo plan question from Before you begin:

200 /admin/v1/info/summary
{"stat": "OK", "response": {"admin_count": 21, "edition": "Duo Premier",
"integration_count": 44, "telephony_credits_remaining": 960, "user_count": 862}}

Duo checks the request in a fixed order — header present, then integration key, then signature, then permission — so the first failure masks everything after it. Work the table top to bottom:

ResponseWhat it means
200 on bothDone. The credential and both permissions are correct.
401 · 40101 Missing request credentialsThe Authorization header did not arrive intact. A transcription problem in the script, not in Duo.
401 · 40102 Invalid identity in request credentialsDuo does not recognise this integration key on this host — so either the key is wrong, or the API hostname is. See the caution below; both look identical here. Back to step 4.
401 · 40103 Invalid signature in request credentialsThe integration key is right and the secret key is not. Re-copy it with the Copy button rather than by selecting the text.
401 · 40104 / 40105The Date header was malformed or out of range. Check the clock on the machine running the script.
403 · 40301 Access forbidden on /info/summary onlyGrant read information is unchecked. Back to step 3.
403 · 40301 Access forbidden on /logs/administrator onlyGrant read log is unchecked. Back to step 3.
403 · 40301 Access forbidden on bothNeither permission is granted — or the application is not an Admin API application at all. Check Application Type on its page, then step 2.
429Rate limited. Wait a minute and run it again.
A wrong API hostname does not fail — it answers

Duo resolves every api-*.duosecurity.com name, whether or not it belongs to an account. A typo in the hostname therefore does not produce a DNS error or a connection refusal; the request completes, reaches Duo, and comes back 401 with 40102 Invalid identity in request credentials — character for character what a wrong integration key returns.

So 40102 has two causes and no way to tell them apart from the response. Check the hostname against the application page before you assume the key is at fault, and copy it with the Copy button: the eight characters after api- are the account identifier and are the whole of what distinguishes your tenant from anyone else's.

Part 2 — Fluency

Install the Application

Go to Platform → Applications → Install Application From Template and choose Cisco Duo Admin API from the Office Software (SaaS) and IAM category.

ParameterNotes
Admin API Integration keyDuo's Integration key from step 4. Begins DI.
Admin API Secret keyDuo's Secret key from step 4. Masked once the application is installed.
Admin API hostnameDuo's API hostname from step 4. Bare host only — api-XXXXXXXX.duosecurity.com, not a URL. admin.duosecurity.com is the console and is not this value.
datalakePre-filled managed.
datalake index namePre-filled Duo. Two applications writing to the same index name in the same lake will collide, and the second one aborts.

Setup New Cisco Duo Admin API Application panel

Press Install. The application then appears in the Installed Applications view, where its badge reads Running once the pipeline is up.

Confirm it is running

The card is named Cisco Duo Admin API. A Running badge means the pipeline started, not that Duo accepted the credential — the two checks that distinguish those are:

  1. Query the Duo index. See Confirm data is arriving. Give it time: Duo holds every event back for two minutes by design (see Under the hood), and the collector polls on its own cadence on top of that.
  2. Compare against Duo's own Reports. Duo's Admin Panel has Reports → Authentication Log over the same window. If Duo shows authentications for a period and the index is empty for it, the problem is the integration; if Duo is empty too, the problem is that nobody authenticated.

That second check matters more here than on most integrations, because an empty index is genuinely ambiguous. Duo only records events when somebody authenticates, so a small organisation outside working hours can legitimately produce nothing for hours. Administrator and telephony events are rarer still. Do not treat silence as failure without looking at Duo's side of it.

If you granted Grant resource - Read, SIEM → Resources should also show a Duo card. That is the faster check where it applies — a roster is never legitimately empty the way an event feed can be.

Maintenance

Rotating the credential

The secret key does not expire, so rotation is something you choose to do rather than something that falls due. Do it immediately if the key has been exposed.

  1. In Duo, open Applications, then the Admin API application.
  2. Use Reset Secret Key.

Duo confirmation dialog reading &quot;Are you sure you want to reset the client secret for this application?&quot; with the warning &quot;This action is permanent. The application will stop working until you update it with the new client secret&quot; and Reset and Cancel buttons

  1. Copy the new secret key.
  2. In Fluency, uninstall and reinstall the application with the new value.
The old key stops working the moment you click Reset

Duo's confirmation says it plainly — "This action is permanent. The application will stop working until you update it with the new client secret." There is no overlap window and no way back to the previous value, so collection stops between the reset and the reinstall, and anything Duo emitted in that gap has to be caught by the next poll's backfill rather than re-requested.

Two things follow. Do the reset and the reinstall in one sitting rather than scheduling them apart. And check first whether anything else uses this application — the integration key and secret key are the application's, not Fluency's, and a reset breaks every consumer of them at once.

Fluency's template parameters are read-only after install, which is why step 4 is a reinstall rather than an edit.

Removing the integration

  1. Uninstall the Cisco Duo Admin API application in Fluency.
  2. In Duo, open Applications, select the Admin API application, and delete it.

Deleting the Duo application invalidates the keys, which is the part that actually revokes access — leaving it in place leaves a working administrative credential behind. Duo notes there is no way to restore an application deleted in error from either the Admin Panel or the API, so confirm nothing else uses it first.

Troubleshooting

SymptomLikely causeFix
Admin API is not in the Application CatalogThe Duo edition does not include it, or you are not signed in as an OwnerCheck the plan against Before you begin; /admin/v1/info/summary reports edition. Confirm your admin role before assuming the plan is at fault.
Application installs, index stays empty, 401 in the logsIntegration key or secret key mistyped, or the API hostname belongs to a different accountRun the verification script. 40102 means the key or the host; 40103 means the secret key.
403 on every requestThe permissions were never saved, or the credential came from an Auth API or Cisco ISE Admin API applicationRe-open the application and confirm Application Type reads Admin API, then re-check the boxes in step 3.
Events arrive; the Duo card on Resources is missing or emptyGrant resource - Read is not grantedCheck that box in Duo. The log feed is unaffected either way, which is why this fails quietly.
Index is empty but the application is healthyNobody authenticated in the windowCompare against Reports → Authentication Log in Duo before treating it as a fault.
Newest events are always a couple of minutes behindDuo's deliberate two-minute bufferExpected. Duo withholds events younger than two minutes so that paged reads stay consistent; nothing to fix.
Events visible in Duo's Reports never reach the lakeThe collector was down longer than your log retention windowCheck Settings → Logging in Duo. Purged entries are gone at the source and cannot be re-requested.
Ingestion falls behind after a busy periodDuo rate limiting (429)Duo throttles per account and recovers on its own. Sustained throttling slows the catch-up rather than dropping data.
Events stopped abruptly with no configuration changeThe secret key was reset, or the application was deletedBoth invalidate the credential immediately. Check the application still exists in Duo, then rotate as above.
Duplicate events after a reinstallThe new install backfilled over ground already collectedDeduplicate on the authentication log's txid, which is unique per transaction.

Under the hood

Engineering reference — the Duo Admin API and how this credential reaches it

What this section describes

Everything below describes the Duo Admin API — the endpoints, the signing scheme and the responses the credential reaches. The settings that belong to your own install rather than to the API — which of the log endpoints it polls, its cadence, what the CiscoDuo resource group holds and the field names events land under — are recorded on the install itself: open the application's details panel with the blue eye button and read its Actions list, which lists every object the install created.

Authentication

Duo uses signed requests rather than bearer tokens, so there is no token endpoint, no expiry and no refresh. Each request carries two headers:

  • Date — RFC 2822, and byte-identical to the value that was signed.
  • Authorization: Basic base64(ikey + ":" + signature).

The signature is an HMAC over a five-line canonical string built from the request itself:

Tue, 21 Aug 2012 17:29:18 -0000
GET
api-xxxxxxxx.duosecurity.com
/admin/v1/info/summary

The fifth line is the sorted, URL-encoded parameter list and stays blank when there are none — but the line itself is not optional. Duo supports two signing versions: v2 (HMAC-SHA1, the form above) and v5 (HMAC-SHA512, which also hashes the request body and any X-Duo-* headers). v5 is preferred and is the default in Duo's own API clients. The log and info endpoints accept either; the Integrations v2/v3, Policies v2 and Passport v2 endpoints require v5 and reject v2-signed requests.

Because the Date header is part of what is signed, the caller's clock is part of the credential — a machine with a badly skewed clock fails authentication with a correct key.

Error codes

Duo returns a JSON body on failure with a numeric code whose first three digits are the HTTP status. It checks in order, so the earliest failure is the one you see:

CodeMeaning
40101Missing request credentials — no usable Authorization header.
40102Invalid identity — the integration key is unknown on this host.
40103Invalid signature — the secret key is wrong.
40104 / 40105The Date header is malformed or outside the accepted range.
40301Access forbidden — the permission is not granted, or the key belongs to another application type.
40401Resource not found — the path is wrong.
429Rate limited.

Note that api-*.duosecurity.com is effectively a wildcard: any subdomain of that form resolves and serves the API, so a wrong hostname returns 40102 rather than failing to connect.

The 180-day window and the two-minute buffer

All log endpoints serve at most the last 180 days, and none of them serve anything newer than two minutes. Duo describes the delay as deliberate: "Duo operates a large scale distributed system, and this two minute buffer period ensures that calls will return consistent results. Querying for results more recent than two minutes will return as empty."

Duo's guidance is to request logs no more than once per minute.

The account-level Settings → Logging value (log_retention_days in the API, 1–365 days, null by default) purges entries below that ceiling and cannot raise it.

Endpoints

EndpointNotes
GET /admin/v2/logs/authenticationPaged by next_offset. Filters on users, groups, applications, results, reasons and factors.
GET /admin/v2/logs/activityRequires mintime and maxtime as 13-digit millisecond timestamps, at most 180 days apart.
GET /admin/v1/logs/administratorReturns only the 1000 earliest matching events; paging is by advancing mintime. Announced for deprecation in favour of Activity Logs v2, with no date given.
GET /admin/v2/logs/telephonyPaged by next_offset.
GET /admin/v1/logs/offline_enrollmentSame 1000-event cap and the same deprecation notice.
GET /admin/v1/trust_monitor/eventsPaged by next_offset. Returns nothing on accounts outside the eligibility window described in What arrives.
GET /admin/v1/info/summaryedition, user_count, admin_count, integration_count, telephony_credits_remaining.

Timestamps are Unix seconds except where noted — the Activity Logs v2 endpoint uses milliseconds, and the authentication log carries both an integer timestamp and an ISO-8601 isotimestamp.

An authentication event

{
"access_device": {
"browser": "Chrome", "browser_version": "67.0.3396.99",
"epkey": "EP18JX1A10AB102M2T2X", "ip": "169.232.89.219",
"location": {"city": "Ann Arbor", "country": "United States", "state": "Michigan"},
"os": "Mac OS X", "os_version": "10.14.1",
"is_encryption_enabled": true, "is_firewall_enabled": true
},
"application": {"key": "DIY231J8BR23QK4UKBY8", "name": "Acme Corp IdP",
"destination_name": "Microsoft 365"},
"auth_device": {"ip": "192.168.225.254", "key": "DP5BJ05HI4WRBVI4Q7JF",
"name": "My iPhone X (734-555-2342)"},
"email": "narroway@example.com",
"event_type": "authentication",
"factor": "duo_push",
"isotimestamp": "2020-02-13T18:56:20.351346+00:00",
"reason": "user_approved",
"result": "success",
"timestamp": 1581620180,
"trusted_endpoint_status": "not trusted",
"txid": "340a23e3-23f3-23c1-87dc-1491a23dfdbb",
"user": {"key": "DU3KC77WJ06Y5HIV7XKQ", "name": "narroway@example.com",
"groups": ["Duo Users", "CorpHQ Users"]}
}

Three properties are worth knowing:

  • txid is the deduplication key. It is unique per authentication transaction and survives a reinstall that re-reads ground already collected.
  • Names are present, not just identifiers. Unlike many audit APIs, Duo returns user.name, user.groups, application.name and auth_device.name inline, so a detection can name its subject without a second lookup. user.key is the user_id that joins to the resource roster where you have collected it.
  • access_device and auth_device are different machines — the one signing in and the one approving. A push approved from a device in a different country from the browser requesting it is visible in a single record.

On Premier and Advantage accounts the record also carries adaptive_trust_assessments, Duo's own scoring of the attempt, with a trust_level and a human-readable reason.

MSP subaccounts

One Admin API application in a parent account can query its subaccounts by sending the subaccount's API host and passing its account_id as a request parameter — there is no need to create a separate application per subaccount. This became the supported path when Duo stopped allowing new Accounts API applications on 11 June 2026. Whether the Fluency template exposes account_id is not something the form suggests; a separate install per subaccount is the straightforward arrangement.

References

Vendor

Fluency

  • Okta — the other identity feed in this section, and the one Duo most often sits alongside.
  • Integration Matrix — which ingress method each product supports.
  • Business Software — the rest of this category.