Back to app

Changelog

Changes to the public API, the scenario grammar, bundles and scoring. Newest first.

2026-10-17: why a verification call was not answered

  • last_attempt of GET /targets/{id}/verification has three new fields: sip_status and sip_reason (the carrier's answer when the line never picked up: 480 unavailable, 486 busy, 603 declined, 404 unknown number...) and failure_hint, what to fix before the next attempt, in plain words.
  • New fields attempts_max and attempts_reset_at (when the oldest failed attempt stops counting). A call the line does not answer still counts as a failed attempt.
  • The dashboard and the MCP tools get_number_status and place_verification_call explain the failure and say how many attempts are left.
  • See When the verification call fails: our calls come from a US number (+1), which some carriers and call-screening features block.

2026-10-11: support tickets

  • Ask the CallQA team from your coding agent: MCP tools contact_support, list_support_tickets, get_support_ticket and reply_support_ticket. A person answers, usually within a few hours; the answer reaches the agent, the app and your email.
  • REST API: GET/POST /support/tickets, GET /support/tickets/{id}, POST /support/tickets/{id}/messages, POST /support/tickets/{id}/close. Any key scope can open a ticket; guests read. At most 20 new tickets a day per organization.
  • get_setup_status has a new field support (how to reach us, answers not read yet), and links.support. Secrets pasted in a ticket are replaced by [redacted secret].
  • A 429 rate_limited error can now carry a more precise detail.
  • See Getting help.

2026-10-11: compliance review of scenarios

  • Every scenario is reviewed against the Acceptable Use Policy before it can call anyone, and again when its content changes. Only an allowed scenario runs; a refused one shows its reasons (category, the words of the scenario, what to change), a doubtful one is held for a human review by CallQA staff. See Compliance review of scenarios.
  • ScenarioOut (POST, PUT and GET /scenarios/{id}) has a new field compliance; the MCP tools create_scenario, update_scenario and get_scenario return it too.
  • POST /scenarios/{id}/runs on a held or refused scenario answers 403 blocked_policy. New call block_reason values: compliance_blocked, compliance_review. A call can wait queued a few seconds while the review runs.
  • More numbers are never called: emergency and public safety numbers of every country code (911, 988, N11, 999, 101, 111, 112, 15, 17, 18, 115, 119, harmonised 116xxx...), and international premium rate (+979) and satellite networks (+870, +881, +882, +883).

2026-10-09: free trial

  • A new organization comes with 10 free test calls to try CallQA, no card needed (plan trial, the calls are bonus_remaining in GET /usage). Only the first organization a person creates gets it. See Free trial.

2026-10-09: grace period on a failed renewal

  • A subscription whose renewal payment failed (past_due, while Stripe retries for up to about 2 weeks) keeps its plan: calls and the API work as usual, instead of ending as subscription_inactive. Only the cancellation after the last retry takes the plan away. See When a renewal payment fails.
  • GET /billing/subscription has a new field payment_retry_until: the deadline to update the card, null when no payment is pending.

2026-10-08: MCP setup tools, docs search, seat limit as a plan error

  • 13 setup tools on the MCP server, so a coding agent can take an organization from zero to scheduled regression tests without the dashboard: get_setup_status, create_environment, list_numbers, add_phone_number, get_number_status, start_number_verification, place_verification_call, set_schedule, list_schedules, list_webhooks, configure_webhook, create_alert_channel and get_ci_setup (GitHub Actions or GitLab CI files for your scenarios). Same scopes, plan limits, verification rules and wallet rules as the REST API.
  • Prompt set-up-callqa: the setup in order, saying where a person must act (sign the attestation of a number, make the line say the verification code, pay, create keys). See MCP server.
  • POST /invitations with every seat taken answers 403 feature_not_in_plan (feature: seats, with required_plan and upgrade_url), like the other plan limits, instead of 400 not_allowed.
  • Importing a scenario whose environments names an environment your organization does not have is still refused (422 invalid_scenario); the error is now on environments.<slug> and lists your environments and how to create one.
  • A call with no result is failed after its own limits.max_duration_s plus a margin (40 minutes at least), and a run left running while all its calls are finished is completed.
  • Runs are called runs everywhere (dashboard, alerts, CLI summary, API summaries). Webhook events keep their names (suite_run.*, suite_run_id).
  • The docs have a search: /docs/search/?q=.

2026-10-02: MCP server

Additions only.

  • MCP server on https://app.callqa.dev/mcp (Streamable HTTP), authenticated with your API keys: 15 tools (scenarios, environments, versions, runs, reports, calls, exports for LLMs, the scenario assistant, usage), the scenario grammar and examples as resources, and 3 prompts. Same scopes, IP restrictions, rate limits and journal as the REST API. See MCP server.

2026-09-27: versions, schedules per environment, free tags, billing forecast

Additions, and deprecated aliases kept until 2027-03-31.

Versions replace releases

A release becomes a version of your code in one environment, with git fields. Existing releases were converted in place: same ids, same runs.

  • /versions (list, create, read, edit, delete) and POST /versions/{id}/promote. A version has label, environment, deployed_at, git_ref, git_sha, source_url, notes, target_id and tags. Runs of an environment placed after deployed_at are attributed to it until the next version.
  • POST /scenarios/{id}/runs takes version, git_ref, git_sha, source_url; run responses carry version and version_id; GET /runs?version_id=.
  • GET /environments/compare takes a_version / b_version.
  • Webhook events version.created and version.promoted.
  • Deprecated (sunset 2027-03-31): /releases and POST /releases/{id}/promote (they answer with Deprecation and Sunset headers), the release field of the trigger request and of run responses, a_release / b_release, and the events release.created / release.promoted (an endpoint subscribed to them still receives them). The CLI --release flag and the GitHub Action release input became --code-version and version.

Scenarios per environment

  • A scenario is activated per environment with its own schedule, time zone and call window: GET /scenarios/{id}/environments, PUT and DELETE /scenarios/{id}/environments/{env}, GET and POST /environments/{env}/scenarios (bulk), GET /matrix (scenario x environment, and what passes per version).
  • Scenario grammar: optional environments map, keyed by environment slug, with enabled, schedule, timezone and call_window. The top-level schedule, timezone and call_window stay the plan of the default environment. Same schema_version: 1.
  • The former per scenario schedule moved to the default environment.

Tags, billing

  • Tags are free keywords on scenarios, runs, versions and numbers: GET /tags?q= (autocomplete, with uses), POST /tags/bulk.
  • GET /billing/forecast (what the schedules will use this month), GET /billing/referral, and on /billing/settings: allow_paid_overage, on_limit (block_calls or pause_schedules) and schedules_paused.

2026-09-27: environments, exports for LLMs, webhook scopes

Additions only.

  • Environments: /environments (CRUD, PUT /environments/{env}/numbers, GET /environments/stability, GET /environments/compare). See Environments.
  • environment on POST /scenarios/{id}/runs, POST /releases, and as a filter on GET /runs, /calls, /releases; environment (slug) in run and release responses.
  • POST /releases/{id}/promote tags a release in another environment.
  • Release versions are unique per environment (they were unique per organization).
  • Exports for LLMs: GET /calls/{id}/llm-export, /runs/{id}/llm-export, /scenarios/{id}/llm-export (Markdown or compact JSON). See Replay and bundles.
  • Webhook scopes: filters (scenario_ids, tags, environments) on POST/PATCH /webhooks, returned by every webhook endpoint. New events call.regressed, call.recovered, suite_run.started, release.created, release.promoted; call and run payloads gain scenario_id, environment, release, tags (and variant_id for calls). score.dropped now compares runs of the same environment. See Webhooks.

2026-09-26: API v1 additions

Additions only, except the stricter webhook events noted below.

  • Alerts: Slack (incoming webhook) and email channels with rules on failure, score and latency, /alert-channels (CRUD and test). See Alerts.
  • Tags, releases, webhooks: GET and PATCH on /tags/{id}, /releases/{id} and /webhooks/{id} (pause a webhook with enabled: false).
  • Deletes: DELETE /runs/{id} and DELETE /calls/{id} (admin); billing lines are kept without the calls' content.
  • Webhook secret rotation: POST /webhooks/{id}/rotate-secret, with a grace period during which deliveries carry two v1 signatures. Accept a delivery if any v1 matches.
  • wallet.low_balance is now sent, with a threshold per organization.
  • API keys: IP restriction (allowed_cidrs), GET and PATCH /api-keys/{id}, in-place rotation with a grace period (POST /api-keys/{id}/rotate); last_used_ip in responses.
  • Billing: GET and PATCH /billing/settings (monthly spend cap, low balance threshold), GET /plans, GET /billing/subscription, POST /billing/subscription/checkout, POST /billing/portal.
  • Audit log: GET /audit-log (admin).
  • Errors: every error has a machine-readable code (missing_scope, feature_not_in_plan, ip_not_allowed, already_exists...); code is never null any more. See Errors.
  • OpenAPI: stable, readable operationIds (targets_create, runs_trigger...), and 401, 403, 404, 422, 429 declared on every operation. Client generators produce readable method names; regenerate your client once.
  • POST /wallet/checkout: the schema now states the real range (2000 to 500000 cents); out of range answers 422.
  • ?wait=true waits asynchronously on the server; same contract (200, 412, 202).
  • Failed authentications from an IP no longer block valid keys used from the same IP.
  • Webhooks: an unknown event name is now refused (400, unknown_event) instead of being silently dropped.
  • Deprecation policy with Deprecation and Sunset headers. The developer docs are served on /docs/.

2026-09-26: API v1 (1.0.0)

First public version.

  • REST API /api/v1: organization, members and invitations; targets and number verification; scenarios (JSON and YAML import/export, validation, generation), variants (manual, auto-derived, from a call); suite runs with a CI mode (?wait=true&threshold=N, answers 200, 412 or 202); calls, transcripts and traces; replay bundles and replays; tags and releases; webhooks with HMAC-SHA256 signatures and retries; API keys with scopes and the API journal; usage, prepaid wallet and top-ups.
  • Scenario grammar schema_version: 1, with the callqa.dev short form and x_* extension fields. JSON Schema at GET /api/v1/scenarios/schema.
  • Replay bundle bundle_version: 1.
  • Webhook events: call.completed, call.failed, call.blocked, suite_run.completed, suite_run.failed, score.dropped (wallet.low_balance reserved at the time).