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:
get-config in NETCONF.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 3072restconf 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 backendIf 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 successA 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:
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=GigabitEthernet2walks module, container, list, key. - Enable with
restconf+ip http secure-server+ a 3072-bit key. It shares the DMI process set with NETCONF;nginxis 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.