TotalPath
Map and test phone IVR systems via API.
Community: Submitted by a user or imported; check the owner before granting accessOnlineNo sign-inGlobalFreeRead-only
What it can do
- CreateMapping: Create an IVR mapping job that will call the specified phone number, navigate the menu tree via DTMF and/or voice prompts, transcribe audio, and analyse with AI to discover all branches
- GetMapping: Get the current state and run metadata for a specific IVR mapping job. USE WHEN: - User asks about a specific mapping job by ID - User wants to know if a mapping run has finished - User wa
- ListMappings: List IVR mapping jobs in your workspace. Supports filtering and cursor pagination. FILTERS (all optional): - status: Filter by the latest run's status. Values: idle | running | completed
What data it sees
Do you need an account
No: the server works without sign-in
Map and test phone IVR systems via API. TotalPath discovers menu trees with real calls, runs scripted persona tests, executes regulatory compliance probes, and orchestrates concurrent load tests at scale — all with AI-graded transcripts. Authenticate with an x-api-key header. Sign up, subscribe and get an API key at https://www.nopaque.co.uk/register — API keys require a paid plan, so the free tier cannot use them. Key setup steps: https://www.nopaque.co.uk/docs/authentication.
Server tool list (16)
Raw names from tools/list. Only developers need these.
| createMapping | Create an IVR mapping job that will call the specified phone number, navigate the menu tree via DTMF and/or voice prompts, transcribe audio, and analyse with AI to discover all branches. Returns a job resource immediately with status="idle". To start the actual mapping, call the startMapping REST endpoint (not yet exposed via MCP — use the REST API or wait for follow-up phases). Mapping completion typically takes 2-15 minutes depending on tree depth. |
| getMapping | Get the current state and run metadata for a specific IVR mapping job. USE WHEN: - User asks about a specific mapping job by ID - User wants to know if a mapping run has finished - User wants run-level metadata (stats, in-flight calls, start/completion times) - You need a job's currentRun.id to feed into getMappingTree or REST /mapping/{id}/runs QUERY PARAMS (optional): - version: Run number (1-indexed) — fetches that specific historical run. Default: latest run. JOB vs RUN STATUS (critical): Mapping JOBS cycle status `running` ↔ `idle` and **never reach `completed`** between runs. Only RUNS reach `completed` / `failed` / `limited`. To detect a finished run, read `currentRun.status === 'completed'`. **Do NOT poll for `status === 'completed'` at the job level — that state never arrives.** See getMappingTree for the discovered IVR tree, available once `currentRun.status === 'completed'`. RESPONSE FIELDS: - id: Job UUID. - status: Job-level status (always `idle` between runs; `running` during an active run). - tags: String labels for grouping (set via createMapping or update). - config: mappingMode, maxDepth, maxCalls, probeMode. - currentRun: The run this response describes — the active/latest run by default, or the run identified by `version` when supplied. Contains: id, status, runNumber, stats, inFlightCount, limitReason, startedAt, completedAt. **Prefer `currentRun.status` over the flat `status`.** - status / runNumber / stats / inFlightCount / limitReason / startedAt / completedAt: Flat-merged duplicates of currentRun fields, kept for back-compat. New code should read currentRun.*. USAGE PATTERNS: - "Is mapping <id> finished?" → getMapping { id } then read `currentRun.status` - "Show me run 2 of mapping <id>" → getMapping { id, version: 2 } - "What's the in-flight call count for mapping <id>?" → getMapping { id } then read `currentRun.inFlightCount` RELATED TOOLS: - listMappings — find a job by phoneNumber/status/tag/createdAfter (use this before getMapping if you don't have the id) - getMappingTree — discovered IVR tree once `currentRun.status === 'completed'` (use `?format=flat` for leaf-count / depth aggregation) - cancelMapping — **DESTRUCTIVE** — stop an in-progress run; only call when explicitly asked - createMapping — **REAL CALL** — starts a new mapping run (initiates external phone call); only call when explicitly asked - REST GET /mapping/{id}/runs — run history (REST-only today; may surface as a future MCP tool if eval shows demand) ERRORS: - 404: job does not exist or belongs to another workspace (cross-workspace 404 by design — do not retry) - 400: invalid version (non-integer or < 1) - 404: requested version not found in this job's run history (response message lists available versions) |
| listMappings | List IVR mapping jobs in your workspace. Supports filtering and cursor pagination. FILTERS (all optional): - status: Filter by the latest run's status. Values: idle | running | completed | failed | limited. IMPORTANT: Mapping JOBS cycle between status `running` (active mapping) and `idle` (between runs) and NEVER reach `completed`. Only RUNS reach `completed`/`failed`/`limited`. The `status` filter compares against the latest run's status — so `status=completed` returns jobs whose most recent run finished, and `status=running` returns jobs with an in-flight run. - tag: Filter to jobs with this tag (exact, lowercase alphanumeric + hyphens, e.g. 'compliance-eu'). - phoneNumber: Filter by exact E.164 phone number (e.g. '+441234567890'). - name: Case-insensitive substring match against the job name. - profileId: Filter to jobs using a specific mapping profile (UUID). - createdAfter / createdBefore: ISO-8601 datetime strings (e.g. '2026-05-01T00:00:00Z'). Efficient DDB range filter — both, either, or neither. - limit: Page size, 1-100, default 50. SORTING: - sortDir: 'asc' or 'desc' (default 'desc' = newest first). Sort is always by createdAt. PAGINATION: - Pass `cursor` (from a previous response's `nextCursor`) to get the next page. - When `nextCursor` is absent from the response, you are on the last page. - LOSSY-PAGINATION CAVEAT: When filtering by `status`, paged results may underfill (return fewer than `limit` items) because the status filter is applied after the DDB query. Always follow `nextCursor` until it is absent to be sure you have all matches. RESULT FIELDS: - id: UUID — use with `getMapping` for full detail (run state, step counts) or `getMappingTree` for the discovered IVR tree (once the latest run has status=`completed`). - status: The latest run's status; `idle` when the job has no active run. - tags: String labels for grouping. Set via `createMapping` / mapping update. - config: Includes mappingMode, maxDepth, maxCalls, probeMode. - runNumber: The run number of the latest run, if any. USAGE PATTERNS: - "List my 5 most recent mappings" → { limit: 5, sortDir: 'desc' } - "Show running mapping jobs" → { status: 'running' } - "Mappings tagged compliance-eu" → { tag: 'compliance-eu' } - "Mappings created this week" → { createdAfter: '<start-of-week ISO>' } - "Find runs for +44... in detail" → call listMappings { phoneNumber: '+44...' } then getMapping(id) |
| cancelMapping | Cancel an in-progress IVR mapping job. Returns the updated job resource. No effect if the job is already idle/cancelled. Use this when you need to stop a long-running mapping early (e.g., the agent realised the wrong number was supplied). |
| getMappingTree | Get the discovered IVR tree structure for a mapping job — every node visited, the DTMF/voice paths between them, audio recordings, and (if enrichment ran) IVR menu transcripts and probe classifications. USE WHEN: - User asks for the discovered tree / map / structure of an IVR - User wants leaf-node count, depth, or aggregate tree statistics (use `format=flat`) - User wants to inspect specific tree-node fields (voice prompts, probe classifications, audio URLs) - User wants to compare two historical runs (call twice with different `version`) BEST CALLED: after `currentRun.status === 'completed'` (from getMapping). If you call earlier and the run is still active, the response will document that via `reason: 'in_progress'` (see below). QUERY PARAMS (optional): - format: `tree` (default) = hierarchical nesting; `flat` = array of nodes with depth/path fields for aggregation. Use `flat` for "how many leaves?" / "how deep?" / "list all voice prompts" questions. - version: Run number (1-indexed) — fetches the tree of that historical run. Default: latest run. RESPONSE — SUCCESS (tree built from steps): - jobId, runId, runNumber, status, stats: identifiers + run-level summary. - tree (when `format=tree`): a hierarchical TreeNode with .children[] recursion. - steps (when `format=flat`): an array of TreeNode (each with empty .children, depth, path). TreeNode fields (each is OPTIONAL — omitted when absent; never null per the AJV contract): - stepId, digit, label, depth, path, status, transcript, isTerminal, children, duration - stepType: 'dtmf' | 'voice' — interaction type (Phase 30 voice-agent) - voicePrompt: spoken prompt text at this node (voice nodes only) - menuLabel: semantic tag emitted per bot turn (e.g. 'greeting', 'capabilities_listed', 'balance_captured'); from Phase 55 voice-agent enrichment - spokenResponse: what the agent said back at this turn (Phase 55 voice-agent) - probeCategory / probeClassification / probeRationale: probe-enrichment fields (Phase 31). Only present after probe enrichment ran. Trigger probes via REST POST /mapping/{id}/runs/{runId}/probe (not exposed via MCP today). - audioUrl: presigned S3 URL for the recorded audio of this step. **Valid for approximately 1 hour. Do not cache or store** — re-call getMappingTree to refresh URLs for long sessions. - inputRequired: per-step UX hint when a prompt requires user input. Contains type, description, formatHint, terminator, startTimeMs. RESPONSE — EMPTY-STATE ENVELOPE (200 OK, tree: null): The handler returns 200 with `tree: null` and a `reason` discriminator in three cases: - `reason: 'no_runs'` — the job has never been started. Message suggests POST /mapping/{id}/start. - `reason: 'no_steps'` — a run started but no steps recorded yet. May still be initialising; retry shortly. - `reason: 'in_progress'` — the latest run is still active and only the root step has been recorded. Don't treat the current tree as complete. Retry shortly OR ask getMapping for `currentRun.status` to confirm. All three empty-state cases return 200 OK with the same envelope shape; only `reason` + `message` differ. USAGE PATTERNS: - "Show me the IVR tree for mapping <id>" → getMappingTree { id } - "How many leaves does mapping <id> have?" → getMappingTree { id, format: 'flat' } then filter steps where children.length === 0 OR isTerminal === true - "How deep is the tree?" → getMappingTree { id, format: 'flat' } then max(steps[].depth) - "What voice prompts did mapping <id> discover?" → getMappingTree { id, format: 'flat' } then filter where stepType === 'voice' or voicePrompt is present - "Show me run 1's tree" → getMappingTree { id, version: 1 } - "What probe classifications fired?" → getMappingTree { id } then walk tree filtering nodes where probeClassification is present RELATED TOOLS: - getMapping — job + run metadata, including `currentRun.status` (check this before deciding the tree is "done") - listMappings — find jobs by phoneNumber/status/tag if you don't have the id - REST GET /mapping/{id}/runs — run history (REST-only today; useful for picking a `version` for historical tree fetches) ERRORS: - 404: job does not exist or belongs to another workspace (cross-workspace 404 by design — do not retry) - 400: invalid version (non-integer or < 1) OR invalid format (not 'tree' or 'flat') - 404: requested version not found - 200 + reason: 'no_runs' | 'no_steps' | 'in_progress' — NOT errors; empty-state envelope (see above) |
| runMissionTest | Launch a mission test run from an existing saved mission-test-config. A mission test calls a number, executes a scripted persona+goal+acceptance flow, and the LLM self-reports pass/fail against the acceptance criterion at end-of-call. Returns the run resource immediately; poll getMissionTestRun for verdict. |
| getMissionTestRun | Use when you have a mission-test run id and want the full AI-judged result: verdict (pass/fail/inconclusive/error), passReasoning, passEvidence, transcript, and compliance fields. Returns 404 for non-mission runs (compliance, standard, param) — use getRunResults for those. For listing across runs use listTestRuns; for counts and percentages use aggregateTestRuns. Returns 404 cross-workspace (D-02 strict type-gate). |
| listMissionTestConfigs | List saved mission-test configs in your workspace with rich filters. Each saved config is a reusable mission-test definition (name, phone, sector, persona/mission, acceptance criterion, profile, optional tags). Filter by: `name` (substring), `phoneNumber` (E.164 exact), `sector` (e.g. `financial-services`), `profileId`, `tag` (lowercase exact, single tag), `createdAfter` / `createdBefore` (ISO8601). Sort by `createdAt` or `name`, asc/desc (default `createdAt desc`). Paginate via `cursor` + `limit` (1..100, default 50). Use when: the user wants to find or list configs by attribute ("configs for compliance-EU", "configs for phone +44…", "configs tagged X", "configs created this month"). Returns a slim projection — for full mission/acceptance text use getMissionTestConfig once you have identified the config. Mission configs are immutable today — there is no separate "modified" timestamp. To find configs newly added in a time window, filter by createdAfter / createdBefore. Cross-tool: for the run history launched from a specific config, use listTestRuns?configId=X. For pass-rate-by-config, use aggregateTestRuns?groupBy=configId. Mission configs are workspace-scoped; cross-workspace returns 404. |
| getMissionTestConfig | Get a single saved mission-test config by ID. Returns the full row: name, description, phoneNumber, sector, mission, acceptance, profileId, tags, createdAt, updatedAt. Use when: you have a config ID (typically from listMissionTestConfigs or from a run.configId field) and want to inspect the persona / mission / acceptance criterion text — for example before launching a new run or to explain to the user how a previous run was configured. Cross-tool: for run history launched from this config, use listTestRuns?configId=X. For the run that produced a specific verdict, use getMissionTestRun. Configs are editable via PATCH /testing/mission-test-configs/{id}; `updatedAt` reflects the most recent edit and may differ from `createdAt`. Cross-workspace returns 404. |
| getRunResults | Get any test run (standard/param/mission/compliance) by id, including per-step results: outcome, transcript, similarity scores, words. Use when you need per-step breakdowns OR when you do not know if the run is mission or standard. For mission-specific shape (verdict, evidence, judgeReasoning) prefer getMissionTestRun. For listing across runs use listTestRuns; for counts use aggregateTestRuns. Returns 404 cross-workspace. |
| listTestRuns | List test runs (mission/compliance/standard/param) with rich filters: runType, outcome (PASS/FAIL/ERROR/INCONCLUSIVE), phoneNumber, configId, catalogueTestId, date range (startedAfter/startedBefore), sort (startedAt/completedAt asc/desc), and cursor pagination. Use cases: "last 3 mission failures", "runs against phone +44… this week", "compliance fails in the last 24h". For counts and percentages use aggregateTestRuns instead. D-11: Load tests live in a separate table — use listLoadTests; runType=load returns 400 here. |
| aggregateTestRuns | Aggregate test-run counts; groupBy outcome | runType | configId | catalogueTestId | phoneNumber; optional timeBucket day/week/month with UTC ISO8601 bucket keys ("2026-05-12" day, "2026-W19" week, "2026-05" month). Use cases: "% pass/fail this week", "which compliance test fails most", "day-by-day pass count last 2 weeks". Response capped at top 100 groups by count desc; truncated:boolean indicates cap hit. D-11: runType=load returns 400 — use listLoadTests. D-12: groupBy=stepName returns 400 — for step-level breakdowns within a single run use getRunResults; for step-level aggregation across runs see Phase 1.1. |
| listLoadTests | List all load-test runs in your workspace. Each load test fans out N concurrent test runs against a target number and produces aggregate statistics. Returns a paginated array. |
| listComplianceCatalogue | List the available compliance tests in the regulatory catalogue (e.g., GDPR consent capture, EU AI Act disclosure, PCI-DSS DTMF masking). Each entry has an ID + sector + description. Use the IDs as input to runComplianceTest. |
| runComplianceTest | Run a compliance test against a phone number. The test calls the number, executes a regulatory probe script (e.g., requests data deletion, asks about AI disclosure), and returns pass/fail per probe. Returns the run resource; poll getRunResults for completion. |
| getWorkspaceUsage | Get the current usage and entitlement snapshot for your workspace: subscription tier, free-minute pool balances (testing/loadTesting/mapping/s2s/s2stest), purchased-pack balances, current-period consumption, and remaining LLM-enrichment tokens. Use this to check whether you have enough capacity before kicking off an expensive job. Returns 404 cross-workspace. |