Skip to content
Back to skills

Central Classic

ASecurity

How to call the classic HPE Aruba Networking Central API gateway from Python: access and refresh tokens, base URL, read calls first, offset paging, rate limits, tests with saved answers.

  • 3 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added October 19, 2026
developmentpythongoshelltestinggitapi

Works with

  • cli
  • api
  • mcp

Security analysis

A100/100

Scanned October 19, 2026

npx -y skills add Choaterboater/casper --skill central-classic --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Central Classic?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Central Classic
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/choaterboater-central-classic/badge)](https://www.skillsdirectory.com/skills/choaterboater-central-classic)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: network-central-classic-api
description: >-
  How to call the classic HPE Aruba Networking Central API gateway from Python: access and
  refresh tokens, base URL, read calls first, offset paging, rate limits, tests with saved answers.
tags: [aruba central, classic central, pycentral, api gateway]
casper-skill:
  platform: central-classic
  triggers:
    strong: ["aruba central", "aruba networking central", "classic central", "central classic", "central api", "pycentral", "arubacentralbase", "apigw"]
    weak: ["central"]
    unless: ["new central"]
  frameworks: [central]
  version: 2
---
# HPE Aruba Networking Central (classic) API gateway

## When to use
Classic Central: paths like `monitoring/v2/aps` and `configuration/v2/groups`, an API gateway
base URL, a customer id, and access plus refresh tokens. New Central (GreenLake sign-in,
`network-monitoring/v1/...` paths) is a different API: use the network-central-api skill. If the
user is not sure which one they have, ask.

## Sign-in and tokens
- Values come from environment variables only: `CENTRAL_BASE_URL`, `CENTRAL_CLIENT_ID`,
  `CENTRAL_CLIENT_SECRET`, `CENTRAL_ACCESS_TOKEN`, `CENTRAL_REFRESH_TOKEN`. Never put them in code,
  never print them, never save them in samples.
- Make the token on Central's API Gateway page with the least rights the task needs. Only
  the product's own access check decides what a token may do.
- Access tokens expire (pycentral's docs say 2 hours). Refresh is a POST sign-in to
  `/oauth2/token` with `grant_type=refresh_token`. The answer holds a new access token and a new
  refresh token: keep the new one in a file outside the project (mode 600), never in git. How
  long a refresh token lasts: check the current docs.

```python
import os, time, httpx

BASE = os.environ["CENTRAL_BASE_URL"].rstrip("/")

def refresh(refresh_token: str) -> dict:  # sign-in POST
    r = httpx.post(f"{BASE}/oauth2/token", timeout=30, params={
        "client_id": os.environ["CENTRAL_CLIENT_ID"],
        "client_secret": os.environ["CENTRAL_CLIENT_SECRET"],
        "grant_type": "refresh_token", "refresh_token": refresh_token})
    r.raise_for_status()
    return r.json()  # access_token, refresh_token
```

## Read first
These calls ask for data. Run them first to learn the account:
- `GET /monitoring/v2/aps` (list key `aps`), `GET /monitoring/v1/switches` (`switches`),
  `GET /monitoring/v1/gateways` (`gateways`)
- `GET /configuration/v2/groups` - group names
- `GET /central/v2/sites` - sites
- `GET /platform/device_inventory/v1/devices` - inventory

```python
def get_all(c: httpx.Client, path: str, key: str, limit: int = 100) -> list[dict]:
    items, tries = [], 0
    while True:
        r = c.get(path, params={"offset": len(items), "limit": limit, "calculate_total": "true"})
        if r.status_code == 429 and tries < 5:
            tries += 1
            time.sleep(2 ** tries)
            continue
        if r.status_code >= 400:
            raise SystemExit(f"GET {path} failed: HTTP {r.status_code} {r.text[:200]}")
        body = r.json()
        page = body.get(key, [])
        items += page
        if not page or len(items) >= body.get("total", len(items)):
            return items

with httpx.Client(base_url=BASE, timeout=httpx.Timeout(30, connect=10),
                  headers={"Authorization": f"Bearer {os.environ['CENTRAL_ACCESS_TOKEN']}"}) as c:
    print(len(get_all(c, "/monitoring/v2/aps", "aps")), "APs")
```

With pycentral 2.x (in 1.x, import `ArubaCentralBase` from `pycentral.base`):

```python
from pycentral.classic.base import ArubaCentralBase
central = ArubaCentralBase(central_info={"base_url": BASE,
    "token": {"access_token": os.environ["CENTRAL_ACCESS_TOKEN"]}}, ssl_verify=True)
resp = central.command(apiMethod="GET", apiPath="/configuration/v2/groups",
                       apiParams={"limit": 20, "offset": 0})
if resp["code"] != 200:
    raise SystemExit(f"Central said {resp['code']}: {resp['msg']}")
```

## Changing things (Casper asks)
MCP: Casper's change box asks; don't ask again in chat. Else ask the user first; show the exact call.
Casper also asks before a shell command reaches a new host.
- First GET what you will change and save the answer to a file. Show the body you will send.
- Say what it reaches: config set on a group goes to every device in that group.
- WRITE: `POST /configuration/v1/devices/move` moves devices to another group. They take that
  group's config.
- WRITE: `POST /configuration/v2/groups` makes a group.
- WRITE: any `PUT`, `PATCH` or `DELETE` under `/configuration/` changes or removes config.
- To undo: send the saved config back, and ask the user again before you do.

## Paging and rate limits
- Lists use `offset` (items to skip) and `limit`. Add `calculate_total=true` to get `total`.
- The largest `limit` differs per endpoint (groups take small pages); check the current docs.
- Rate limits are per second and per day. Answers carry `X-RateLimit-Limit-day`,
  `X-RateLimit-Remaining-day` and `X-RateLimit-Remaining-second`. The numbers are in the current
  docs.
- On HTTP 429 wait and retry a few times with a longer wait. If the day limit is used up, stop
  and tell the user.

## Common traps
- Wrong base URL: each cluster has its own API gateway URL. Copy it from Central, do not guess.
- A new Central path (`network-monitoring/v1/devices`) on a classic base URL gives 404.
- Group vs device: a device-level setting or template variable can hide the group config.
- pycentral classic caches tokens in a `temp` folder by default; keep it out of git. It sets
  no request timeout and exits the program on a request error.
- pycentral's `command()` does not raise on HTTP errors; check `resp["code"]`.
- Never turn off TLS checks (`ssl_verify=False`, `verify=False`).

## Testing with saved sample data
- Tests make no live calls. Use `respx` for httpx (return a saved answer for
  `GET {BASE}/monitoring/v2/aps`), or `responses` for pycentral classic, which uses requests.
- Or pytest-recording (vcrpy) with `--record-mode=none` and
  `vcr_config = {"filter_headers": ["authorization"]}`, as `casper new mist-python` does.
- Record once by hand, only with the user's OK. Before saving, replace tokens, IDs, hostnames,
  serials and MAC addresses with placeholders.
- Sample data, not from a real network:
  `{"aps": [{"serial": "SAMPLE0001", "name": "ap-lab-1"}], "count": 1, "total": 1}`

## Public docs
- https://developer.arubanetworks.com/central/docs/api-oauth-access-token
- https://developer.arubanetworks.com/central/docs/api-gateway-creating-application-token
- https://developer.arubanetworks.com/central/docs/python-using-api-sdk
- https://github.com/aruba/pycentral

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.