Network Automation

RESTCONF on Cisco IOS XE: GET, PATCH, and the YANG Path

RESTCONF GET and PATCH against ietf-interfaces with a 204 No Content success
In: Network Automation, Labs

If NETCONF is the powerful, ceremonious way to do model-driven management, RESTCONF is the friendly one. It exposes the same YANG models over ordinary HTTPS, with the REST verbs every engineer already half-knows: GET to read, PATCH to modify, PUT to replace, DELETE to remove. If you can use curl or Python's requests, you can drive RESTCONF, and that low barrier is exactly why it is the on-ramp to network automation for most people.

This article covers RESTCONF on Cisco IOS XE. It extends the Network Automation cluster guide.

A Note on the Lab

Being straight about this lab, as always. The automation host (a Debian VM running Python requests) is real and reaches the target Catalyst 8000v; the RESTCONF HTTPS port (443) is reachable from it, confirmed live. The device has restconf and ip http secure-server enabled and all the DMI processes running. However, on this virtual platform the DMI datastore backend (confd/ndbmand) did not finish initializing within the lab window, so nginx served an "unavailable" page rather than data, a known limitation of the virtualized DMI. The RESTCONF request URLs, headers, and response structure below are therefore documentation-style, drawn from Cisco's documented RESTCONF behaviour and clearly framed as such. The device configuration and reachability are real captures. Nothing here is presented as a lab capture that was not one.

RESTCONF Is REST Mapped Onto YANG

The elegant thing about RESTCONF (RFC 8040) is how directly it maps familiar REST concepts onto the YANG tree:

GETRead a resource (a subtree of the model). Like get-config in NETCONF.
PATCHMerge a change into a resource. Modify one field, leave the rest. The everyday edit.
PUTReplace a resource entirely with what you send. Idempotent: converges to the sent state.
DELETERemove a resource. POST creates a new one under a parent.

The URL is the path into the YANG tree. To address GigabitEthernet2 in the ietf-interfaces model, the URL walks the model exactly as the YANG tree nests:

https://<device>/restconf/data/ietf-interfaces:interfaces/interface=GigabitEthernet2
                            ^base^ ^----- model:container/list=key -----^

That maps directly onto the tree: ietf-interfaces module, interfaces container, interface list, keyed by GigabitEthernet2. Once you can read a YANG tree, you can build any RESTCONF URL, because the URL is the tree path.

Enabling It

R2(config)# restconf
R2(config)# ip http secure-server
R2(config)# crypto key generate rsa modulus 3072

restconf turns on the feature, ip http secure-server provides the HTTPS transport (RESTCONF is HTTPS-only, and rightly so, a plaintext config API would be indefensible), and the RSA key backs the TLS. RESTCONF is served by the same DMI process set as NETCONF; nginx is the front end on port 443. Confirm the stack the same way, with a real capture:

R2#show platform software yang-management process
nginx            : Running     <- serves RESTCONF on 443
confd            : Running
ndbmand          : Running     <- the datastore backend

If nginx is up but requests return an error page rather than data, the datastore backend (confd/ndbmand) has not finished initializing, exactly the condition this virtual lab hit. The port is reachable, the web server answers, but it has no data to serve yet.

Reading With GET

A GET against the interface resource, with the JSON accept header:

import requests
requests.packages.urllib3.disable_warnings()   # lab only; verify certs in production

url = "https://10.0.12.2/restconf/data/ietf-interfaces:interfaces/interface=GigabitEthernet2"
hdr = {"Accept": "application/yang-data+json"}

r = requests.get(url, headers=hdr, auth=("admin", "Cisco@123"), verify=False, timeout=15)
print(r.status_code)
print(r.json())
200 OK   (structure per the ietf-interfaces model)
{
  "ietf-interfaces:interface": {
    "name": "GigabitEthernet2",
    "type": "iana-if-type:ethernetCsmacd",
    "enabled": true,
    "ietf-ip:ipv4": {
      "address": [ { "ip": "10.0.12.2", "netmask": "255.255.255.252" } ]
    }
  }
}

The Accept: application/yang-data+json header is what asks for JSON (you can request XML instead). The response is a clean JSON object shaped by the model, ready to hand straight to the JSON handling every automation script does. The verify=False is a lab convenience and a production sin, as the API security article stresses.

Changing With PATCH

To modify one field (the description) without disturbing the rest, PATCH a small JSON body:

url = "https://10.0.12.2/restconf/data/ietf-interfaces:interfaces/interface=GigabitEthernet2"
hdr = {"Content-Type": "application/yang-data+json"}
body = { "ietf-interfaces:interface": {
    "name": "GigabitEthernet2",
    "description": "Configured via RESTCONF" } }

r = requests.patch(url, json=body, headers=hdr, auth=("admin","Cisco@123"), verify=False)
print(r.status_code)   # 204 on success

A successful PATCH returns 204 No Content: the change applied and there is nothing to return. This is the code that confuses newcomers (an empty body looks like failure but is success), and it is why the response codes article exists. PATCH merges, so only the fields you send change; PUT would replace the entire interface with your body, wiping anything you omitted.

The Response Codes You Will See

RESTCONF speaks standard HTTP status codes, and reading them is how you know what happened:

200 / 204GET succeeded with data / change succeeded, no content. Both are success.
401 / 403Bad credentials / not permitted. Re-auth or check your role.
404The YANG path does not exist. Usually a typo in the URL or a wrong interface name.
400Malformed body or a value the model rejects. The response body's error-message says what.

Handling these properly is the whole subject of the response codes article: check every code, never blindly retry a 4xx, back off on 429 and 5xx, and read the body for the real reason.

FAQ

What port does RESTCONF use?

HTTPS on 443 (RESTCONF is HTTPS-only). It is served by nginx, part of the same DMI process set as NETCONF.

Why does RESTCONF return an error page instead of data?

If nginx is running but you get an "unavailable" page, the datastore backend (confd/ndbmand) has not finished initializing. Check show platform software yang-management process. On virtual platforms this can take a long time or fail.

PATCH or PUT?

PATCH merges (changes only the fields you send). PUT replaces the entire resource with your body, removing anything you omit. Use PATCH for a targeted change; PUT when you mean to define the whole resource.

Why did my PATCH return 204 with no body?

204 No Content is success for a change: it worked, and there is nothing to return. An empty body here is expected, not a failure.

NETCONF or RESTCONF?

RESTCONF for simplicity and quick tasks (familiar REST verbs, easy tooling). NETCONF when you need datastores, locking, or transactional changes. Same YANG models, different transport.

Key Takeaways

  • RESTCONF maps REST verbs onto YANG over HTTPS (443): GET reads, PATCH merges, PUT replaces, DELETE removes.
  • The URL is the path into the YANG tree: /restconf/data/ietf-interfaces:interfaces/interface=GigabitEthernet2 walks module, container, list, key.
  • Enable with restconf + ip http secure-server + a 3072-bit key. It shares the DMI process set with NETCONF; nginx is the front end.
  • A GET returns model-shaped JSON (with Accept: application/yang-data+json); a successful PATCH returns 204 No Content (empty body = success).
  • Read the HTTP status codes: 200/204 success, 401/403 auth, 404 wrong path, 400 bad body. Never blindly retry a 4xx.
  • Honest platform note: on this virtual cat8000v the DMI datastore did not finish initializing, so nginx served an error page rather than data. Reachability and device config are real; the request/response structure is documentation-framed, never faked.

Next: NETCONF hands-on for the transactional alternative, or the Network Automation cluster guide.

Written by
More from Ping Labz
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Ping Labz.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.