128 lines
5.3 KiB
Markdown
128 lines
5.3 KiB
Markdown
---
|
|
name: packetdial
|
|
description: >-
|
|
Manage the Arizona Computer Guru (ACG) PacketDial / OITVOIP hosted-VoIP
|
|
platform via the NetSapiens SNAPsolution API v2 (pbx.packetdial.com,
|
|
v44.4). List and inspect domains, users, devices/phones, DIDs (phone
|
|
numbers), resellers, and pull CDRs (call detail records). Provision new
|
|
customer domains, users, SIP devices, and phone numbers (all writes gated
|
|
behind --confirm). Read-only by default. Invoke for: "packetdial",
|
|
"oitvoip", "oit voip", "netsapiens", "voip portal", "pbx portal", "voip
|
|
domain", "voip user", "voip extension", "provision phone", "add did",
|
|
"phone number on voip", "call detail records", "cdr", "voip.packetdial",
|
|
"pbx.packetdial". NOTE: voip.packetdial.com is the customer-facing portal
|
|
(the fax/UC dashboard, e.g. Cascades account 28598) and has no API — the
|
|
programmable surface is pbx.packetdial.com. This skill talks to the LIVE
|
|
production reseller PBX; treat writes conservatively.
|
|
---
|
|
|
|
# PacketDial / NetSapiens (OITVOIP) Skill
|
|
|
|
Standalone CLI client for the NetSapiens SNAPsolution **API v2** that backs
|
|
ACG's hosted-VoIP offering through OITVOIP / PacketDial. Read-only by default;
|
|
every write (create / update / delete) is gated behind `--confirm`.
|
|
|
|
## The two hostnames (important)
|
|
|
|
| Host | What it is | API? |
|
|
|---|---|---|
|
|
| `voip.packetdial.com` | Customer-facing white-label portal / UC & fax dashboard (e.g. Cascades fax account **28598**). Login-gated UI. | **No** |
|
|
| `pbx.packetdial.com` | Reseller PBX platform — NetSapiens v44.4. | **Yes** — this skill targets it |
|
|
|
|
- API base: `https://pbx.packetdial.com/ns-api/v2`
|
|
- Token endpoint: `https://pbx.packetdial.com/ns-api/v2/tokens`
|
|
- Live OpenAPI spec: `https://pbx.packetdial.com/ns-api/webroot/openapi/openapi.json`
|
|
- Live Swagger UI: `https://pbx.packetdial.com/ns-api/openapi`
|
|
- Vendor docs: https://docs.ns-api.com/ (login) and https://voipdocs.io/oitvoip-access-platform-apis
|
|
|
|
## Credentials — ONE-TIME SETUP (not yet provisioned)
|
|
|
|
As of this skill's creation **no API key exists yet** — the vault entry
|
|
`msp-tools/oitvoip.sops.yaml` is empty/absent, so every command will fail with a
|
|
clear "No credentials found" error until you do this once:
|
|
|
|
1. Log into `pbx.packetdial.com` -> **Admin > API Keys** and create a
|
|
reseller-scoped key (prefix `nsr_`). If self-service key creation is not
|
|
available, reply to **Darwin Escaro (OITVOIP)** for reseller OAuth client
|
|
credentials.
|
|
2. Store it in the SOPS vault. Preferred (static bearer key):
|
|
```
|
|
# msp-tools/oitvoip.sops.yaml
|
|
credentials:
|
|
api_key: nsr_xxxxxxxxxxxxxxxx
|
|
```
|
|
Or, for OAuth2 password-grant credentials:
|
|
```
|
|
credentials:
|
|
client_id: <client id>
|
|
client_secret: <client secret>
|
|
username: <portal user@domain>
|
|
password: <portal password>
|
|
```
|
|
3. That's it — the client auto-detects which shape is present.
|
|
|
|
The client never hardcodes secrets. Resolution order: `PACKETDIAL_API_KEY` env
|
|
-> `PACKETDIAL_CLIENT_ID`+friends env -> vault `credentials.api_key` -> vault
|
|
OAuth fields. Env overrides exist for quick testing without touching the vault.
|
|
|
|
## Running the CLI
|
|
|
|
This machine's Python launcher is `py` (per identity.json); `python` / `python3`
|
|
also work. Run from the scripts dir so the two modules resolve.
|
|
|
|
```bash
|
|
cd C:/claudetools/.claude/skills/packetdial/scripts
|
|
|
|
py ns.py status # API version + authenticated key identity
|
|
py ns.py domains # list all domains
|
|
py ns.py domain <domain> # one domain's config
|
|
py ns.py users <domain> # users / extensions in a domain
|
|
py ns.py user <domain> <user>
|
|
py ns.py phones <domain> # SIP devices registered in a domain
|
|
py ns.py dids <domain> # phone numbers (DIDs) on a domain
|
|
py ns.py devices <domain> <user>
|
|
py ns.py cdrs --domain <domain> --start 2026-06-01 --end 2026-06-02
|
|
py ns.py resellers
|
|
```
|
|
|
|
## Writes (gated)
|
|
|
|
Every mutating command prints a `[DRY RUN]` line and exits non-zero unless you
|
|
pass `--confirm`. Bodies are raw JSON matching the NetSapiens v2 schema.
|
|
|
|
```bash
|
|
py ns.py create-domain --body '{"domain":"acme","description":"Acme Inc"}' --confirm
|
|
py ns.py create-user acme --body '{"user":"101","name-first-name":"Jane"}' --confirm
|
|
py ns.py create-phone acme --body '{...}' --confirm
|
|
py ns.py create-did acme --body '{"phonenumber":"15205551234"}' --confirm
|
|
py ns.py update-user acme 101 --body '{"name-last-name":"Doe"}' --confirm
|
|
py ns.py delete-user acme 101 --confirm
|
|
```
|
|
|
|
## Raw escape hatch (any of the 239 v2 paths)
|
|
|
|
The named commands cover the common surface; for anything else, hit the path
|
|
directly. Non-GET methods still require `--confirm`.
|
|
|
|
```bash
|
|
py ns.py raw GET domains/acme/users/101/answerrules
|
|
py ns.py raw POST domains/acme/users --body '{...}' --confirm
|
|
```
|
|
|
|
## Standard provisioning flow (new customer)
|
|
|
|
1. `create-domain` -> dial plan auto-generates
|
|
2. `create-user` per extension
|
|
3. `create-phone` per SIP device (MAC-provisioned)
|
|
4. `create-did` to attach DIDs and route them to users
|
|
5. Log the work back to the Syncro ticket
|
|
|
|
## Notes
|
|
|
|
- This is the LIVE production reseller PBX. A bad `create-domain` or
|
|
`delete-user` affects real customers — confirm the target domain first with a
|
|
read command before any write.
|
|
- CDR queries can be large; always pass `--start`/`--end` and a `--limit`.
|
|
- Reference detail (auth shapes, full endpoint inventory) lives in
|
|
`references/api.md`.
|