DNA Center
DNA Center (legacy) REST APIs, configuration templates, and Plug and Play device onboarding.
DNA Center → Catalyst Center
DNA Center has been rebranded to Catalyst Center as of version 2.3.5+. The API paths remain the same (/dna/…). This document covers the legacy DNA Center name and any patterns specific to older versions. For the full reference, see Catalyst Center Quick Reference.
|
API Token Authentication
Get auth token — identical to Catalyst Center
DNAC_HOST="dnac.example.com"
TOKEN=$(curl -s -k -X POST \
"https://${DNAC_HOST}/dna/system/api/v1/auth/token" \
-H "Content-Type: application/json" \
-u "admin:password" | jq -r '.Token')
The /dna/ prefix in API paths has been retained even in Catalyst Center. Cisco has not changed the API base path.
|
Device Inventory
List all network devices
curl -s -k \
"https://${DNAC_HOST}/dna/intent/api/v1/network-device" \
-H "X-Auth-Token: ${TOKEN}" | jq '.response[] | {hostname, managementIpAddress, platformId, softwareVersion}'
Get device by serial number — useful for PnP correlation
curl -s -k \
"https://${DNAC_HOST}/dna/intent/api/v1/network-device?serialNumber=FCW2345L0AB" \
-H "X-Auth-Token: ${TOKEN}" | jq '.response[] | {hostname, managementIpAddress}'
Plug and Play (PnP) — Zero-Touch Provisioning
List PnP devices waiting for claim
curl -s -k \
"https://${DNAC_HOST}/dna/intent/api/v1/onboarding/pnp-device" \
-H "X-Auth-Token: ${TOKEN}" | jq '.[] | {serialNumber, hostname, state: .deviceInfo.state, pid: .deviceInfo.pid}'
Output
{
"serialNumber": "FCW2345L0AB",
"hostname": "floor2-sw-01",
"state": "Unclaimed",
"pid": "C9300-48T"
}
Claim a PnP device — assign to site with template
curl -s -k -X POST \
"https://${DNAC_HOST}/dna/intent/api/v1/onboarding/pnp-device/claim" \
-H "X-Auth-Token: ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"deviceClaimList": [{
"deviceId": "eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee",
"configList": [{
"configId": "ffffffff-ffff-ffff-ffff-ffffffffffff",
"configParameters": [
{"key": "hostname", "value": "floor2-sw-01"},
{"key": "mgmt_ip", "value": "10.50.2.10"}
]
}]
}],
"siteId": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
"type": "Default"
}' | jq
Get PnP device history — trace provisioning steps
DEVICE_ID="eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee"
curl -s -k \
"https://${DNAC_HOST}/dna/intent/api/v1/onboarding/pnp-device/${DEVICE_ID}/history" \
-H "X-Auth-Token: ${TOKEN}" | jq '.response[] | {timestamp, details, errorFlag}'
PnP workflow:
1. New switch boots → DHCP option 43 points to DNAC
2. Device contacts DNAC → appears in PnP device list (state: Unclaimed)
3. Admin claims device → assigns site, template, image
4. DNAC pushes day-0 config + image upgrade
5. Device reboots → state changes to Provisioned
SWIM — Software Image Management
Get available software images
curl -s -k \
"https://${DNAC_HOST}/dna/intent/api/v1/image/importation" \
-H "X-Auth-Token: ${TOKEN}" | jq '.response[] | {name, version, imageType, isGoldenImage: .isTaggedGolden}'
Mark an image as golden — sets it as the standard for a device family
curl -s -k -X PUT \
"https://${DNAC_HOST}/dna/intent/api/v1/image/importation/golden" \
-H "X-Auth-Token: ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"imageId": "11111111-1111-1111-1111-111111111111",
"siteId": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
"deviceRole": "ALL",
"deviceFamilyIdentifier": "Switches and Hubs"
}' | jq
Distribute image to a device — stage before activation
curl -s -k -X POST \
"https://${DNAC_HOST}/dna/intent/api/v1/image/distribution" \
-H "X-Auth-Token: ${TOKEN}" \
-H "Content-Type: application/json" \
-d '[{
"deviceUuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
"imageUuid": "11111111-1111-1111-1111-111111111111"
}]' | jq
Activate image on device — triggers reload
curl -s -k -X POST \
"https://${DNAC_HOST}/dna/intent/api/v1/image/activation/device" \
-H "X-Auth-Token: ${TOKEN}" \
-H "Content-Type: application/json" \
-d '[{
"deviceUuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
"imageUuidList": ["11111111-1111-1111-1111-111111111111"],
"activateLowerImageVersion": true
}]' | jq
| SWIM follows a 3-step process: Import → Distribute (copy to device flash) → Activate (set boot variable + reload). Always distribute during business hours, activate during maintenance window. |
Site Hierarchy
Get all sites
curl -s -k \
"https://${DNAC_HOST}/dna/intent/api/v1/site" \
-H "X-Auth-Token: ${TOKEN}" | jq '.response[] | {name: .siteNameHierarchy, type: .additionalInfo[0].attributes.type}'
Create a building in the hierarchy
curl -s -k -X POST \
"https://${DNAC_HOST}/dna/intent/api/v1/site" \
-H "X-Auth-Token: ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"type": "building",
"site": {
"building": {
"name": "Building-B",
"parentName": "Global/US/Los Angeles",
"address": "1234 Main St, Los Angeles, CA 90012",
"latitude": 34.0522,
"longitude": -118.2437
}
}
}' | jq
Template Programmer
List all template projects
curl -s -k \
"https://${DNAC_HOST}/dna/intent/api/v1/template-programmer/project" \
-H "X-Auth-Token: ${TOKEN}" | jq '.[] | {name, id, templates: [.templates[]?.name]}'
Get template content — see the Jinja/Velocity template body
TEMPLATE_ID="dddddddd-dddd-dddd-dddd-dddddddddddd"
curl -s -k \
"https://${DNAC_HOST}/dna/intent/api/v1/template-programmer/template/${TEMPLATE_ID}" \
-H "X-Auth-Token: ${TOKEN}" | jq '{name, templateContent, templateParams: [.templateParams[].parameterName]}'
Output
{
"name": "Day1-Access-Switch",
"templateContent": "hostname $hostname\ninterface vlan $mgmt_vlan\n ip address $mgmt_ip $mgmt_mask\n...",
"templateParams": ["hostname", "mgmt_vlan", "mgmt_ip", "mgmt_mask"]
}
Templates use Velocity ($variable) or Jinja2 ({{ variable }}) syntax. Velocity is the default. Bind variables appear in templateParams and must be supplied at deployment time.
|