PONGo_ios/MCMS_API.md
2026-05-31 14:11:29 +02:00

758 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Ciena MCMS 6.2 REST API — Implementer's Field Guide
Reference for building an HTTP client against a Ciena MicroClimate
Management System (MCMS) 6.2 PON Manager. Distilled from the official
dev guide (`323-1961-306`) plus empirical findings against a working
deployment with GNXS / Tibit MicroPlug ONUs on Interos Everest 5.x
firmware.
Language-agnostic — every quirk listed here was hit in production. If
you skip the gotchas in §3, you will lose an afternoon to one of them.
---
## 1. Connection basics
- **Base URL.** The root of the PON Manager web UI (e.g.
`https://mcms.example.net`). All REST paths are prefixed with `/api`.
- **Transport.** HTTPS. Internal deployments commonly use self-signed
certificates on private IPs — your client needs an opt-in to skip
TLS verification for that case (do **not** disable globally).
- **HTTP version.** HTTP/1.1 works. The server also negotiates HTTP/2
but the dev-guide examples are 1.1 and the only behavioural
difference observed is irrelevant to clients.
- **Path normalisation.** The dev guide writes paths as
`/v1/users/authenticate/` — the real wire path is
`/api/v1/users/authenticate/`. Normalise once in your client.
- **API versions.** Both `/api/v1/...` and `/api/v3/...` exist and serve
different endpoints. **Use whichever the dev guide lists for that
resource — they are not interchangeable.** See §4 endpoint table.
- **Trailing slashes.** Required. `/api/v1/onus/configs/<id>/` works;
`/api/v1/onus/configs/<id>` does not (Django's `APPEND_SLASH` is
on, but a few endpoints 500 instead of redirecting).
---
## 2. Login & session
MCMS uses Django session cookies + a CSRF token. Sessions do **not**
auto-expire on idle — log out explicitly when done.
### 2.1 Authenticate
```
POST /api/v1/users/authenticate/
Content-Type: application/json
{ "data": { "email": "user@example.net", "password": "..." } }
```
Response on success (`HTTP 200`):
```json
{ "status": "success" }
```
Set-Cookie headers carry the session. On observed MCMS 6.2 builds:
```
Set-Cookie: __Host-csrftoken=<token>; Path=/; Secure; SameSite=Lax
Set-Cookie: __Host-sessionid=<id>; Path=/; Secure; HttpOnly; SameSite=Lax
Set-Cookie: __Host-sessionexpire=<epoch>; Path=/; Secure; SameSite=Lax
```
**The `__Host-` prefix is significant.** Some MCMS builds (older
ones, mostly) use bare `csrftoken` / `sessionid`. Your cookie reader
should accept either prefix.
→ Some build variants accept an unwrapped body too:
`{"email": ..., "password": ...}` with no `data` envelope. If wrapped
returns HTTP 400, retry unwrapped.
### 2.2 Subsequent requests
Every authenticated request must send:
```
Cookie: __Host-csrftoken=<token>; __Host-sessionid=<id>; ...
X-CSRFToken: <token> # the value from __Host-csrftoken
Referer: <baseURL>/ # MCMS rejects POST/PUT/DELETE without this
User-Agent: <anything> # see §3.1 — must not be empty
Accept: application/json
```
For PUT/POST/PATCH also:
```
Content-Type: application/json
Content-Length: <bytes>
```
### 2.3 (Optional) Database selection
If the deployment manages multiple databases:
```
PUT /api/v1/databases/selection/
{ "data": "<database_id>" }
```
Most deployments only have one and skip this step.
### 2.4 Logout
```
GET /api/v1/users/logout/
```
Best-effort — don't fail your client if this errors.
---
## 3. The gotchas (read this section twice)
### 3.1 User-Agent header is REQUIRED
If you don't send a `User-Agent`, some MCMS middleware dereferences
`HTTP_USER_AGENT` without a null check and returns **HTTP 500** with
body:
```json
{"status": "fail", "details": {"message": "Internal server error. See server logs for details."}}
```
Reproduce: `curl -A '' https://mcms/api/v3/onus/configs/`. Any non-empty
string works (`PonFleetClient/1.0`, etc.).
**For iOS/Swift**: `URLSession` sets a default User-Agent automatically
(e.g. `<bundle>/1 CFNetwork/... Darwin/...`), so this is unlikely to
bite you there — but if you ever set a custom `URLRequest` with
`setValue(nil, forHTTPHeaderField: "User-Agent")`, the 500s will
return.
### 3.2 CSRF token field name
The token cookie is `__Host-csrftoken` on new builds, bare `csrftoken`
on older. The header you send back is always `X-CSRFToken` (no
prefix, capital `T` in `Token`). Both Django case-fold the header
name, so casing is fine — but the body name is exact.
### 3.3 Pagination: use `next`, NOT `skip`
`/api/v3/onus/configs/?skip=N` has been observed returning HTTP 500.
The working approach uses the last document's `_id` as a cursor:
```
GET /api/v3/onus/configs/?limit=100
→ returns 100 docs, the last with _id = "X"
GET /api/v3/onus/configs/?limit=100&next=X
→ returns the next 100, EXCLUDING all _ids <= X
```
Loop until you get a short page (< limit) or an empty page. Most list
endpoints accept this pattern.
### 3.4 Page size 100 is the safe default
`?limit=1000` against `/api/v3/onus/configs/` on a ~1500-ONU fleet
times out at the Apache front-end before Django logs the request.
Full `ONU-CFG` documents are ~30 KB each, so 1000 × 30 KB = 30 MB,
which exceeds the proxy timeout. **100 per page keeps each response
~3 MB** and well under any default proxy budget.
This applies to all bulk list endpoints (configs, states, OLT states).
### 3.5 Request body envelope: `{"data": payload}`
PUT/POST/PATCH bodies are wrapped:
```json
{ "data": { "_id": "...", "ONU": { ... } } }
```
Response envelope is similar:
```json
{ "status": "success", "data": { ... } }
{ "status": "fail", "details": { "message": "..." } }
{ "status": "warning", "data": { ... }, "details": { ... } }
```
`"warning"` is treated as success by MCMS (the write happened) but
indicates a schema mismatch you should log.
### 3.6 PUT is full-document replace, NOT patch
`PUT /api/v1/onus/configs/<id>/` replaces the entire `ONU-CFG`
document. You **must** GET the current doc, mutate fields, and PUT
the entire result. There is no PATCH equivalent that works reliably
on MCMS 6.2.
Forgetting this turns into "I PUT'd just the FW Bank fields and now
the ONU has no service config" the dev guide is explicit but easy
to skim past.
### 3.7 Timestamp format
MCMS emits and accepts timestamps as:
```
"YYYY-MM-DD HH:MM:SS" # second precision
"YYYY-MM-DD HH:MM:SS.ffffff" # microsecond precision (for STATE.Time)
```
Always **UTC**, always with a **literal space** between date and time
(not ISO-8601 `T`). Used on:
- `ONU-STATE.Time`
- `OLT-STATE.Time`
- Alarm timestamps
- `AUTO-TASK-CFG.Task["Scheduled Start Time"]`
- `start-time` / `end-time` URL params on stats endpoints
**For Swift**: `ISO8601DateFormatter` will NOT parse this. Use a
plain `DateFormatter` with:
```swift
let fmt = DateFormatter()
fmt.timeZone = TimeZone(identifier: "UTC")
fmt.dateFormat = "yyyy-MM-dd HH:mm:ss.SSSSSS" // or "yyyy-MM-dd HH:mm:ss"
fmt.locale = Locale(identifier: "en_US_POSIX")
```
The `en_US_POSIX` locale matters without it, devices set to a
24-hour-format locale will still parse fine but devices set to
12-hour-format locales will fail. POSIX locale forces parse rules.
### 3.8 Server-side query/projection filters are brittle
The dev guide documents `query`, `projection`, `sort`, `limit`,
`skip`, `next`, `distinct` URL parameters. In practice:
- **`query`** (Mongo-style filter) works for simple equality on
bare field names. Anything with **spaces in field names**, quoted
values with non-ASCII characters, or projection paths that don't
exist on every document version is unreliable you'll get either
empty results or 400s.
- **`projection`** is *very* picky about paths. Better to fetch full
docs and project client-side.
**Recommended approach**: load the full fleet (paginated by `next`)
and filter client-side. The data volume is fine for any device with
enough RAM to hold a few thousand 30 KB documents.
### 3.9 URL encoding
Use percent-encoding (`encodeURIComponent` equivalent). MCMS does NOT
accept `+` for spaces in URL parameters use `%20`.
This matters for query params like `start-time` which carry literal
spaces in the timestamp.
### 3.10 ONU IDs
The `_id` field of an ONU document is:
- The **serial number** for XGS-PON / GPON ONUs (e.g. `GNXS05057fee`)
- The **MAC address** for 10G-EPON ONUs
Treat as opaque strings. They're URL-safe in observed deployments
but always `encodeURIComponent` to be defensive.
### 3.11 Registration status lives on OLT-STATE, not ONU-STATE
This is non-obvious. The 9 registration buckets live as arrays on the
OLT's state document:
```json
{
"_id": "<OLT MAC>",
"ONU States": {
"Registered": ["GNXS01", "GNXS02", ...],
"Deregistered": ["GNXS09", ...],
"Dying Gasp": [...],
"Disabled": [...],
"Disallowed Admin": [...],
"Disallowed Error": [...],
"Disallowed Reg ID": [...],
"Unspecified": [...],
"Unprovisioned": [...]
}
}
```
To resolve "what's the status of ONU X?", you walk every OLT-STATE
doc, find which bucket contains X, and that's your answer. See
Procedure 2 in the dev guide.
An ONU should appear in exactly one bucket on exactly one OLT. In the
rare duplicate case, prefer the non-`Registered` bucket that's the
interesting signal.
### 3.12 FEC counters live on ONU-STATE.STATS, not on `/onus/stats/`
`GET /api/v1/onus/stats/<id>/?start-time=...` returns historical PM
samples (time-series). For the *current* FEC counters and optical
levels, read the live `ONU-STATE` document:
```
GET /api/v3/onus/states/<id>/
→ data.STATS["ONU-PON"]["RX Pre-FEC BER"]
→ data.STATS["ONU-PON"]["RX Post-FEC BER"]
→ data.STATS["ONU-PON"]["RX Optical Level"] (dBm)
→ data.STATS["ONU-PON"]["TX Optical Level"] (dBm)
→ data.STATS["OLT-PON"]["RX Pre-FEC BER"]
→ data.STATS["OLT-PON"]["RX Post-FEC BER"]
```
The MCMS Web UI's `/api/onu/summary` helper returns the same data
under `data.state_collection.STATS.*` (wrapper shape).
### 3.13 Bulk endpoints don't return everything in one shot
Even on a small fleet, MCMS may silently truncate large list
responses. Always paginate don't trust `?limit=large_number` to be
authoritative.
### 3.14 Verbose error logging matters
When MCMS 500s, the response body sometimes contains useful detail
(missing required param, schema validation failure, etc.). Always log
both the response headers and the FULL body on non-2xx during
development most "mysterious 500" cases resolve to a one-line hint
in the body.
---
## 4. Endpoints used by the fleet-upgrade app
| Method | Path | Purpose |
|---|---|---|
| `POST` | `/api/v1/users/authenticate/` | Login |
| `GET` | `/api/v1/users/logout/` | Logout |
| `PUT` | `/api/v1/databases/selection/` | (Optional) DB selection |
| `GET` | `/api/v3/onus/configs/` | List ONU configs (paginated) |
| `GET` | `/api/v1/onus/configs/<id>/` | Get single ONU config |
| `PUT` | `/api/v1/onus/configs/<id>/` | Replace ONU config (full doc) |
| `DELETE` | `/api/v1/onus/configs/<id>/` | Delete ONU (Procedure 43) |
| `GET` | `/api/v3/onus/states/` | List ONU states (paginated) |
| `GET` | `/api/v3/onus/states/<id>/` | Get single ONU state |
| `DELETE` | `/api/v1/onus/states/<id>/` | Delete ONU state (best-effort) |
| `GET` | `/api/v3/olts/states/` | List OLT states (paginated; registration) |
| `GET` | `/api/v1/files/onu-firmware/` | List uploaded firmware files |
| `POST` | `/api/v1/files/onu-firmware/<name>/` | Upload firmware |
| `PUT` | `/api/v3/tasks/configs/<id>/` | Create bulk upgrade task (Procedure 8) |
| `GET` | `/api/v3/tasks/configs/<id>/` | Poll bulk task config |
| `GET` | `/api/v1/onus/<id>/upgrade/status/` | (Build-dependent) per-ONU status |
### Other endpoints documented but not (yet) used
| Method | Path | Notes |
|---|---|---|
| `GET` | `/api/v1/onus/stats/<id>/?start-time=...` | Time-series ONU PM data |
| `GET` | `/api/v1/olts/stats/<id>/?start-time=...` | OLT PM data |
| `GET` | `/api/v1/onus/logs/<id>/?start-time=...` | Per-ONU syslog |
| `GET` | `/api/v1/olts/logs/<id>/?start-time=...` | Per-OLT syslog |
| `GET` | `/api/v3/tasks/states/<id>/` | Bulk task progress (good follow-up) |
| `GET` | `/api/v1/onus/automation/states/` | PON automation state |
| `GET` | `/api/v1/onus/cpe-states/` | ONU CPE states (downstream devices) |
---
## 5. Data shapes (observed)
These are not formally specified in the dev guide for MCMS 6.2 they
were extracted from live traffic.
### 5.1 ONU-CFG
```jsonc
{
"_id": "GNXS05057fee",
"ONU": {
"Name": "Operator-set label",
"Address": "Street, city",
"PON Mode": "GPON", // GPON | XGS-PON | 10G-EPON
"Equipment ID": "FT-XGS2110",
"FW Bank Files": ["...bin", "...bin"], // [slot 0, slot 1]
"FW Bank Versions": ["EV05110R", "EV05100R"],
"FW Bank Ptr": 0, // 0 | 1 | 65535 (unset)
"ONU-ALARM-CFG": "Default",
"Vendor": "GNXS",
"Serial Number": "GNXS05057fee",
"Host MAC Address": "58:00:32:05:7f:ee",
// ...many more fields - preserve all of them when PUTing
},
"OLT-Service 0": { ... }, // service config slots
"OLT-Service 1": { ... },
// ...
}
```
**Critical**: when mutating for an upgrade, only change `ONU["FW Bank
Files"]`, `ONU["FW Bank Versions"]`, and `ONU["FW Bank Ptr"]`. Pass
through everything else unchanged.
### 5.2 ONU-STATE
```jsonc
{
"_id": "GNXS05057fee",
"Time": "2026-05-04 21:51:57.394127", // UTC, last update
"ONU": {
"Equipment ID": "FT-XGS2110",
"FW Bank Files": [...],
"FW Bank Versions": [...],
"FW Bank Ptr": 0,
"FW Version": "EV05110R", // resolved active version
"FW Upgrade Status": {
"Bank": 0,
"Status": "Success", // status string
"Progress": 100, // percent
"Upgrade Time": "2026-03-18 17:12:43.093893",
"Total Blocks": 482915,
"Sent Blocks": 482915,
"Failures": 0,
// ...
},
"PON Mode": "GPON",
"Online Time": "2026-03-18 17:13:42.285965",
// ...
},
"STATS": {
"ONU-PON": {
"RX Pre-FEC BER": 22388041291, // cumulative since reset
"RX Post-FEC BER": 22379111198,
"RX Optical Level": -17.544, // dBm
"TX Optical Level": 5.532 // dBm
},
"OLT-PON": {
"RX Pre-FEC BER": 0, // upstream view
"RX Post-FEC BER": 0,
"TX Optical Level": 5.6,
"RX Optical Level": -18.3
},
"ONU-EnhancedFecPmHistData-32769": { // NOT the same as the BER fields above
"uncorrectable_code_words": 1829, // (these are codeword counts,
"corrected_bytes": 181, // not bit-error-rate ratios)
"corrected_code_words": 181
},
// ...many more
},
"Alarm": {
"0-EMERG": [], "1-ALERT": [], "2-CRIT": [],
"3-ERROR": [], "4-WARNING": [], "5-NOTICE": [],
"6-INFO": [], "7-DEBUG": []
}
}
```
### 5.3 OLT-STATE (relevant subset)
```jsonc
{
"_id": "<OLT MAC>",
"Time": "2026-05-04 21:51:57.394127",
"ONU States": {
"Registered": ["onu1", "onu2", ...],
"Deregistered": [...],
"Dying Gasp": [...],
"Disabled": [...],
"Disallowed Admin": [...],
"Disallowed Error": [...],
"Disallowed Reg ID": [...],
"Unspecified": [...],
"Unprovisioned": [...]
}
// ...
}
```
### 5.4 AUTO-TASK-CFG (bulk firmware task, Procedure 8)
```jsonc
{
"_id": "<your-task-id>", // unique, caller-generated
"Task": {
"Device Type": "ONU",
"Operation": "Firmware Upgrade",
"Scheduled Start Time": "2026-05-12 03:00:00" // UTC space format
},
"Task Details": {
"Devices": ["GNXS01", "GNXS02", ...], // ONU IDs (serial / MAC)
"ONU": {
"FW Bank Ptr": 1, // target slot (single value!)
"FW Bank Files": { "0": "old.bin", "1": "new.bin" },
"FW Bank Versions": { "0": "EV05110R", "1": "EV05120R" }
}
}
}
```
PUT to `/api/v3/tasks/configs/<task-id>/`. Note: `FW Bank Files` and
`FW Bank Versions` here are **objects keyed by slot index as strings**
(`"0"`, `"1"`), not arrays. This is different from the `ONU-CFG`
shape where the same fields are arrays almost certainly a Mongo
serialisation quirk. Match it as-is.
**Single bank per task.** Because `FW Bank Ptr` accepts one slot, if
your selection spans ONUs with different active banks, bucket them
by target slot and create one task per bucket.
### 5.5 Firmware file entry (from `/api/v1/files/onu-firmware/`)
```jsonc
{
"_id": "...",
"filename": "Interos-Everest-5.12.0-R-EV05120R.bin",
"metadata": {
"Compatible Manufacturer": "TIBITCOM",
"Compatible Model": ["MicroPlug ONU"],
"Version": "EV05120R"
},
// GridFS metadata...
}
```
To upload:
```
POST /api/v1/files/onu-firmware/<filename>/
{
"data": {
"file": "<base64 binary contents>",
"metadata": {
"Compatible Manufacturer": "TIBITCOM",
"Compatible Model": ["MicroPlug ONU"],
"Version": "EV05120R"
}
}
}
```
---
## 6. Firmware upgrade flow
Two methods documented:
### 6.1 Procedure 7 — per-ONU PUT
For each ONU:
1. `GET /api/v1/onus/configs/<id>/` full doc.
2. Compute the inactive bank (see §6.3).
3. Set:
- `ONU["FW Bank Files"][writeSlot] = "<filename>"`
- `ONU["FW Bank Versions"][writeSlot] = "<version>"`
- `ONU["FW Bank Ptr"] = writeSlot` (this initiates the download)
4. `PUT /api/v1/onus/configs/<id>/` with the entire mutated document.
Pros: see errors per ONU live. Cons: slow for large fleets, you own
retries.
### 6.2 Procedure 8 — bulk task (recommended)
Build one `AUTO-TASK-CFG` per (target slot) bucket:
```
PUT /api/v3/tasks/configs/<task-id>/
(body shape in §5.4)
```
MCMS owns the rollout: scheduled start, retries, pacing.
Monitor progress (build permitting):
```
GET /api/v3/tasks/states/<task-id>/
```
Or just poll the ONU configs and watch `FW Bank Versions` /
`FW Bank Ptr` flip.
### 6.3 Inactive-bank selection
`FW Bank Ptr` identifies the active bank (0, 1, or 65535 = unset).
**Always write to the inactive bank** so you don't blow away the
running image:
| Current `FW Bank Ptr` | Write slot | Why |
|---|---|---|
| 0 | 1 | preserve active |
| 1 | 0 | preserve active |
| 65535 (unset) | 1 | matches Procedure 7 example; slot 0 stays as factory fallback |
MCMS flips `FW Bank Ptr` to the new slot when the download completes.
The ONU reboots into the new image on its next reboot.
---
## 7. FEC + optical interpretation
### 7.1 Four FEC counters
Per the user guide green-LED criteria (`323-1961-302` p149):
| Field | Path | Green | Red |
|---|---|---|---|
| ONU Pre-FEC BER | `STATS["ONU-PON"]["RX Pre-FEC BER"]` | 0 | (informational) |
| ONU Post-FEC BER | `STATS["ONU-PON"]["RX Post-FEC BER"]` | 0 | > 0 |
| OLT Pre-FEC BER | `STATS["OLT-PON"]["RX Pre-FEC BER"]` | 0 | (informational) |
| OLT Post-FEC BER | `STATS["OLT-PON"]["RX Post-FEC BER"]` | 0 | > 0 |
Note: the field name is "BER" but the magnitudes are big integers
(cumulative error byte counts since reset), not ratios in [0,1].
Treat them as counts.
### 7.2 Health bucket rules
Suggested 4-state reduction:
- **OK**: all four counters present and == 0.
- **Pre-FEC errors**: any pre > 0, all post == 0. (Marginal link;
FEC is correcting.)
- **Post-FEC errors**: any post > 0. (Uncorrected bits reaching the
user.)
- **Buggy (pre ≈ post)**: ONU pre > 0 AND post > 0 AND
`post / pre >= 0.95`. Real FEC reduces errors; if post is within
5% of pre, the firmware is mirroring the counter. Observed on
Interos Everest ONUs.
### 7.3 Optical levels
```
STATS["ONU-PON"]["RX Optical Level"] // ONU receive power, dBm
STATS["ONU-PON"]["TX Optical Level"] // ONU transmit power, dBm
```
User guide thresholds:
| | Green | Red |
|---|---|---|
| RX | ≥ 30 dBm | < 30 dBm |
| TX | ≥ 3 dBm | < 3 dBm |
Operators usually want a margin warning band e.g. yellow when RX
is between 28 and 30 dBm.
---
## 8. iOS-specific notes
### 8.1 Library stack suggestions
- **HTTP**: `URLSession` is fine. The features you need are standard
cookie storage, custom headers, and the option to bypass cert
validation. Don't reach for Alamofire just for this.
- **Cookies**: `HTTPCookieStorage` handles `__Host-` prefixes
correctly. Get the CSRF value via:
```swift
HTTPCookieStorage.shared.cookies(for: baseURL)?
.first { $0.name == "__Host-csrftoken" || $0.name == "csrftoken" }?.value
```
- **Self-signed certs**: Implement
`URLSessionDelegate.urlSession(_:didReceive:completionHandler:)`
and accept `serverTrust` only when the user has explicitly toggled
"accept self-signed" for the configured host. Never default-on.
- **JSON**: `JSONSerialization` is simpler than `Codable` for the
envelope pattern (`{status, data, details}`) because the `data`
payload is heterogeneous. `Codable` works if you model each
endpoint individually.
### 8.2 Concurrency
The fleet load is N HTTPS round-trips for per-ONU state (the bulk
endpoint is the optimisation but the per-ID fallback may also be
needed). Use Swift Concurrency (`TaskGroup`) with a concurrency cap
of 810 to avoid stampeding the server. The desktop client uses 5
for deletes and 8 for state fetches.
### 8.3 Background uploads
Firmware `.bin` files are 1050 MB base64-encoded. If you implement
uploads:
- Don't block the main thread.
- Consider `URLSession` background configuration so an upload can
survive an app suspend.
- The upload is a single POST; no chunking required.
### 8.4 Storing the session
For UX: persist the base URL and username in `UserDefaults`, never
the password. Re-prompt for password on launch.
The session cookie itself goes in the per-session cookie storage
and is automatically discarded — don't try to persist it.
### 8.5 Date handling
See §3.7. Default `DateFormatter` with `en_US_POSIX` locale + UTC
timezone, format `"yyyy-MM-dd HH:mm:ss.SSSSSS"` (microseconds) or
`"yyyy-MM-dd HH:mm:ss"` (seconds). Try the microsecond format
first, fall back to second if it fails.
### 8.6 Cell-vs-Wi-Fi
MCMS APIs are typically reachable only from the operator's internal
network. Test on cellular: many internal hosts won't be reachable,
and your error UI needs to communicate that clearly.
### 8.7 Self-signed cert prompt
Make this a first-class onboarding step. The lab MCMS at
`https://mcms.lab.svorka.net/` uses a self-signed cert, and any
auto-rejection will silently break login.
---
## 9. Procedures referenced in the dev guide
| # | Title | Notes |
|---|---|---|
| 2 | Determining ONU registration status | OLT-STATE["ONU States"] buckets |
| 7 | Per-ONU firmware upgrade | Full-doc PUT to ONU-CFG |
| 8 | Bulk firmware upgrade | AUTO-TASK-CFG via PUT |
| 38 | Resetting bit error rate values | Names the four FEC fields |
| 43 | Deleting an ONU | DELETE on ONU-CFG |
(Page numbers vary by document revision; cite by procedure number.)
---
## 10. Quick implementation checklist for a new client
A correct first POST-login GET against `/api/v3/onus/configs/?limit=1`
returning HTTP 200 means you've got the eight critical pieces right:
- [ ] HTTPS reachable (with cert exception if needed)
- [ ] Path prefix `/api` added
- [ ] User-Agent set to non-empty value
- [ ] Cookie jar storing `__Host-sessionid` + `__Host-csrftoken`
- [ ] `X-CSRFToken` header pulled from `__Host-csrftoken` cookie value
- [ ] `Referer` header set to base URL
- [ ] `Accept: application/json`
- [ ] Trailing slash on the path
Add for write operations:
- [ ] `Content-Type: application/json`
- [ ] Body wrapped: `{"data": ...}`
- [ ] Full-document PUT (never partial)
Add for list endpoints:
- [ ] Page size ≤ 100
- [ ] `next` cursor (not `skip`)
- [ ] Loop until short page
Once those land, the API is comfortable to work with — the hard parts
are upfront.
---
*Compiled from `323-1961-306` (REST API dev guide), `323-1961-302`
(PON Manager User Guide), and empirical testing against MCMS 6.2 with
Interos Everest 5.11/5.12 firmware on GNXS / Tibit MicroPlug ONUs.*