Developers · Reference
Every route, in the order the controllers serve it.
148 routes under /api/v1, plus health and metrics. Each one is grouped by the controller that owns it, with the permission it requires and what it does in a sentence.
On this page
Jump to a group
Auth, then a controller for each part of the phone system, then the operator-only platform surface at the end.
Auth
modules/auth/auth.controller.ts
Session cookie or bearer token. See the authentication section above for how the token works.
| Method | Path | What it does | Permission |
|---|---|---|---|
| POST | /api/v1/auth/login | Sign in and receive a session. | public, no session |
| POST | /api/v1/auth/mfa/verify | Complete the multi-factor challenge.MFA-exempt: this is how MFA itself gets satisfied. | session only |
| POST | /api/v1/auth/mfa/enrol | Start authenticator enrolment.MFA-exempt. | session only |
| POST | /api/v1/auth/mfa/enrol/confirm | Confirm enrolment and receive recovery codes.MFA-exempt. | session only |
| GET | /api/v1/auth/me | The signed-in user, their active tenant and role, every tenant they belong to, and their sorted permission list. The one call a portal makes on load. | session only |
| POST | /api/v1/auth/switch-tenant | Change the active account for this session.Refuses without a membership or an open support session in the target account. | session only |
| POST | /api/v1/auth/portal-mode | Switch the active tenant membership between Simple and Advanced mode. | session only |
| POST | /api/v1/auth/password | Change the signed-in user's password.Every other session for this user is signed out. | session only |
| POST | /api/v1/auth/logout | End the session and clear the cookie.MFA-exempt. | session only |
| GET | /api/v1/auth/roles | The permission set for every tenant role, for a portal that explains what a role can do. | session only |
Extensions
modules/extensions/extensions.controller.ts
| Method | Path | What it does | Permission |
|---|---|---|---|
| GET | /api/v1/extensions | List the lines on this account.Offset pagination: `?page=&pageSize=`, capped at 100. | extension.read |
| GET | /api/v1/extensions/next-number | Suggest the next free extension number. | extension.read |
| POST | /api/v1/extensions | Add a line: the Add Line wizard, executed server-side, in one call.Takes `idempotencyKey` (8-120 chars); a repeat with the same key replays the recorded result rather than creating a second line. | extension.manage |
| GET | /api/v1/extensions/:id | Get one line, with its site, voicemail box, devices, assigned numbers, emergency location and dial permission. | extension.read |
| GET | /api/v1/extensions/:id/sip-credentials | The live SIP username, password and server settings a phone needs to register this line.Reading it is audited by name every time; the extension record itself never carries the password. | extension.manage |
| GET | /api/v1/extensions/:id/dependencies | What breaks if this line is removed. | extension.read |
| PATCH | /api/v1/extensions/:id | Update a line's settings. | extension.manage |
| DELETE | /api/v1/extensions/:id | Remove a line, choosing what happens to its number. | extension.manage |
Numbers
modules/numbers/numbers.controller.ts
| Method | Path | What it does | Permission |
|---|---|---|---|
| GET | /api/v1/numbers | List the numbers on this account.Offset pagination, capped at 200. | number.read |
| GET | /api/v1/numbers/territories | Where the platform can supply a number right now. | number.read |
| GET | /api/v1/numbers/search | Search carrier inventory for numbers available to buy.Returns `{ numbers, notes }`. `notes` carries the reasons a territory or capability came back empty, so keep it: it is how a customer learns emergency calling is unavailable before buying, not after. | number.read |
| POST | /api/v1/numbers/purchase | Buy a number from a carrier and add it to inventory.Idempotent on `idempotencyKey`; a concurrent retry gets `409 This number order is already in progress.` | number.purchase |
| POST | /api/v1/numbers/:e164/assign | Route a number to an extension, ring group, queue, IVR or call flow. | number.manage |
| POST | /api/v1/numbers/:e164/unassign | Stop routing a number anywhere. | number.manage |
| POST | /api/v1/numbers/:e164/caller-id | Set the outbound caller ID name (CNAM) for a number. | number.manage |
| GET | /api/v1/numbers/:e164 | One number, with its routing and emergency state. | number.read |
Devices
modules/devices/devices.controller.ts, branding.controller.ts
| Method | Path | What it does | Permission |
|---|---|---|---|
| GET | /api/v1/devices | List enrolled phones with their registration state. | device.read |
| GET | /api/v1/devices/catalog | Phone models we can provision, and hardware we sell. | device.read |
| POST | /api/v1/devices | Enrol a phone by MAC address and issue its provisioning URL. | device.manage |
| POST | /api/v1/devices/:id/assign-extension | Put an extension on a line key of this phone. | device.manage |
| POST | /api/v1/devices/:id/reissue-token | Issue a fresh provisioning URL; the previous one stops working. | device.manage |
| DELETE | /api/v1/devices/:id | Remove a phone from the account. | device.manage |
| GET | /api/v1/devices/provisioning-settings | Where phones should look for their configuration. | device.read |
| GET | /api/v1/devices/branding | The logo and idle text handsets are showing. | device.read |
| PUT | /api/v1/devices/branding | Set the logo and idle text for every handset on the account. | device.manage |
| DELETE | /api/v1/devices/branding | Put the handsets back to the default screen. | device.manage |
Emergency (E911)
modules/emergency/emergency.controller.ts
| Method | Path | What it does | Permission |
|---|---|---|---|
| GET | /api/v1/emergency/locations | Emergency (911) addresses on this account. | emergency.read |
| POST | /api/v1/emergency/locations | Add an emergency address; it is validated immediately. | emergency.manage |
| POST | /api/v1/emergency/locations/:id/validate | Re-run carrier validation on an address. | emergency.manage |
| POST | /api/v1/emergency/numbers/:e164/register | Register a validated address against a number with the carrier. | emergency.manage |
| GET | /api/v1/emergency/unprotected-lines | Lines that would dial 911 without a usable address. | emergency.read |
Call handling
modules/ring-groups, queues, ivrs, call-flows, schedules, sites, dial-permissions
Ring groups, queues, auto attendants (IVRs), call flows, schedules, sites and dialling permissions each follow the same list / get / create / update / delete shape, with one or two operations of their own.
| Method | Path | What it does | Permission |
|---|---|---|---|
| GET | /api/v1/ring-groups | List ring groups. | routing.read |
| GET | /api/v1/ring-groups/:id | Get one ring group with its members. | routing.read |
| POST | /api/v1/ring-groups | Create a ring group. | routing.manage |
| PATCH | /api/v1/ring-groups/:id | Update a ring group. | routing.manage |
| DELETE | /api/v1/ring-groups/:id | Delete a ring group. | routing.manage |
| POST | /api/v1/ring-groups/:id/members | Add an extension to a ring group. | routing.manage |
| PATCH | /api/v1/ring-groups/:id/members/:extensionId | Change a member's ring delay, order, or enabled state. | routing.manage |
| DELETE | /api/v1/ring-groups/:id/members/:extensionId | Remove an extension from a ring group. | routing.manage |
| PUT | /api/v1/ring-groups/:id/members/order | Set the ring order for every member of the group. | routing.manage |
| GET | /api/v1/queues | List call queues. | routing.read |
| GET | /api/v1/queues/:id | Get one queue with its agents. | routing.read |
| POST | /api/v1/queues | Create a call queue. | routing.manage |
| PATCH | /api/v1/queues/:id | Update a call queue. | routing.manage |
| DELETE | /api/v1/queues/:id | Delete a call queue. | routing.manage |
| POST | /api/v1/queues/:id/agents | Add an agent to a queue. | routing.manage |
| PATCH | /api/v1/queues/:id/agents/:extensionId | Change an agent's tier, position, or enabled state. | routing.manage |
| DELETE | /api/v1/queues/:id/agents/:extensionId | Remove an agent from a queue. | routing.manage |
| GET | /api/v1/ivrs | List auto attendants. | routing.read |
| GET | /api/v1/ivrs/:id | Get one auto attendant with its menu. | routing.read |
| POST | /api/v1/ivrs | Create an auto attendant. | routing.manage |
| PATCH | /api/v1/ivrs/:id | Update an auto attendant. | routing.manage |
| DELETE | /api/v1/ivrs/:id | Delete an auto attendant. | routing.manage |
| POST | /api/v1/ivrs/:id/options | Add a menu key. | routing.manage |
| PUT | /api/v1/ivrs/:id/options | Replace the whole menu in one call. | routing.manage |
| PATCH | /api/v1/ivrs/:id/options/:optionId | Change one menu key. | routing.manage |
| DELETE | /api/v1/ivrs/:id/options/:optionId | Remove a menu key. | routing.manage |
| GET | /api/v1/call-flows | List call flows. | routing.read |
| GET | /api/v1/call-flows/:id | Get one call flow with its recent versions. | routing.read |
| GET | /api/v1/call-flows/:id/versions | List saved versions of a call flow. | routing.read |
| GET | /api/v1/call-flows/:id/versions/:versionId | Get the full graph of one version. | routing.read |
| POST | /api/v1/call-flows | Create a call flow as a draft. | routing.manage |
| PATCH | /api/v1/call-flows/:id | Rename a call flow. | routing.manage |
| POST | /api/v1/call-flows/:id/versions | Save a new draft version; returns the validation report. | routing.manage |
| POST | /api/v1/call-flows/:id/validate | Check a graph without saving or publishing it. | routing.read |
| POST | /api/v1/call-flows/:id/publish | Make a version live. | routing.manage |
| POST | /api/v1/call-flows/:id/rollback | Republish an earlier version. | routing.manage |
| DELETE | /api/v1/call-flows/:id | Delete a call flow. | routing.manage |
| GET | /api/v1/schedules | List schedules. | routing.read |
| GET | /api/v1/schedules/:id | Get one schedule with its holidays. | routing.read |
| GET | /api/v1/schedules/:id/state | Whether this schedule is open right now, and why. | routing.read |
| POST | /api/v1/schedules | Create a schedule. | schedule.manage |
| PATCH | /api/v1/schedules/:id | Update a schedule. | schedule.manage |
| DELETE | /api/v1/schedules/:id | Delete a schedule. | schedule.manage |
| POST | /api/v1/schedules/:id/holidays | Add a holiday. | schedule.manage |
| PATCH | /api/v1/schedules/:id/holidays/:holidayId | Update a holiday. | schedule.manage |
| DELETE | /api/v1/schedules/:id/holidays/:holidayId | Remove a holiday. | schedule.manage |
| POST | /api/v1/schedules/:id/close-now | Close the office temporarily, with a reason and an expiry. | schedule.manage |
| DELETE | /api/v1/schedules/:id/close-now | Lift a temporary closure and go back to the normal schedule. | schedule.manage |
| GET | /api/v1/sites | List the sites in this account. | tenant.read |
| GET | /api/v1/sites/:id | Get one site. | tenant.read |
| POST | /api/v1/sites | Create a site. | site.manage |
| PATCH | /api/v1/sites/:id | Update a site. | site.manage |
| DELETE | /api/v1/sites/:id | Delete a site. | site.manage |
| GET | /api/v1/dial-permissions | List dialling permissions. | tenant.read |
| GET | /api/v1/dial-permissions/:id | Get one dialling permission. | tenant.read |
| POST | /api/v1/dial-permissions | Create a dialling permission. | advanced.access |
| PATCH | /api/v1/dial-permissions/:id | Update a dialling permission. | advanced.access |
| DELETE | /api/v1/dial-permissions/:id | Delete a dialling permission. | advanced.access |
Analytics
modules/analytics/analytics.controller.ts
| Method | Path | What it does | Permission |
|---|---|---|---|
| GET | /api/v1/analytics/summary | Call analytics for a date range. | analytics.read |
| GET | /api/v1/analytics/call-volume | Daily call volume series only. | analytics.read |
| GET | /api/v1/analytics/busiest-extensions | Extensions ranked by call count. | analytics.read |
Call history (CDR)
modules/cdr/cdr.controller.ts
| Method | Path | What it does | Permission |
|---|---|---|---|
| GET | /api/v1/cdr | List calls.Call detail is regulated as CPNI. | cdr.read |
| GET | /api/v1/cdr/:id | One call, with its quality metrics. | cdr.read |
Billing and plans
modules/billing/billing.controller.ts, plans.controller.ts
| Method | Path | What it does | Permission |
|---|---|---|---|
| GET | /api/v1/billing/subscription | Current subscription, plan, seats and period. | billing.read |
| GET | /api/v1/billing/invoices | Invoices with their lines, most recent first. | billing.read |
| GET | /api/v1/billing/usage | Minutes, numbers and storage this period, with the projected charge. | billing.read |
| POST | /api/v1/billing/preview | Monthly cost delta for a proposed change (the Add Line wizard Review step).A POST because the proposed change is a structured request body, not because it changes anything. | billing.read |
| PATCH | /api/v1/billing/plan | Move the account to a different plan. | billing.manage |
| PATCH | /api/v1/billing/seats | Change the number of paid users. | billing.manage |
| GET | /api/v1/plans | List the publicly available plans and their features. | public, no session |
| GET | /api/v1/plans/:code | One plan, by its stable code. | public, no session |
Signup
modules/signup/signup.controller.ts
Public, because every one of these runs before the customer has an account. No endpoint takes a price from the client; every figure comes from the Plan, PlanFeature and HardwareSku rows on the server.
| Method | Path | What it does | Permission |
|---|---|---|---|
| POST | /api/v1/signup/quote | Price a basket. No side effects: nothing is created, reserved, or charged. | public, no session |
| POST | /api/v1/signup | Create a pending tenant, an owner, an incomplete subscription and a draft number order.Guarded by an `idempotencyKey` unique constraint; a repeat submission cannot create a second account. | public, no session |
| GET | /api/v1/signup/:id | Where a signup got to, for a browser that came back. | public, no session |
| POST | /api/v1/signup/:id/confirm | Capture payment, then activate, buy numbers and run guided setup, in that order. | public, no session |
Webhooks
modules/webhooks/webhook-endpoint.controller.ts
Managing your own outbound webhook subscriptions. See the webhooks section above for the delivery, signing and payload details.
| Method | Path | What it does | Permission |
|---|---|---|---|
| GET | /api/v1/webhooks/endpoints | List webhook endpoints. Signing secrets are never returned here. | webhook.manage |
| GET | /api/v1/webhooks/endpoints/:id | Get one webhook endpoint. | webhook.manage |
| GET | /api/v1/webhooks/endpoints/:id/deliveries | Recent delivery attempts for one endpoint.Filter with `?status=PENDING|SUCCEEDED|FAILED`. | webhook.manage |
| POST | /api/v1/webhooks/endpoints | Create a webhook endpoint.The response carries the signing secret in cleartext. This is the only time it is ever returned. | webhook.manage |
| PATCH | /api/v1/webhooks/endpoints/:id | Update a webhook endpoint. | webhook.manage |
| POST | /api/v1/webhooks/endpoints/:id/rotate-secret | Issue a new signing secret; returned in cleartext once.Deliveries already in flight keep signing with the old secret. | webhook.manage |
| DELETE | /api/v1/webhooks/endpoints/:id | Delete a webhook endpoint. | webhook.manage |
Enquiries
modules/enquiries/enquiries.controller.ts
| Method | Path | What it does | Permission |
|---|---|---|---|
| POST | /api/v1/enquiries | Send an enquiry from the public website.Rate limited to 3 per minute per IP; see the rate limits section. | public, no session |
| GET | /api/v1/platform/enquiries | The enquiry pipeline from the public website. | platform.tenant.read |
| PATCH | /api/v1/platform/enquiries/:id | Move an enquiry through the pipeline. | platform.tenant.manage |
Platform (operator-only)
modules/platform/platform.controller.ts, teams/teams.controller.ts
Held by platform roles, not by a tenant role. This is how wiTech itself runs the service, included here for completeness rather than as a customer integration surface.
| Method | Path | What it does | Permission |
|---|---|---|---|
| GET | /api/v1/platform/tenants | List every account on the platform. | platform.tenant.read |
| GET | /api/v1/platform/tenants/:id | One account, with its limits and open support sessions. | platform.tenant.read |
| POST | /api/v1/platform/tenants | Create an account. | platform.tenant.manage |
| POST | /api/v1/platform/tenants/:id/suspend | Suspend an account; calls in progress are not cut. | platform.tenant.manage |
| POST | /api/v1/platform/tenants/:id/reactivate | Return a suspended account to service. | platform.tenant.manage |
| PATCH | /api/v1/platform/tenants/:id/limits | Change concurrency, international, recording and advanced-mode limits. | platform.tenant.manage |
| POST | /api/v1/platform/tenants/:id/support-session | Open a time-boxed, logged support session into an account. | platform.support.impersonate |
| DELETE | /api/v1/platform/tenants/:id/support-session/:sessionId | End a support session immediately. | platform.support.impersonate |
| GET | /api/v1/platform/carriers | Carriers, their routes, and what each is verified to do. | platform.carrier.manage |
| POST | /api/v1/platform/carriers | Add a carrier and optionally its credentials. | platform.carrier.manage |
| PATCH | /api/v1/platform/carriers/:id | Update a carrier or rotate its credentials. | platform.carrier.manage |
| PUT | /api/v1/platform/carriers/:id/routes | Replace a carrier routing table. | platform.carrier.manage |
| POST | /api/v1/platform/carriers/health-check | Probe every carrier now and record the result. | platform.health.read |
| GET | /api/v1/platform/health | Database, Redis, carrier and PBX node health. | platform.health.read |
| GET | /api/v1/platform/audit-logs | Platform-wide audit log.Offset pagination, capped at 200. | platform.audit.read |
| GET | /api/v1/platform/tenants/:tenantId/teams-trunk | A tenant's Microsoft Teams Direct Routing trunk configuration. | platform.carrier.manage |
| PUT | /api/v1/platform/tenants/:tenantId/teams-trunk | Pair a tenant to Teams Direct Routing. | platform.carrier.manage |
| PATCH | /api/v1/platform/tenants/:tenantId/teams-trunk | Change a tenant's Teams Direct Routing trunk settings. | platform.carrier.manage |
| DELETE | /api/v1/platform/tenants/:tenantId/teams-trunk | Remove a Teams Direct Routing trunk. | platform.carrier.manage |
Health and metrics
modules/health/health.controller.ts
| Method | Path | What it does | Permission |
|---|---|---|---|
| GET | /health | Liveness. Answers as long as the process is running. | public, no session |
| GET | /health/ready | Readiness. Fails while the database is unreachable.503 when the database does not answer. | public, no session |
| GET | /metrics | Prometheus metrics.Gated on an `x-metrics-token` header when `METRICS_TOKEN` is set. | public, no session |
Not built
What is not here yet, said plainly
No controller exists for voicemail, recordings, user invitations, API tokens, generic SIP trunk management, port requests, or fraud events, even though the underlying data models exist for several of them. If your integration needs one of these, ask; it tells us where to build next.