IOS-XE RESTCONF list element operations
Combining API endpoints, payloads and methods

In this blog post, we will cover RESTCONF on IOS-XE, exploring supported HTTP methods and endpoint paths, along with example JSON payloads and the corresponding CLI configuration results. Understanding which combination of HTTP methods and endpoints paths are supported, as well as the appropriate JSON payloads, can be challenging. We can use the structure of the YANG model to get insights on how we can interact with each endpoint in the model.

The following error messages are commonly seen for unsupported combinations:

A lot of the configuration that we provision through the RESTCONF API are dealing with lists (corresponding to YANG lists and leaf-lists) and list elements (corresponding to YANG leafs and containers). To find the correct API endpoint path we need to identify which of these variations we are dealing with.

Examples of what a list may represent:

Examples of what a list element may represent:

Let's recap the basic HTTP methods that may be used to interact with device configuration via RESTCONF according to RFC 8040 section 4:

The examples below provides valid ways of configuring the Loopback9 interface on an IOS-XE router using the native YANG model.
The following "pyang -f tree" snippet shows the YANG model we will be using to construct the API endpoints and payload.

module: Cisco-IOS-XE-native

  +--rw native

     +--rw interface

     |  +--rw GigabitEthernet* [name]

     |  |  +--rw name                        string

     |  |  +--rw description?                string

     |  +--rw Loopback* [name]

     |  |  +--rw name                        string

     |  |  +--rw description?                string


Please note that when dealing with RESTCONF, the top-level element of the payload is always a JSON object with one single item. (Curly-bracket syntax; similar to Python dict)

The HTTP GET method

Example 1: Retrieving a container with multiple lists

The following RESTCONF endpoint is representing a container that holds multiple lists, including the lists for GigabitEthernet and Loopback interfaces.

The JSON key of the top-level payload item corresponds to the last URL path segment - this means the string after the last slash in the path: /Cisco-IOS-XE-native:native/interface in this case. 

The key is prepended with the Cisco-IOS-XE-native prefix when the payload is returned.

Because the endpoint relates to a YANG container, the value of the item is a JSON object. (Curly-bracket syntax; similar to Python dict)

GET /restconf/data/Cisco-IOS-XE-native:native/interface

1{

2   "Cisco-IOS-XE-native:interface": {

3.        "Loopback": [

4.           {

5.             "name": 1,

6.             "description": "Configured from CLI"

7.           },

8.           {

9.             "name": 9,

10.            "description": "Configured from CLI"

11.          }

12.       ],

13.        "GigabitEthernet": [

14.           {

15.             "name": 1,

16.             "description": "Configured from CLI"

17.           }

18.       ]

19.    }

20. }

Existing CLI configuration

! Config before RESTCONF operation

!

interface Loopback1
  description Configured from CLI
  no ip address

!

interface Loopback9
  description Configured from CLI
  no ip address

!

interface GigabitEthernet1
  description Configured from CLI
  no ip address

!

Example 2: Retrieving a list

The following RESTCONF endpoint is representing single list of all Loopback interfaces.

The JSON key of the top-level payload item corresponds to the last URL path segment - this means the string after the last slash in the path: /Cisco-IOS-XE-native:native/interface/Loopback in this case. 

The key is prepended with the Cisco-IOS-XE-native prefix when the payload is returned.

Because the endpoint relates to a YANG list, the value of the item is a JSON array. (Square-bracket syntax; similar to Python list)

GET /restconf/data/Cisco-IOS-XE-native:native/interface/Loopback

1.  {

2.     "Cisco-IOS-XE-native:Loopback": [

3.        {

4.          "name": 1,

5.          "description": "Configured from CLI"

6.        },

7.        {

8.          "name": 9,

9.          "description": "Configured from CLI"

10.       }

11.    ]

12. }

Existing CLI configuration

! Config before RESTCONF operation

!

interface Loopback1
  description Configured from CLI
  no ip address

!

interface Loopback9
  description Configured from CLI
  no ip address

!

interface GigabitEthernet1
  description Configured from CLI
  no ip address

!

Example 3: Retrieving a single list item

The following RESTCONF endpoint is representing a single Loopback interface.

The JSON key of the top-level payload item corresponds to the last URL path segment - this means the string after the last slash in the path: /Cisco-IOS-XE-native:native/interface/Loopback=9 in this case. 

The key is prepended with the Cisco-IOS-XE-native prefix when the payload is returned.

The equal-sign is used to filter the list and return only one single item that matches the list key. The key of the Loopback interface list in the Cisco-IOS-XE-native YANG model, is the "name" leaf.

Because the endpoint relates to a YANG container, the value of the item is a JSON object. (Curly-bracket syntax; similar to Python dict)

GET /restconf/data/Cisco-IOS-XE-native:native/interface/Loopback=9

1{

2   "Cisco-IOS-XE-native:Loopback": {

3       "name": 9,

4       "description": "Configured from CLI"

5   }

6}

Existing CLI configuration

! Config before RESTCONF operation

!

interface Loopback9
  description Configured from CLI
  no ip address

!

interface Loopback9
  description Configured from CLI
  no ip address
!

interface GigabitEthernet1
  description Configured from CLI
  no ip address

!

The HTTP POST method

Example 4: Posting new configuration to a container

When posting new configuration to a container, the key of the top-level payload item must be the identifier of the YANG leaf we want to add the configuration to. In this case it is the description leaf.

For POST operations within a container, the API endpoint must be the parent container of the configuration payload: /Cisco-IOS-XE-native:native/interface/Loopback=9/description

Because we are adding data to one or more YANG leaf(s), the value of the payload item is a JSON object. (Curly-bracket syntax; similar to Python dict)

POST /restconf/data/Cisco-IOS-XE-native:native/interface/Loopback=9

1{

2   "description": "Configured from RESTCONF"
3}

CLI configuration result

! Config before RESTCONF operation

!

interface Loopback9
  no ip address



!

! Config after RESTCONF operation

interface Loopback9
  description Configured from RESTCONF
  no ip address

Example 5: Posting new items to lists

When posting new configuration to lists, the key of the top-level payload item must be the identifier of the YANG list we want to add one or more entries to. In this case it is the Loopback list.

For POST operations on a list, the API endpoint must be the parent container of the list we want to add new configuration items to: /Cisco-IOS-XE-native:native/interface/Loopback

Because we are adding item(s) to a YANG list, the value of the payload item is a JSON array. (Square-bracket syntax; similar to Python list)

POST /restconf/data/Cisco-IOS-XE-native:native/interface

1.  {

2.     "Loopback": [

3.         {

4.             "name": 9,

5.             "description": "Configured from RESTCONF"

6.         }

7.     ]
8.  }

CLI configuration result

! Config before RESTCONF operation

! (No loopback configured)



!

! Config after RESTCONF operation

interface Loopback9
  description Configured from RESTCONF
  no ip address

Explanation of "POST on list must be on list element" error message

The common RESTCONF error message "POST on list must be on list element" actually means:

"POST on list must use the parent element API endpoint path and include the list identifier as the top-level payload element key."

It may seem a bit confusing, so I created a color-coded example on how this could look for an endpoint and top-level payload:

POST /restconf/data/Cisco-IOS-XE-native:native/interface

1.  {

2.     "Loopback": [

3.         {

4.             ...

The HTTP PUT method

Example 6: Replacing configuration of a single list item

When replacing configuration of a single list item, the key of the top-level payload item must be the name of the YANG list we want to replace an entries inside. In this case it is the Loopback list.

For PUT operations on list items, the API endpoint is the container itself and we need to supply a filter to interact with one specific item.

The equal-sign is used to filter the list and return only one single item that matches the list key. The list key of interfaces in Cisco-IOS-XE-native YANG model is the "name" leaf.

Because we are replacing an item in a YANG list, the value of the payload item is a JSON array. (Square-bracket syntax; similar to Python list)

In this case the Loopback9 exists with a description and an IPv4 address before the RESTCONF operation. Because the PUT payload only includes a description for the interface all other configuration for the interface wil be removed.

PUT /restconf/data/Cisco-IOS-XE-native:native/interface/Loopback=9

1.  {

2.     "Loopback": [

3.         {

4.             "name": 9,

5.             "description": "Configured from RESTCONF"

6.         }

7.     ]
8.  }

CLI configuration result

! Config before RESTCONF operation
!

interface Loopback1

  description Configured from CLI
  ip address 1.1.1.1 255.255.255.255
!
interface Loopback9

  description Configured from CLI
  ip address 9.9.9.9 255.255.255.255


! Config after RESTCONF operation
!
interface Loopback1

  description Configured from CLI
  ip address 1.1.1.1 255.255.255.255
!

interface Loopback9

  description Configured from RESTCONF
  no ip address

Example 7: Replacing or adding configuration with the PUT method

If the configuration items in the payload does not exist as a leaf or container before the PUT operation, it will be created dynamically.

The exception to this rule are list API endpoints such as /Cisco-IOS-XE-native:native/interface/Loopback, because the PUT method is not allowed on such internal lists - it would result in HTTP error 405: Method Not Allowed. Please note that this error may not return any payload! So if you happen to use "curl" for testing, you wont see the error unless you add the -v parameter for verbose output.

To ensure a specific configuration element it is possible to use the PUT method on the specific API endpoint. The configuration will then be wither replaced or created. 

PUT /restconf/data/Cisco-IOS-XE-native:native/interface/Loopback=9/description

1. {

2.     "description": "Configured from RESTCONF"

3. }

CLI configuration result

! Config before RESTCONF operation
!
interface Loopback9

  no ip address


! Config after RESTCONF operation
!
interface Loopback9

  no ip address
  description Configured from RESTCONF

PUT /restconf/data/Cisco-IOS-XE-native:native/interface/Loopback=9/description

1. {

2.     "description": "Configured from RESTCONF"

3. }

CLI configuration result

! Config before RESTCONF operation
!
interface Loopback9

  no ip address

  description Configured from CLI


! Config after RESTCONF operation
!
interface Loopback9

  no ip address
  description Configured from RESTCONF

The HTTP PATCH method

Example 8: Merging new list items with existing configuration

When merging configuration using the PATCH method, the key of the top-level payload item matches both the identifier of YANG node and the last path segment in the API endpoint: /Cisco-IOS-XE-native:native/interface

We do not need to specify any filtering at the API endpoint level because the key of YANG list items is present inside the payload. The list key of interfaces in Cisco-IOS-XE-native YANG model is the "name" leaf.

A shortcut to finding the correct JSON payload structure for the RESTCONF operation is to GET the API endpoint first, and evaluate the response.

The PATCH method never removes configuration. If the payload doesn't match existing configuration it will be appended to what is already there.

PATCH /restconf/data/Cisco-IOS-XE-native:native/interface

1{

2   "interface": {

3       "Loopback": [

4           {

5               "name": 9,

6               "description": "Configured from RESTCONF"

7           }

8       ]

9   }

10. }

CLI configuration result

! Config before RESTCONF operation
!

interface Loopback1

  description Configured from CLI
  ip address 1.1.1.1 255.255.255.255
!


! Config after RESTCONF operation
!
interface Loopback1

  description Configured from CLI
  ip address 1.1.1.1 255.255.255.255
!

interface Loopback9

  description Configured from RESTCONF
  no ip address

Example 9: Merging configuration of an existing  list item

In this case the Loopback9 exists with a description and an IPv4 address before the RESTCONF operation. Because the PATCH payload only includes a description for the interface, this is the only thing that will be changed.

PATCH /restconf/data/Cisco-IOS-XE-native:native/interface

1.  {

2.     "interface": {

3.         "Loopback": [

4.             {

5.                 "name": 9,

6.                 "description": "Configured from RESTCONF"

7.             }

8.         ]

9.     }

10. }

CLI configuration result

! Config before RESTCONF operation
!

interface Loopback9

  description Configured from CLI
  ip address 9.9.9.9 255.255.255.255


! Config after RESTCONF operation
!

interface Loopback9

  description Configured from RESTCONF
  ip address 9.9.9.9 255.255.255.255

Example 10: Merging configuration for new and existing list items

It is possible to PATCH configuration on any level of the YANG tree and with any API endpoint, as long as the last path segment of the API endpoint matches the top-level item of the payload:

PATCH /restconf/data/Cisco-IOS-XE-native:native/interface/Loopback

1.  {

2.     "Loopback": [

3.         {

5.             "name": 9,

4.             "description": "Configured from RESTCONF"

5.         },

3.         {

5.             "name": 10,

4.             "description": "Configured from RESTCONF"

5.         }

6.     ]
7.  }

CLI configuration result

! Config before RESTCONF operation
!

interface Loopback9

  description Configured from CLI
  ip address 9.9.9.9 255.255.255.255


! Config after RESTCONF operation
!

interface Loopback9

  description Configured from RESTCONF
  ip address 9.9.9.9 255.255.255.255

!

interface Loopback10

  description Configured from RESTCONF
  no ip address

Example 11: Merging list item configuration using endpoint key filter

It is possible to PATCH configuration of one specific list item without specifying the list item key inside the JSON payload, if it is added API endpoint as a filter instead:

PATCH /restconf/data/Cisco-IOS-XE-native:native/interface/Loopback=9

1.  {

2.     "Loopback": [

3.         {

4.             "description": "Configured from RESTCONF"

5.         }

6.     ]
7.  }

CLI configuration result

! Config before RESTCONF operation
!

interface Loopback9

  description Configured from CLI
  ip address 9.9.9.9 255.255.255.255


! Config after RESTCONF operation
!

interface Loopback9

  description Configured from RESTCONF
  ip address 9.9.9.9 255.255.255.255

Summary

To find the correct combination of RESTCONF API endpoint and JSON payload, you must know wether you are dealing with a list or list item in the YANG model.

For PUT and PATCH operations, the last URL path segment (the string after the very last slash) must match to the top-level item key.

For POST operations, the last URL path segment (the string after the very last slash) must correspond to the parent of the top-level item.

Finding the correct combination of method, endpoint and payload isn't easy, but looking at examples and being aware of the presence and limitations of lists does help.

Written by:
Andreas Baekdahl
Cisco Certified DevNet Expert #20220006
3xCCIE and CCDE