packetdial: build out + document the skill against the live NetSapiens v2 API
Key is now provisioned + live-verified, so grounded the skill in the real spec (RTFM): - Mapped the OpenAPI surface (v44.4.10, 239 paths / 354 ops) — capability map added to SKILL.md (what the platform exposes vs what's wrapped vs raw-only). - Added 6 live-verified read wrappers (ns.py + ns_client.py): callqueues, timeframes, sites, contacts, autoattendants, billing (domain limits/usage). - Replaced the stale "not yet provisioned" credentials section with the live status (vaulted nsr_ reseller key, key-id nsr_hSGUB5Wo, scope Reseller 91912.service, RW) + the pbx.packetdial.com vs api.ucaasnetwork.com hostname note + override. - api.md history updated. Writes remain gated behind --confirm; everything unwrapped reachable via `raw`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -97,6 +97,12 @@ def main(argv=None) -> int:
|
||||
sp = sub.add_parser("phones", help="phones (devices) in a domain"); sp.add_argument("domain")
|
||||
sp = sub.add_parser("dids", help="phone numbers in a domain"); sp.add_argument("domain")
|
||||
sp = sub.add_parser("devices", help="devices for a user"); sp.add_argument("domain"); sp.add_argument("user")
|
||||
sp = sub.add_parser("callqueues", help="ACD call queues in a domain"); sp.add_argument("domain")
|
||||
sp = sub.add_parser("timeframes", help="time-based routing schedules in a domain"); sp.add_argument("domain")
|
||||
sp = sub.add_parser("sites", help="multi-site definitions in a domain"); sp.add_argument("domain")
|
||||
sp = sub.add_parser("contacts", help="shared/domain contacts"); sp.add_argument("domain")
|
||||
sp = sub.add_parser("autoattendants", help="auto-attendants (IVR) in a domain"); sp.add_argument("domain")
|
||||
sp = sub.add_parser("billing", help="domain limits + current usage counts"); sp.add_argument("domain")
|
||||
sub.add_parser("resellers", help="list resellers")
|
||||
sp = sub.add_parser("cdrs", help="call detail records")
|
||||
sp.add_argument("--domain"); sp.add_argument("--start"); sp.add_argument("--end")
|
||||
@@ -138,6 +144,18 @@ def main(argv=None) -> int:
|
||||
_emit(client.phonenumbers(args.domain))
|
||||
elif args.cmd == "devices":
|
||||
_emit(client.devices(args.domain, args.user))
|
||||
elif args.cmd == "callqueues":
|
||||
_emit(client.callqueues(args.domain))
|
||||
elif args.cmd == "timeframes":
|
||||
_emit(client.timeframes(args.domain))
|
||||
elif args.cmd == "sites":
|
||||
_emit(client.sites(args.domain))
|
||||
elif args.cmd == "contacts":
|
||||
_emit(client.contacts(args.domain))
|
||||
elif args.cmd == "autoattendants":
|
||||
_emit(client.autoattendants(args.domain))
|
||||
elif args.cmd == "billing":
|
||||
_emit(client.billing(args.domain))
|
||||
elif args.cmd == "resellers":
|
||||
_emit(client.resellers())
|
||||
elif args.cmd == "cdrs":
|
||||
|
||||
@@ -351,6 +351,31 @@ class NetSapiensClient:
|
||||
def subscriptions(self) -> Any:
|
||||
return self.request("GET", "subscriptions")
|
||||
|
||||
# --- per-domain feature resources (live-verified shapes, 2026-06-22) ---
|
||||
def callqueues(self, domain: str) -> Any:
|
||||
"""ACD call queues in a domain (agents, dispatch type, live queued count)."""
|
||||
return self.request("GET", f"domains/{urllib.parse.quote(domain)}/callqueues")
|
||||
|
||||
def timeframes(self, domain: str) -> Any:
|
||||
"""Time-based routing schedules (business hours / holidays) for a domain."""
|
||||
return self.request("GET", f"domains/{urllib.parse.quote(domain)}/timeframes")
|
||||
|
||||
def sites(self, domain: str) -> Any:
|
||||
"""Multi-site definitions within a domain."""
|
||||
return self.request("GET", f"domains/{urllib.parse.quote(domain)}/sites")
|
||||
|
||||
def contacts(self, domain: str) -> Any:
|
||||
"""Shared/domain contacts (address book)."""
|
||||
return self.request("GET", f"domains/{urllib.parse.quote(domain)}/contacts")
|
||||
|
||||
def autoattendants(self, domain: str) -> Any:
|
||||
"""Auto-attendants (IVR menus) in a domain."""
|
||||
return self.request("GET", f"domains/{urllib.parse.quote(domain)}/autoattendants")
|
||||
|
||||
def billing(self, domain: str) -> Any:
|
||||
"""Domain billing/limits snapshot: max + current counts (users, queues, AAs, calls)."""
|
||||
return self.request("GET", f"domains/{urllib.parse.quote(domain)}/billing")
|
||||
|
||||
# ======================================================================
|
||||
# WRITE METHODS (gated — the CLI requires --confirm before calling these)
|
||||
# ======================================================================
|
||||
|
||||
Reference in New Issue
Block a user