A real-life situation
An auditor wants a list of every switch with its model, software version and serial number, by Friday. You could log in to each one and run show version, then copy the results into a spreadsheet. Or you could ask Catalyst Center, which already knows all of this, with one HTTPS request and get back clean, structured data a script can turn into a report in seconds.
That request is a REST API call, and the data comes back as JSON. Both are now basic tools for network engineers, and both are on the CCNA exam.
What a REST API is
An API (application programming interface) is a defined way for one program to ask another for data or actions. REST (representational state transfer) is a style of API built on HTTP, the same protocol web browsers use. A REST API has these properties:
- Client-server: the client (your script) asks; the server (the controller or device) answers.
- Stateless: each request stands alone and carries its own authentication. The server doesn't remember earlier requests.
- Cacheable: responses can say whether they may be cached and reused.
- Uniform interface: every thing you can work with is a resource with its own address, a URI, and you act on it with standard HTTP verbs.
A URI for the device list in Catalyst Center breaks down like this:
HTTP verbs and CRUD
Everything you do with data is one of four actions, called CRUD: create, read, update, delete. REST maps each one to an HTTP verb (also called a method):
| CRUD action | HTTP verb | Network example |
|---|---|---|
| Create | POST | Add a new VLAN, or ask for an auth token |
| Read | GET | List devices, read an interface's settings |
| Update | PUT (replace all) or PATCH (change some fields) | Change an interface description |
| Delete | DELETE | Remove a VLAN or a device from inventory |
HTTP status codes
Every response starts with a three-digit status code. The first digit tells you the class: 2xx success, 4xx the client (you) made a mistake, 5xx the server failed.
| Code | Meaning | When you see it |
|---|---|---|
200 OK | Success, data in the body | A GET that worked |
201 Created | A new resource was made | A POST that created something |
202 Accepted | Request taken, work still running | Catalyst Center tasks that take time; you check the task later |
204 No Content | Success, nothing to return | A PATCH, PUT or DELETE that worked |
400 Bad Request | The request is malformed | Broken JSON, a missing field |
401 Unauthorized | Not authenticated | Wrong password, missing or expired token |
403 Forbidden | Authenticated but not allowed | A read-only account trying to change something |
404 Not Found | No such resource | A typo in the URI |
500 Internal Server Error | The server failed | A bug or crash on the server side |
Authentication
- Basic authentication: the client sends
Authorization: Basicfollowed byusername:passwordencoded in Base64. Base64 is an encoding, not encryption, so this is only acceptable inside HTTPS. - Token-based: you log in once (often with Basic authentication) and receive a token, a long random string. You send the token with every later request. Catalyst Center uses an
X-Auth-Tokenheader; tokens expire after a set time (one hour by default). - API keys: a fixed secret string issued to an application, sent in a header.
- OAuth 2.0: a separate authorization server issues short-lived
Bearertokens. Common with cloud services.
Why it works that way
REST won because it reuses what already exists. HTTP and TLS run on every operating system, pass through firewalls on TCP 443, and have libraries in every programming language. Statelessness means a controller cluster can send each request to any node, since no node needs to remember your session. And JSON is easy for people to read and trivial for programs to parse, unlike the CLI output a script would otherwise have to scrape line by line.
How it works step by step
Here is the audit request from the course lab: the NetOps PC (10.10.0.50) talks to Catalyst Center (cc1.example.com, 10.10.0.10) on its northbound API.
If the token has expired, the GET returns 401 Unauthorized and the script must request a new token.
The raw HTTP request for the device list looks like this:
GET /dna/intent/api/v1/network-device?hostname=SW1 HTTP/1.1 Host: cc1.example.com Accept: application/json X-Auth-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...
GET: the verb: read only, no bodyAccept: asks for the response in JSONX-Auth-Token: the token from the login request
Reading JSON
JSON (JavaScript Object Notation) is a text format for structured data. It has only a few rules:
- An object is wrapped in curly braces
{ }and holds key/value pairs separated by commas. - A key is always a string in double quotes, followed by a colon:
"hostname": "SW1". - An array is an ordered list in square brackets
[ ]. - A value is a string (in double quotes), a number,
trueorfalse,null, an object or an array. - No comments, no single quotes, no comma after the last item. Spaces and line breaks don't matter.
This is the body Catalyst Center returns for SW1:
{
"response": [
{
"hostname": "SW1",
"managementIpAddress": "10.10.1.11",
"platformId": "C9300-24P",
"softwareVersion": "17.9.4",
"role": "ACCESS",
"reachabilityStatus": "Reachable",
"serialNumber": "FOC2211X0AB",
"upTime": "21 days, 4:12:09.00"
}
],
"version": "1.0"
}{ … }: the outer object has two keys: response and version"response": [ … ]: an array, here with one object per matching device (just SW1)"hostname": "SW1": a key/value pair whose value is a string
To get the software version, a script follows the path response → first item → softwareVersion (in Python: data["response"][0]["softwareVersion"]). A short illustrative Python script that makes the whole audit request:
import requests
BASE = "https://cc1.example.com"
# 1. Log in once with Basic auth and keep the token
token = requests.post(f"{BASE}/dna/system/api/v1/auth/token",
auth=("netops", "Str0ng-Secret")).json()["Token"]
# 2. Read the device list, sending the token in a header
devices = requests.get(f"{BASE}/dna/intent/api/v1/network-device",
headers={"X-Auth-Token": token}).json()["response"]
for d in devices:
print(d["hostname"], d["platformId"], d["softwareVersion"], d["serialNumber"])JSON is one of three data formats you should recognize:
| Format | Looks like | Where you meet it |
|---|---|---|
| JSON | {"vlan": 10} | REST APIs, RESTCONF, most controllers |
| XML | <vlan>10</vlan> | NETCONF, older APIs |
| YAML | vlan: 10 (indentation, no braces) | Ansible playbooks, config files |
How to configure RESTCONF on Cisco IOS XE
Controllers have their REST API on from the start. Cisco IOS XE devices can offer one too: RESTCONF, a standard (RFC 8040) REST API that reads and changes the device configuration using YANG data models. Here is R1 in the course lab.
username netadmin privilege 15 secret Str0ng-Secret
aaa new-model
aaa authentication login default local
aaa authorization exec default localRESTCONF needs a privilege 15 user and AAA with local authentication and exec authorization.
ip http secure-server
ip http authentication localStarts the HTTPS server (TCP 443) and checks logins against the local user database.
restconfGlobal config: turns on the RESTCONF API at https://<device>/restconf/.
The full configuration on R1:
hostname R1
username netadmin privilege 15 secret Str0ng-Secret
!
aaa new-model
aaa authentication login default local
aaa authorization exec default local
!
interface GigabitEthernet0/0/0
description Management segment
ip address 10.10.0.1 255.255.255.0
no shutdown
!
ip http secure-server
ip http authentication local
no ip http server
!
restconfno ip http server disables plain HTTP so credentials are never sent unencrypted.
How to verify it
Test with curl, a command-line HTTP client, from the NetOps PC. RESTCONF uses its own media type, application/yang-data+json. The / characters in an interface name must be URL-encoded as %2F.
netops$ curl -k -i -u netadmin:Str0ng-Secret -H "Accept: application/yang-data+json" https://r1.example.com/restconf/data/ietf-interfaces:interfaces/interface=GigabitEthernet0%2F0%2F0 HTTP/1.1 200 OK Content-Type: application/yang-data+json { "ietf-interfaces:interface": { "name": "GigabitEthernet0/0/0", "description": "Management segment", "type": "iana-if-type:ethernetCsmacd", "enabled": true, "ietf-ip:ipv4": { "address": [ { "ip": "10.10.0.1", "netmask": "255.255.255.0" } ] }, "ietf-ip:ipv6": { } } }
ietf-interfaces YANG model, so they look the same on any vendor that supports that model. (-k skips certificate checking because the lab router uses a self-signed certificate; don't do that in production.)Now change the description with PATCH, which updates only the fields sent:
netops$ curl -k -i -u netadmin:Str0ng-Secret -X PATCH -H "Content-Type: application/yang-data+json" -d '{"ietf-interfaces:interface": {"name": "GigabitEthernet0/0/0", "description": "To MGMT-SW"}}' https://r1.example.com/restconf/data/ietf-interfaces:interfaces/interface=GigabitEthernet0%2F0%2F0 HTTP/1.1 204 No Content
R1#show running-config interface GigabitEthernet0/0/0 Building configuration... Current configuration : 112 bytes ! interface GigabitEthernet0/0/0 description To MGMT-SW ip address 10.10.0.1 255.255.255.0 negotiation auto end
What goes wrong and how to troubleshoot it
| Result | Likely cause | Fix |
|---|---|---|
| Connection refused | ip http secure-server or restconf missing, or TCP 443 blocked | Check show running-config | include http|restconf and any ACL |
401 Unauthorized | Wrong credentials, user not privilege 15, AAA not set, or an expired token | Check the user and AAA lines; request a new token |
404 Not Found | Typo in the path, or / in the interface name not encoded | Use %2F; check the YANG model name |
400 Bad Request | Broken JSON: single quotes, trailing comma, missing brace | Run the body through a JSON validator |
415 Unsupported Media Type | Wrong Content-Type header | Use application/yang-data+json for RESTCONF |
Common mistakes
- Confusing 401 (who are you?) with 403 (I know who you are, but no).
- Using PUT when you meant PATCH, and wiping fields you didn't send.
- Thinking Base64 hides the password. It doesn't; HTTPS does.
- Writing JSON with single quotes or a comma after the last item.
- Forgetting the token on the second request: REST servers don't remember you.
💡 Exam tip: the CCNA asks you to describe REST APIs (authentication types, CRUD, HTTP verbs and data encoding) and to recognize the components of JSON. Expect to match CRUD actions to verbs, pick the meaning of a status code, count the objects or arrays in a JSON sample, or spot why a JSON snippet is invalid. Remember: objects use { }, arrays use [ ], keys are always double-quoted strings.
Key takeaways
- REST APIs use HTTP(S): client-server, stateless, resources identified by URIs.
- CRUD: POST creates, GET reads, PUT/PATCH update, DELETE deletes.
- 2xx success, 4xx client error (401 not authenticated, 403 not allowed, 404 not found), 5xx server error.
- Basic auth is Base64, not encryption; tokens are sent on every request.
- JSON: objects in braces, arrays in brackets, double-quoted keys, no comments.
- On IOS XE:
ip http secure-serverplusrestconfturns on a REST API.
Check yourself
A script needs to add a new VLAN through a controller's REST API. Which HTTP verb fits best?
A GET to Catalyst Center worked an hour ago. Now the same request returns 401. What is the most likely cause?
Which of these is valid JSON?
In {"response": [{"hostname": "SW1"}, {"hostname": "SW2"}]}, what is the value of response?
A PATCH to R1's RESTCONF API returns 204 No Content. What happened?