NetApp ONTAP
REST API
Storage Automation
Field Guide

Managing ONTAP Using the REST API: An Engineer’s Field Guide

17 min read

The ticket says: “report the size and utilisation of every volume on the cluster, weekly.” You could click through System Manager and copy numbers into a spreadsheet every Friday — or you could ask the cluster itself, in one line, and let a script do Fridays forever. That second path runs through the ONTAP REST API, and learning it is the single highest-leverage skill jump a storage engineer can make. This guide takes you from zero to creating volumes programmatically, with every concept illustrated by a diagram, a real request, and a real response.

What this guide covers

The fundamentals of the ONTAP REST API for engineers who have used System Manager or the ONTAP CLI but never touched the API: what REST means in practice, how to authenticate, how to read responses and status codes, and worked examples — listing volumes, creating one, resizing it, and tracking the background job — in curl and Python. Applies to ONTAP 9.6 and later, where the REST API is the standard management interface.

Audience: storage and infrastructure engineers, NOC analysts moving into automation, and anyone who inherits a NetApp estate and a pile of repetitive tickets. Assumes you can open a terminal; assumes no programming background.

The restaurant analogy: how to think about an API

Before any syntax, build the picture. You are seated at a restaurant. You want food. You do not walk into the kitchen, find a pan, and start cooking — you would be thrown out, and rightly so. Instead, you read the menu, give your order to the waiter, and the waiter carries it to the kitchen. The kitchen does the work. The waiter returns with your dish — or with a polite explanation of why you cannot have it.

That is an API. The waiter is a defined, disciplined intermediary between you and a system you are not allowed to touch directly. You ask in an agreed format; you receive answers in an agreed format; what happens inside the kitchen is not your problem.

Figure 01 · The restaurant: you never enter the kitchen

Youhungry, at the tableThe waitertakes orders, brings dishesThe kitchendoes the actual workTHE MENUeverything you may orderyour orderyour dish (or an explanation)you never cross this line
The waiter is the API: a defined intermediary with an agreed way of asking and an agreed way of answering. The red line is the point — customers do not cook, and clients do not reach into the storage operating system.

Now relabel every actor and the whole of ONTAP REST falls into place. Your script is the customer. The cluster is the kitchen. The REST API is the waiter. The menu — the complete list of what you may ask for and exactly how to phrase it — is the cluster’s own documentation page at /docs/api. And the order ticket the kitchen pins up for dishes that take a while? Hold that thought — it becomes the job UUID when we get to asynchronous operations.

Figure 02 · The same picture, relabeled for ONTAP

AT THE RESTAURANTON THE CLUSTERYou, the customeryour script, curl, Python, AnsibleThe menuhttps://<cluster>/docs/apiYour order, phrased properlyHTTP request: verb + URI + JSON bodyThe waiterthe ONTAP REST APIThe kitchenthe ONTAP clusterThe dish that arrivesJSON response + status codeThe order ticket for slow dishesthe job UUID (status 202)
Every restaurant role has an exact ONTAP counterpart. When any concept later in this guide feels abstract, come back to this table — the analogy holds all the way down, including the order ticket.

What a REST API is — in plain language

An API (application programming interface) is a way for software to ask other software to do things — the waiter, formalised. A REST API is a specific, very common style of API that works over HTTPS, the same protocol your browser uses. That detail matters more than it sounds: it means anything that can make a web request — curl, Python, PowerShell, Ansible, a monitoring platform — can manage your storage, with no agent and no special client software.

Every NetApp ONTAP cluster running 9.6 or later ships with a REST API built in, listening on the same cluster management address you already use for System Manager. In fact, System Manager itself is a REST API client — every button you click in the UI becomes one of the API calls you are about to learn.

Three building blocks make up every exchange, and each maps straight back to the restaurant:

  • The URI — which dish you are pointing at on the menu. /api/storage/volumes means “the volumes.” The noun.
  • The HTTP method — what you want done with it. GET reads, POST creates, PATCH modifies, DELETE removes. The verb.
  • JSON — the agreed phrasing for orders and answers. Human-readable "key": "value" pairs, nothing more exotic than that.

If you remember one sentence from this section: a REST call is a verb applied to a noun, with details in JSON.

Figure 03 · The four verbs, at the table and on the cluster

GETRead — change nothing“What are today’s specials?”GET /api/storage/volumesPOSTCreate something new“One margherita, please.”POST /api/storage/volumesPATCHModify what exists“Make that a large instead.”PATCH /api/storage/volumes/{uuid}DELETERemove it“Cancel my order.”DELETE /api/storage/volumes/{uuid}
Four verbs cover nearly everything you will ever ask a cluster to do. GET is safe to experiment with endlessly — it is the only verb that cannot change anything.

Anatomy of a call

Here is a complete request, labeled piece by piece. Do not run it yet — read it:

curl -X GET "https://cluster1.corp.example.com/api/storage/volumes" \
     -u apireader:SuperSecret1! \
     -H "accept: application/json"

#  -X GET .............. the verb: read, change nothing
#  https://cluster1.... the cluster management address (same one System Manager uses)
#  /api/storage/volumes the resource: all volumes (a "collection")
#  -u user:password .... basic authentication - an ONTAP account, checked by RBAC
#  -H accept: .......... "answer me in JSON, please"

The URI reads like a postal address for data — each segment narrows the destination:

Figure 04 · A URI is an address, read left to right

https://cluster1.corp.example.com/api/storage/volumes/9b2f4e11-… (optional)the restaurant’s street addressthe front door of the APIthe section of the menuthe dish family (collection)one specific dish (UUID)
Reading a URI left to right: server, API root, category, resource collection, and — when you append a UUID — one specific object. Leave the UUID off and you are addressing the whole collection.

ONTAP groups its resources into categories you will recognise from System Manager’s menu: storage (disks, aggregates, volumes, LUNs, snapshots, qtrees, quotas), svm, networking, protocols (NFS, SMB, S3, SAN), cluster (nodes, jobs, licensing, schedules), security, and snapmirror, among others. Guessing a path from this pattern works surprisingly often — and when it does not, the cluster documents itself: browse to https://<cluster-mgmt>/docs/api and ONTAP serves the menu — a complete, interactive reference for every endpoint, generated from the exact software version you are running. Bookmark it; it is the authoritative answer to “what fields does this take?”

When the request needs to carry information — a POST creating something — it travels in four layers, like a properly written order slip:

Figure 05 · Anatomy of a write request: the order slip

THE VERBPOST“I am ordering, not asking”THE URI/api/storage/volumes“from the volumes menu”HEADERSauthorization: Basic …content-type: application/json“table 12, and I speak JSON”BODY (JSON){“name”: “vol_apitest”,“svm”: { “name”: “svm1” },“size”: “100GB”}“the order details:what, for whom, how big”
A write request dissected. The verb states intent, the URI names the target, headers identify you and declare the format, and the JSON body carries the actual order details. GET requests are the same slip with no body.

Your first call: ask the cluster who it is

The safest possible first call is a read against the cluster itself:

curl -X GET "https://cluster1.corp.example.com/api/cluster" \
     -u apireader:SuperSecret1! -H "accept: application/json"

{
  "name": "cluster1",
  "uuid": "5f7f9a4e-2c1d-11ee-a7b2-00a098d39e12",
  "version": {
    "full": "NetApp Release 9.14.1P2",
    "generation": 9,
    "major": 14,
    "minor": 1
  },
  "management_interfaces": [
    { "name": "cluster_mgmt", "ip": { "address": "192.168.0.101" } }
  ]
}

That JSON response is worth a slow read. Notice the uuid: every object in ONTAP — cluster, volume, SVM, LUN — has one, and it is how the API names individual things unambiguously. Names can be changed and reused; UUIDs cannot. You will spend a lot of your API life looking up a UUID with one call and using it in the next.

WUC field note · the certificate warning

On a lab cluster, curl will refuse the connection because the cluster presents a self-signed TLS certificate. The internet will tell you to add -k (or verify=False in Python) to skip verification. In a lab, fine. In production, that habit disables the protection that proves you are talking to your cluster and not something pretending to be it — while your admin credentials are in the request. The production-grade fix takes five minutes: export the cluster certificate, hand it to curl with --cacert or to Python via verify="/path/to/cluster1.pem", and never type -k on a production fabric again.

Authentication: who you are, and what you may touch

Every request carries credentials — there is no “session login” like the CLI. The straightforward method is HTTP basic authentication: an ONTAP username and password sent (TLS-encrypted) with each call, exactly what -u does in the examples above. ONTAP also supports certificate-based authentication, where a client certificate replaces the password entirely — the right choice for unattended scripts once you graduate from experimenting.

What that account is allowed to do is governed by the same role-based access control (RBAC) as the CLI and System Manager. In restaurant terms: identification gets you a table, but the wine list still depends on whose name the reservation is under. This is your safety net, and you should use it from day one: create a dedicated read-only account for learning, and you become physically unable to break anything while you explore.

cluster1::> security login create -user-or-group-name apireader \
    -application http -authentication-method password -role readonly

One account, http application, built-in readonly role. Every GET in this guide works under it; every POST, PATCH, and DELETE is refused with a 403 — which, while you are learning, is a feature.

Reading the cluster’s answers: HTTP status codes

Every response begins with a three-digit status code — the waiter’s tone of voice before you even look at the plate. Reading them well separates an engineer who troubleshoots from one who retries the same failing call.

Figure 06 · Status codes as the waiter’s replies

2xx“Your order, as requested.”200here it is201freshly made, done202still cooking — takethis ticket (job UUID)4xx“A problem with your order.”400I cannot read this order401I cannot confirm who you are403not available to your table404that is not on the menu409clashes with an existing orderfix the request, then retry5xx“A problem in the kitchen.”500internal error —not your faultcheck EMS logs, retry cautiously
First digit first: 2xx means proceed, 4xx means the problem is in your request, 5xx means the problem is in the kitchen. The 401-versus-403 distinction — identity versus permission — is the first question in any access ticket.
Code Meaning What it tells you to do
200 Success (no new object created) Read your data and carry on
201 Object created The create finished synchronously — done
202 Accepted — background job started The work is not done yet; poll the job (next section)
400 Bad request Your JSON has a wrong value, a typo’d field, or a missing required field — reread the request, not the cluster
401 Authentication failed Wrong username or password — identity problem
403 Authorisation failed Right user, insufficient role — permission problem
404 Resource does not exist Wrong UUID or wrong path — look the resource up again
409 Conflict Something already exists or is in the way (duplicate name, busy resource)
500 Internal server error The cluster’s problem, not your request — check EMS logs, retry cautiously

Collections, UUIDs, and asking for only what you need

A URI without a UUID names a collection (“all volumes”); with a UUID appended it names one object (a singleton). Collection responses arrive in a standard envelope — a records array plus a num_records count:

Figure 07 · Collection vs singleton — the menu page vs one dish

GET /api/storage/volumesthe collection — a whole menu page{ “name”: “svm1_root”, “uuid”: “1d7e…” }{ “name”: “vol_finance”, “uuid”: “9b2f…” }{ “name”: “vol_hr”, “uuid”: “c411…” }“records”: [ … ], “num_records”: 3GET /api/storage/volumes/9b2f…the singleton — one specific dish“name”: “vol_finance”“size”: 107374182400“svm”: { “name”: “svm1” }no envelope — the object itself?fields=name,size → “only tell me the name and the size”
No UUID = the whole collection wrapped in a records envelope; UUID appended = exactly one object. The fields parameter trims either response to only the attributes you asked for.
curl -s "https://cluster1/api/storage/volumes?fields=name,size,svm.name" \
     -u apireader:SuperSecret1!

{
  "records": [
    { "uuid": "1d7e8c2a-...", "name": "svm1_root", "size": 1073741824,
      "svm": { "name": "svm1" } },
    { "uuid": "9b2f4e11-...", "name": "vol_finance", "size": 107374182400,
      "svm": { "name": "svm1" } }
  ],
  "num_records": 2
}

Two details in that call do a lot of work. First, ?fields=name,size,svm.name — by default ONTAP returns only a minimal set of attributes, so you ask for what you need (or fields=* for everything, at a cost in response size). Second, sizes come back in bytes — 107374182400 is 100 GiB. Your scripts will divide by 1073741824 more often than you expect.

Collections also filter directly in the query string. Every volume in one SVM larger than 50 GiB, sorted by size, biggest first:

/api/storage/volumes?svm.name=svm1&size=>53687091200&order_by=size%20desc

That one-line filter replaces a page of script logic — let the cluster do the filtering and your code stays small. The same pattern powers monitoring: /api/cluster/metrics?interval=1h and the per-volume /api/storage/volumes/{uuid}/metrics endpoints return IOPS, throughput, and latency series ready for dashboards — the data layer behind infrastructure performance monitoring.

Making your first change: creating a volume

Reads behind you, RBAC understood — time to place a real order. Switch to an account with an appropriate role, and tell the cluster the three things a volume needs: a name, a home SVM, and a size (the aggregate is optional — ONTAP picks one if you stay silent):

curl -X POST "https://cluster1/api/storage/volumes" \
     -u apiadmin:EvenMoreSecret2@ \
     -H "accept: application/json" -H "content-type: application/json" \
     -d '{
           "name": "vol_apitest",
           "svm":  { "name": "svm1" },
           "size": "100GB",
           "comment": "created via REST - training"
         }'

HTTP/1.1 202 Accepted
{
  "job": {
    "uuid": "f1a2b3c4-2d1e-11ee-a7b2-00a098d39e12",
    "_links": { "self": { "href": "/api/cluster/jobs/f1a2b3c4-..." } }
  }
}

Note what did not happen: the cluster did not say “volume created.” It said 202 — “order accepted, the kitchen is on it” — and handed you an order ticket: the job UUID. That is the asynchronous pattern, and it is the part of ONTAP REST that catches every newcomer.

Asynchronous jobs: the two-second rule and the order ticket

Think about how the restaurant actually works. Ask the waiter for the specials and the answer comes back immediately — no kitchen involved. Order a glass of water and it arrives in seconds. But order the forty-minute roast and the waiter does not stand frozen at your table while it cooks — you get a ticket on the table, the kitchen works, and you check back. ONTAP makes exactly this decision, with a threshold of about two seconds:

Figure 08 · Synchronous vs asynchronous — water vs the roast

SYNCHRONOUS — the glass of water (finishes < 2 s)clientclusterGET /api/storage/volumes200 + the data, immediatelyASYNCHRONOUS — the slow roast (takes > 2 s)clientclusterkeeps cookingPOST /api/storage/volumes202 + the order ticket: job uuid f1a2…GET /api/cluster/jobs/f1a2… (repeat until done)“state”: “queued” → “running” → “success”
Reads and fast writes return finished. Anything slower returns 202 with a job UUID — the order ticket — and the client checks back. A script that never checks the ticket has no idea whether dinner was ever served.

The discipline: after any 202, poll the job until it reaches a terminal state.

curl -s "https://cluster1/api/cluster/jobs/f1a2b3c4-2d1e-11ee-a7b2-00a098d39e12" \
     -u apiadmin:EvenMoreSecret2@

{ "uuid": "f1a2b3c4-...", "description": "POST /api/storage/volumes",
  "state": "success", "end_time": "2026-06-11T14:09:21+00:00" }

state walks through queuedrunningsuccess (or failure, with a message explaining why). A script that fires a POST and exits without polling has not deployed anything — it has expressed a wish. Check the job, then verify the resource exists with a GET. That fire-poll-verify rhythm is the habit that separates automation you can trust from automation you hope about.

Modifying and deleting: PATCH and DELETE

Changes to an existing object go to its singleton URI — UUID required — with only the fields you are changing in the body. Growing our volume to 200 GB:

curl -X PATCH "https://cluster1/api/storage/volumes/9b2f4e11-..." \
     -u apiadmin:EvenMoreSecret2@ -H "content-type: application/json" \
     -d '{ "size": "200GB" }'

Deletion is the same shape with no body: DELETE /api/storage/volumes/9b2f4e11-.... Treat DELETE with CLI-grade respect — it is a one-line, irreversible operation, which is exactly why your learning account should not be able to run it, and why production scripts that delete things belong under change control with a human approving the list of UUIDs first.

WUC field note · the API mirrors the CLI you already know

Engineers coming from the ONTAP CLI sometimes treat the API as foreign territory. It is the same territory with different signposts: volume show is GET /api/storage/volumes, volume modify is a PATCH, vserver delete is a DELETE on /api/svm/svms/{uuid}. When you know the CLI command but not the endpoint, the mapping table below — and the cluster’s own /docs/api — bridge the gap in seconds. Everything you know about ONTAP objects still applies; only the syntax changed.

The same calls from Python

curl proves concepts; scripts do Fridays. The requests library is the standard way Python speaks HTTP, and the translation from curl is nearly mechanical:

import requests

CLUSTER = "https://cluster1.corp.example.com"
AUTH    = ("apireader", "SuperSecret1!")
CA      = "/etc/ssl/certs/cluster1.pem"   # exported cluster cert - no verify=False

r = requests.get(
    f"{CLUSTER}/api/storage/volumes",
    params={"fields": "name,size,svm.name"},
    auth=AUTH, verify=CA,
)
r.raise_for_status()                       # turns 4xx/5xx into a visible error

for vol in r.json()["records"]:
    gib = vol["size"] / 1024**3
    print(f'{vol["svm"]["name"]:>10}  {vol["name"]:<24} {gib:8.1f} GiB')

Twelve lines, and the Friday spreadsheet writes itself. When your scripts grow past one file, NetApp’s official Python client library (pip install netapp-ontap) wraps the raw HTTP in storage-shaped objects and handles the order tickets for you:

from netapp_ontap import HostConnection
from netapp_ontap.resources import Volume

with HostConnection("cluster1.corp.example.com",
                    username="apiadmin", password="EvenMoreSecret2@",
                    verify="/etc/ssl/certs/cluster1.pem"):
    vol = Volume(name="vol_apitest2", svm={"name": "svm1"}, size="100GB")
    vol.post(poll=True)        # poll=True waits for the async job - the 202 dance, handled
    print(vol.uuid, "created")

PowerShell engineers get the identical experience through Invoke-RestMethod — same URIs, same JSON, same status codes. The protocol knowledge transfers untouched across every tool.

The CLI-to-REST translation table

You know this CLI command REST equivalent Verb
volume show /api/storage/volumes GET (collection)
volume show vol1 /api/storage/volumes/{uuid} GET (singleton)
volume create /api/storage/volumes POST
volume modify /api/storage/volumes/{uuid} PATCH
aggr create /api/storage/aggregates POST
vserver show /api/svm/svms GET
vserver delete /api/svm/svms/{uuid} DELETE
snapshot create /api/storage/volumes/{uuid}/snapshots POST
statistics show /api/cluster/metrics and per-object /metrics GET

Beyond raw calls: where Ansible fits

Once the API makes sense, the next rung is declarative automation. Ansible’s netapp.ontap collection wraps these same REST endpoints in idempotent modules: instead of scripting “create the volume, poll the job,” a playbook states “a 100 GB volume named vol_apitest exists on svm1” and Ansible makes it so — creating it if absent, leaving it untouched if present, reporting what changed either way. Idempotency is what turns scripts into infrastructure you can re-run safely, and it is the natural second course after this one. The protocol fluency you built here is exactly what lets you debug a playbook when a module fails: under every Ansible error is one of the status codes you can now read.

Figure 09 · The skills ladder — every rung uses the one below it

System Managerclick by clickONTAP CLIvolume create …REST APIcurl · Python · PowerShellAnsibledeclare the end stateyou are climbing to here — and the rungs above and belowit (System Manager, Ansible) are REST API clients underneath
The automation ladder. REST fluency is the load-bearing rung: the UI below it and the playbooks above it both speak REST to the cluster on your behalf.

This skills ladder — UI to CLI to REST to declarative automation — is the same path our engineers apply across post-OEM storage maintenance estates, where one team manages NetApp alongside Dell EMC and IBM platforms and the API is what makes multi-vendor scale survivable.

Six beginner pitfalls, so you can skip them

  1. Treating 202 as “done.” It is the order ticket, not the dish. Poll the job. Verify the resource. Every time.
  2. Confusing 401 with 403. 401 is who-you-are (credentials); 403 is what-you-may (role). They route to different fixes and different ticket queues.
  3. Forgetting fields=. The default response is deliberately minimal; if an attribute you expected is “missing,” you probably did not ask for it.
  4. Hand-counting bytes. Sizes are bytes in responses; write the GiB conversion once, in one function, and reuse it.
  5. Normalising -k / verify=False. Lab habit, production liability. Export the cluster certificate and verify properly.
  6. Learning with an admin account. A read-only RBAC account makes your exploration phase consequence-free. Privilege comes later, scoped to what the script actually does.

Work these examples against a lab cluster — NetApp’s Lab on Demand, an ONTAP Select instance, or a simulator — and within an afternoon the API stops being an abstraction and becomes what it actually is: the fastest tool in your kit for every question that starts with “across all our volumes…” And when the estate grows past what afternoons can cover — or the NetApp gear ages past OEM support while the workloads stay — that is what WUC engineering and managed services are for.

Frequently asked questions

Q01

Does the ONTAP REST API replace ZAPI?

Yes. REST is the strategic successor to ONTAPI (ZAPI), the proprietary interface used before ONTAP 9.6. New automation should target REST exclusively; NetApp publishes an ONTAPI-to-REST mapping to migrate existing ZAPI scripts, and ONTAPI is on a deprecation path in current releases.

Q02

Which ONTAP versions support the REST API?

ONTAP 9.6 and later carry the full REST API as the standard management interface, and every subsequent release expands endpoint coverage. The cluster documents exactly what your version supports at https://<cluster-mgmt>/docs/api — generated from the running software, so it never lies about availability.

Q03

How do I authenticate to the ONTAP REST API?

Two methods: HTTP basic authentication — an ONTAP account and password sent TLS-encrypted with each request — or certificate-based authentication, where a client certificate replaces the password entirely. Authorization is governed by the same RBAC roles as the CLI; start with a read-only account and scope privilege to what each script actually does.

Q04

Is the ONTAP REST API enabled by default?

Yes. On ONTAP 9.6 and later the REST API listens on the cluster management LIF out of the box — the same address System Manager uses, because System Manager is itself a REST client. There is no separate enable step; access control happens through accounts and RBAC roles, not a feature switch.

Q05

Can I manage volumes through the REST API?

Fully. /api/storage/volumes supports the complete lifecycle — create, resize, modify, snapshot, and delete — which is exactly what this guide demonstrates end to end. The same pattern extends to aggregates, LUNs, SVMs, exports, and quotas: one verb, one URI, details in JSON.

Need help automating NetApp infrastructure?

The patterns in this guide scale from one script to an estate — and that is where WUC works daily: as a NetApp maintenance provider for AFF and FAS inside and outside OEM support, an ONTAP automation consultant, a storage modernization partner, and a managed storage services provider across multi-OEM data centers.

Prefer to read first? See post-OEM storage maintenance and managed services.

References

  1. NetApp. ONTAP Automation Documentation. The official hub for REST API, workflows, and client libraries.
  2. NetApp. Your First ONTAP REST API Call. The vendor’s own getting-started walk-through.
  3. NetApp. RBAC Security for the REST API. Role-based access control as it applies to API accounts.
  4. NetApp. netapp-ontap Python Client Library. PyPI package and documentation.
About WUC Engineering
Storage and infrastructure engineers at WUC Technologies operating NetApp ONTAP estates — AFF and FAS, on OEM support and beyond it — alongside the Cisco MDS fabrics they ride on, under SLA-backed multi-OEM maintenance engagements across enterprise data centers. Authorized Dell & Cisco partner.

Find our field guides faster in Google. Add WUC Technologies as a preferred source and our engineering guides carry a “preferred” badge in your Search results, AI Overviews, and AI Mode.

Add as preferred source →