Lab 21.1 - Exploring the IOS-XE RESTCONF API¶
Cisco IOS-XE supports different YANG models and each of these models uses a different data structure. This means you can "get" or "configure" particular features on IOS-XE with different JSON or XML objects.
- Lab 21.1 - Exploring the IOS-XE RESTCONF API
- Task 1 - Browse the IOS-XE Native Model with Postman
- Task 2 - Make Configuration Changes using the Native Model
Task 1 - Browse the IOS-XE Native Model with Postman¶
This task will focus on issuing GET requests with Postman.
Note: For these tasks, use the
csr1device.
Step 1-0¶
Remote Desktop into your Jump Host and open the Postman application on the Desktop.
On your first run of the application you may get a prompt to create an account. Please select Skip and go to the app, you do NOT need to create an account for this lab.

Step 1-1¶
Create a new "HTTP Request" by using the New button or pressing the + sign on the central bar.
Note: The Postman application will look similar to the screenshots in this lab - but, due to the fact that the application layout changes over time, the screenshots may not be exactly the same in your lab environment.

Step 1-2¶
You are now going to construct your first HTTP Request to get configuration data from the IOS-XE device.
First, confirm the HTTP request type is GET.
Step 1-3¶
In the Authorization tab, select Basic Auth for the Type, and input ntc for Username and ntc123 for the Password respectively.

Step 1-4¶
In the Headers tab, add two header options:
AcceptContent-Type
Set both to application/yang-data+json.
These headers are specific to RESTCONF. They mean we are going to be using JSON data, but it is JSON data that adheres to YANG models.

Step 1-5¶
Add the following URL in the text box next to the GET drop down:
This URL is a good starting point that returns the whole running configuration structured using the Cisco "native" specific data model.
Step 1-6¶
Click the Send button to make the HTTP request.
Step 1-7¶
If it fails, it is again because Postman by default validates certificates and our lab devices use self-signed certificates. In the pane below, click the Disable SSL Verification button - you can always toggle this On/Off later from the global Postman settings.

Step 1-8¶
Press the Send button, this time the request should be successful - take note of the 200 OK response code and the verbose output in the Body tab below.

Step 1-9¶
You should see a large JSON response in the bottom pane.
Scroll through the response object and take a deeper look.
Note that Status code is 200. This is a standard HTTP Response code and tells us that everything worked.
This is a sample of what you'll see in Postman:
{
"Cisco-IOS-XE-native:native": {
"version": "17.1",
"boot-start-marker": [
null
],
"boot-end-marker": [
null
],
"memory": {
"free": {
"low-watermark": {
"processor": 72107
}
}
},
"call-home": {
"Cisco-IOS-XE-call-home:contact-email-addr": "sch-smart-licensing@cisco.com",
"Cisco-IOS-XE-call-home:profile": [
{
"profile-name": "CiscoTAC-1",
"active": true,
"destination": {
"transport-method": "http"
}
}
]
},
"service": {
"timestamps": {
"debug": {
"datetime": {
"msec": {}
}
},
"log": {
"datetime": {
"msec": [
null
]
}
}
},
**OUTPUT TRUNCATED**
Step 1-10¶
You can now limit the response and filter by adding "keys" found in the JSON response to the URL.
For example, version was a root key as we saw in the response above.
Step 1-11¶
Add version to the URL.
This should be the updated URL:
Step 1-12¶
Click Send.
You should see the following response:
Notice how cleaner the response is since you are only requesting specific data.
Step 1-13¶
Query for all interfaces using this URL:
Step 1-14¶
You should have a configured IP on GigabitEthernet2 from a previous lab. If not, configure an address and mask on Gi2 first via the CLI (access through SSH).
ntc@ntc-training:~$ ssh csr1
Password:
csr1#conf t
Enter configuration commands, one per line. End with CNTL/Z.
csr1(config)#int gi2
csr1(config-if)#ip address 10.1.13.1 255.255.255.0
csr1(config-if)#description Connects to csr3
csr1(config-if)#end
csr1#
Step 1-15¶
Query for just GigabitEthernet2:
Response:
{
"Cisco-IOS-XE-native:GigabitEthernet": {
"name": "2",
"description": "Connects to csr3",
"ip": {
"address": {
"primary": {
"address": "10.1.13.1",
"mask": "255.255.255.0"
}
}
},
"mop": {
"enabled": false,
"sysid": false
},
"Cisco-IOS-XE-ethernet:negotiation": {
"auto": true
}
}
}
Step 1-16¶
Query for just the interface description:
Response:
Step 1-17¶
Query for just the Primary Address and Mask:
https://csr1/restconf/data/Cisco-IOS-XE-native:native/interface/GigabitEthernet=2/ip/address/primary
You can continue trying "different URLs" to query different sets of data.
Step 1-18¶
As we said earlier, IOS-XE supports different models of data. Let's see what interface configuration data looks like modeled in a different fashion.
Now query the device's GigabitEthernet2, but using the IETF interfaces model:
Response:
{
"ietf-interfaces:interface": {
"name": "GigabitEthernet2",
"description": "Connects to csr3",
"type": "iana-if-type:ethernetCsmacd",
"enabled": true,
"ietf-ip:ipv4": {
"address": [
{
"ip": "10.1.13.1",
"netmask": "255.255.255.0"
}
]
},
"ietf-ip:ipv6": {}
}
}
Notice how this is the same exact data received in Step 14, but with just a different data structure? That's because it's built using a different model!
Step 1-19¶
Limit the response to just the configured IP addresses:
https://csr1/restconf/data/ietf-interfaces:interfaces/interface=GigabitEthernet2/ietf-ip:ipv4/address/
Step 1-20¶
Let's look at one more data structure for an interface.
This time using the OpenConfig model for interfaces:
Response:
{
"openconfig-interfaces:interface": {
"name": "GigabitEthernet2",
"config": {
"name": "GigabitEthernet2",
"type": "iana-if-type:ethernetCsmacd",
"description": "Connects to csr3",
"enabled": true
},
"state": {
"name": "GigabitEthernet2",
"type": "iana-if-type:ethernetCsmacd",
"description": "Connects to csr3",
"enabled": true,
"ifindex": 2,
"admin-status": "UP",
"oper-status": "UP",
"last-change": "1636026002772000000",
"counters": {
"in-octets": "6954992",
"in-unicast-pkts": "20218",
"in-broadcast-pkts": "0",
"in-multicast-pkts": "0",
"in-discards": "0",
"in-errors": "0",
"in-unknown-protos": "0",
"in-fcs-errors": "0",
"out-octets": "6957110",
"out-unicast-pkts": "20225",
"out-broadcast-pkts": "0",
"out-multicast-pkts": "0",
"out-discards": "0",
"out-errors": "0",
"last-clear": "1636025887000000000"
}
},
"subinterfaces": {
"subinterface": [
{
"index": 0,
"config": {
"index": 0,
"description": "Connects to csr3",
"enabled": true
},
"state": {
"description": "Connects to csr3",
"enabled": true,
"name": "GigabitEthernet2",
"ifindex": 2,
"admin-status": "UP",
"oper-status": "UP",
"last-change": "1636026002772000000",
"counters": {
"in-octets": "6954992",
"in-unicast-pkts": "20218",
"in-broadcast-pkts": "0",
"in-multicast-pkts": "0",
"in-discards": "0",
"in-errors": "0",
"in-unknown-protos": "0",
"in-fcs-errors": "0",
"out-octets": "6957110",
"out-unicast-pkts": "20225",
"out-broadcast-pkts": "0",
"out-multicast-pkts": "0",
"out-discards": "0",
"out-errors": "0",
"last-clear": "1636025887000000000"
}
},
"openconfig-if-ip:ipv4": {
"addresses": {
"address": [
{
"ip": "10.1.13.1",
"config": {
"ip": "10.1.13.1",
"prefix-length": 24
},
"state": {
"ip": "10.1.13.1",
"prefix-length": 24
}
}
]
},
"proxy-arp": {
"state": {
"mode": "DISABLE"
}
},
"state": {
"counters": {
"in-pkts": "0",
"in-octets": "0",
"in-error-pkts": "0",
"in-forwarded-pkts": "0",
"in-forwarded-octets": "0",
"in-discarded-pkts": "0",
"out-pkts": "0",
"out-octets": "0",
"out-error-pkts": "0",
"out-forwarded-pkts": "0",
"out-forwarded-octets": "0",
"out-discarded-pkts": "0"
}
}
},
"openconfig-if-ip:ipv6": {
"config": {
"enabled": false
},
"state": {
"enabled": false,
"counters": {
"in-pkts": "0",
"in-octets": "0",
"in-error-pkts": "0",
"in-forwarded-pkts": "0",
"in-forwarded-octets": "0",
"in-discarded-pkts": "0",
"out-pkts": "0",
"out-octets": "0",
"out-error-pkts": "0",
"out-forwarded-pkts": "0",
"out-forwarded-octets": "0",
"out-discarded-pkts": "0"
}
}
}
}
]
},
"openconfig-if-ethernet:ethernet": {
"config": {
"mac-address": "52:54:00:14:b7:08",
"auto-negotiate": true,
"enable-flow-control": true
},
"state": {
"mac-address": "52:54:00:14:b7:08",
"auto-negotiate": true,
"port-speed": "openconfig-if-ethernet:SPEED_1GB",
"enable-flow-control": false,
"hw-mac-address": "52:54:00:14:b7:08",
"negotiated-duplex-mode": "FULL",
"negotiated-port-speed": "openconfig-if-ethernet:SPEED_1GB",
"counters": {
"in-mac-control-frames": "0",
"in-mac-pause-frames": "0",
"in-oversize-frames": "0",
"in-jabber-frames": "0",
"in-fragment-frames": "0",
"in-8021q-frames": "0",
"in-crc-errors": "0",
"out-mac-control-frames": "0",
"out-mac-pause-frames": "0",
"out-8021q-frames": "0"
}
}
}
}
}
Task 2 - Make Configuration Changes using the Native Model¶
In this task we want to manage the configuration of a loopback interface. When you start doing configuration via a RESTful API, it's usually easier to configure something manually via SSH, do a HTTP GET via Postman, and then push that object back via a PATCH/POST/PUT to ensure it's structured properly.
That's the methodology we'll use here.
Step 2-1¶
SSH to csr1 and add a Loopback200 interface with the following commands:
Verify it's configured properly.
csr1#show run interface loopback 200
Building configuration...
Current configuration : 68 bytes
!
interface Loopback200
ip address 10.200.200.1 255.255.255.0
end
csr1#
Step 2-2¶
Update the URL in Postman to query the configuration for Loopback200:
You should see this response:
{
"Cisco-IOS-XE-native:address": {
"primary": {
"address": "10.200.200.1",
"mask": "255.255.255.0"
}
}
}
Step 2-3¶
Change the HTTP Verb to PATCH.
As soon as you change the verb to PATCH, a new tab will be available where you put the "data" we can send to the device. This will be the "Body" tab next to the "Authorization" and "Headers" tabs.
Simply copy the response from Step 2 into to the "Body" tab (selecting the raw option from the dropdown).

Step 2-4¶
Click Send making a PATCH to device.
You should see a 204 No Content response.
This means it was successful.
Step 2-5¶
SSH back to the device.
Verify there has been no change in configuration.
csr1#show run interface loopback 200
Building configuration...
Current configuration : 68 bytes
!
interface Loopback200
ip address 10.200.200.1 255.255.255.0
end
csr1#
Step 2-6¶
Add several secondary interfaces to this interface so the updated configuration looks like this:
csr1#show run interface loopback 200
Building configuration...
Current configuration : 215 bytes
!
interface Loopback200
ip address 10.202.202.1 255.255.255.0 secondary
ip address 10.202.203.1 255.255.255.0 secondary
ip address 10.202.204.1 255.255.255.0 secondary
ip address 10.200.200.1 255.255.255.0
end
csr1#
Step 2-7¶
Re-issue the PATCH request.
You should still see 204 No content.
Even though you only have the primary interface in the "Body" there is no change. Remember, a PATCH is simply a "merge" operation and it's just ensuring that interface primary IP is there -- not affecting any of the secondary IPs.
Check the CLI of csr1 to confirm:
csr1#show run interface loopback 200
Building configuration...
Current configuration : 215 bytes
!
interface Loopback200
ip address 10.202.202.1 255.255.255.0 secondary
ip address 10.202.203.1 255.255.255.0 secondary
ip address 10.202.204.1 255.255.255.0 secondary
ip address 10.200.200.1 255.255.255.0
end
Step 2-8¶
Change the HTTP verb to GET and click Send.
You should see the updated interfaces in the JSON response:
{
"Cisco-IOS-XE-native:address": {
"secondary": [
{
"address": "10.202.202.1",
"mask": "255.255.255.0",
"secondary": [
null
]
},
{
"address": "10.202.203.1",
"mask": "255.255.255.0",
"secondary": [
null
]
},
{
"address": "10.202.204.1",
"mask": "255.255.255.0",
"secondary": [
null
]
}
],
"primary": {
"address": "10.200.200.1",
"mask": "255.255.255.0"
}
}
}
Step 2-9¶
Change to the verb to be an HTTP PUT. Verify the "Body" still has the following object:
{
"Cisco-IOS-XE-native:address": {
"primary": {
"address": "10.200.200.1",
"mask": "255.255.255.0"
}
}
}
Step 2-10¶
Click Send and confirm it was successful by checking the code: 204 No Content.
Step 2-11¶
SSH back into csr1 and verify the new configuration:
csr1#show run interface loopback 200
Building configuration...
Current configuration : 68 bytes
!
interface Loopback200
ip address 10.200.200.1 255.255.255.0
end
csr1#
Keep in mind a PUT ensures whatever you're pushing to the device is the ONLY configuration for that object. In this case, the object is Loopback200. It has great power with ensuring the configuration you're pushing to the device is the only configuration on the device (but could also cause damage if not used properly).