Qualytics CLI is a command-line interface for the Qualytics data quality platform. It wraps the Qualytics controlplane REST API, enabling users to manage quality checks, datastores, containers, and operations (sync, profile, scan) programmatically.
License: MIT Language: Python 3.10+ Build Backend: hatchling Package Manager: uv
qualytics-cli/
├── .github/workflows/
│ ├── ci.yml # PR validation: lint, test, pre-commit
│ ├── publish.yml # Tag-triggered: build + publish to PyPI + GitHub Release
│ └── release.yml # Manual dispatch: version bump → commit → tag → push
├── qualytics/
│ ├── __init__.py
│ ├── qualytics.py # Entry point — registers all Typer sub-apps
│ ├── config.py # Configuration management (load/save/validate)
│ ├── api/
│ │ ├── client.py # Centralized API client (QualyticsClient)
│ │ ├── anomalies.py # Anomaly API operations (CRUD + bulk)
│ │ ├── containers.py # Container API operations (CRUD + validate + field profiles)
│ │ ├── connections.py # Connection API operations (CRUD + test)
│ │ ├── datastores.py # Datastore API operations (CRUD + verify + enrichment)
│ │ ├── operations.py # Operation API operations (run, get, list, abort)
│ │ └── quality_checks.py # Quality checks API operations (CRUD + bulk)
│ ├── cli/
│ │ ├── main.py # Deprecated wrappers (init → auth init, show-config → auth status)
│ │ ├── anomalies.py # anomalies get/list/update/archive/delete commands
│ │ ├── checks.py # checks CRUD + git-friendly export/import
│ │ ├── auth.py # auth login/status/init commands
│ │ ├── connections.py # connections create/update/get/list/delete/test commands
│ │ ├── containers.py # containers create/update/get/list/delete/validate/import/preview commands
│ │ ├── datastores.py # datastores create/update/get/list/delete/verify/enrichment commands
│ │ ├── export_import.py # config export/import (config-as-code)
│ │ ├── operations.py # operations sync/profile/scan/materialize/export/get/list/abort commands
│ │ ├── mcp_cmd.py # mcp serve CLI command
│ │ ├── computed_tables.py # Internal helpers for computed table import and preview (used by containers.py)
│ │ └── schedule.py # schedule export-metadata command
│ ├── mcp/
│ │ ├── __init__.py
│ │ └── server.py # FastMCP server — all MCP tools (wraps api/ and services/ layer)
│ ├── services/
│ │ ├── quality_checks.py # Quality check business logic
│ │ ├── connections.py # Connection lookup, payload building, name resolution
│ │ ├── containers.py # Container business logic (name resolution, payload building)
│ │ ├── datastores.py # Datastore lookup, payload building, name resolution
│ │ ├── export_import.py # Config-as-code export/import orchestration
│ │ └── operations.py # Operation execution and polling
│ └── utils/
│ ├── validation.py # URL normalization
│ ├── file_ops.py # Error logging, file deduplication
│ ├── secrets.py # Env var resolution and sensitive field redaction
│ └── serialization.py # YAML/JSON load, dump, display, format detection
├── tests/
│ ├── conftest.py # Shared fixtures (cli_runner)
│ ├── test_anomalies.py # Anomaly API + CLI tests
│ ├── test_cli.py # CLI smoke tests (command registration)
│ ├── test_connections.py # Connection API + service + secrets + CLI tests
│ ├── test_containers.py # Container API + service + CLI tests
│ ├── test_datastores.py # Datastore API + service + CLI tests
│ ├── test_export_import.py # Config export/import service + CLI tests
│ ├── test_operations.py # Operation API + service + CLI tests
│ ├── test_client.py # API client unit tests
│ ├── test_config.py # Configuration and token validation tests
│ ├── test_quality_checks.py # Quality checks API + CLI + service tests
│ └── test_serialization.py # Serialization utilities tests
├── pyproject.toml # Project config (hatchling, dependencies, tools)
├── uv.lock # Locked dependency versions (committed)
├── .pre-commit-config.yaml # Pre-commit hooks
├── docs/
│ └── examples/
│ └── github-actions-promotion.md # CI/CD promotion workflow guide
├── AGENTS.md # This file
└── README.md # User-facing documentation
CLI layer (cli/) ← Typer commands, user interaction, argument parsing
↓
Service layer (services/) ← Business logic, orchestration, pagination
↓
API layer (api/) ← Centralized HTTP client, thin wrappers
↓
Config (config.py) ← Load/save/validate configuration
Key rule: Only api/client.py imports requests. All other modules use QualyticsClient.
All HTTP communication goes through the centralized QualyticsClient class:
from qualytics.api.client import get_client
client = get_client() # Loads config, validates token, returns client
response = client.get("quality-checks", params={"datastore": 1})
response = client.post("operations/run", json={"type": "sync", ...})The client provides:
requests.Session-based connection pooling with persistent Bearer auth- Configurable SSL verification (from config)
- Configurable request timeout (default 30s)
- Automatic URL construction from path fragments
Non-2xx responses raise typed exceptions:
QualyticsAPIError (base)
├── AuthenticationError ← 401, 403
├── NotFoundError ← 404
├── ConflictError ← 409
└── ServerError ← 5xx
CLI commands catch specific exceptions for business logic (e.g., ConflictError for upsert patterns in checks import) and let unexpected errors propagate.
SSL verification is secure by default (True) and configurable per installation:
qualytics auth init --no-verify-sslsavesssl_verify: falseto~/.qualytics/config.yamlQualyticsClientreadsssl_verifyfrom configInsecureRequestWarningis suppressed only when SSL is explicitly disabledqualytics auth statusdisplays the current SSL status
Full operation lifecycle management — trigger, monitor, list, and abort operations.
Supported operation types: sync, profile, scan, materialize, export
Architecture:
api/operations.py— 5 thin HTTP wrappers:run_operation,get_operation,list_operations,list_all_operations,abort_operationservices/operations.py— business logic:run_sync,run_profile,run_scan,run_materialize,run_export,wait_for_operation,_handle_operation_resultcli/operations.py— 8 CLI commands underqualytics operations
Polling behavior:
| Setting | Default | CLI Flag |
|---|---|---|
| Poll interval | 10 seconds | --poll-interval |
| Timeout | 1800 seconds (30 min) | --timeout |
- Shows progress counters (containers analyzed, records processed) every 60s for profile/scan
- Returns
Noneon timeout, allowing callers to handle gracefully - Background mode (
--background) skips polling entirely
Git-friendly export/import with upsert support for multi-environment promotion (Dev → Test → Prod).
Export format: One YAML file per check, organized by container subdirectory:
checks/
orders/
notnull__order_id.yaml
between__total_amount.yaml
customers/
matchespattern__email.yaml
Stable UID: Each exported check contains _qualytics_check_uid in additional_metadata, computed as {container}__{rule_type}__{sorted_fields}. This enables upsert on import — matching UIDs update existing checks, new UIDs create new checks.
Portable fields: rule_type, description, container (by name), fields (by name), coverage, filter, properties, tags (by name), status, additional_metadata. Environment-specific fields (IDs, timestamps, anomaly counts) are stripped on export.
Multi-datastore import: checks import --datastore-id 1 --datastore-id 2 processes each datastore independently, resolving container names to IDs within each target.
Anomaly CRUD for CI/CD gating and status management. Anomalies are created by failed quality checks during scan operations — there is no "create" command.
Status model:
- Open statuses (via
updatecommand → PUT/PATCH):Active,Acknowledged - Archive statuses (via
archivecommand → DELETE witharchive=true):Resolved,Invalid,Duplicate,Discarded - Hard delete (via
deletecommand → DELETE witharchive=false): permanent removal
API functions:
list_anomalies()— GET /anomalies with 14+ filter params (datastore, container, quality_check, status, anomaly_type, tag, rule_type, start_date, end_date, timeframe, archived, sort_created, sort_weight)list_all_anomalies()— auto-paginate across all pagesget_anomaly()— GET /anomalies/{id}update_anomaly()— PUT /anomalies/{id} (single, open statuses only)bulk_update_anomalies()— PATCH /anomalies (bulk, open statuses only)delete_anomaly()— DELETE /anomalies/{id} (archive or hard-delete)bulk_delete_anomalies()— DELETE /anomalies (bulk archive or hard-delete)
CLI commands:
get— single anomaly by--idlist— filterable by--datastore-id,--container,--check-id,--status,--type,--tag,--start-date,--end-dateupdate— single (--id) or bulk (--ids), validates open statuses onlyarchive— single or bulk soft-delete with status (default:Resolved)delete— single or bulk hard-delete
CI use case:
# Gate CI pipeline on active anomalies
ANOMALIES=$(qualytics anomalies list --datastore-id $DS --status Active --format json)
COUNT=$(echo "$ANOMALIES" | python -c "import sys,json; print(len(json.load(sys.stdin)))")
if [ "$COUNT" -gt "0" ]; then echo "FAIL: $COUNT active anomalies"; exit 1; fiFull connection lifecycle management — create, update, get, list, delete, and test connections. Connections are the most sensitive resource because they hold database credentials.
Secrets strategy:
- Sensitive CLI flags (
--host,--username,--password,--access-key,--secret-key,--uri) support${ENV_VAR}syntax, resolved viaos.path.expandvars()before being sent to the API - Unresolved
${VAR}placeholders raise an error and abort - All CLI output is redacted via
redact_payload()fromutils/secrets.py - Sensitive fields never touch disk in plaintext
Architecture:
api/connections.py— 7 thin HTTP wrappers:create_connection,update_connection,get_connection_api,list_connections,list_all_connections,delete_connection,test_connectionservices/connections.py— business logic:get_connection_by,get_connection_by_name,build_create_connection_payload,build_update_connection_payloadcli/connections.py— 6 CLI commands underqualytics connections
--parameters JSON catch-all: For type-specific fields that don't have dedicated flags (e.g., --parameters '{"role": "ADMIN", "warehouse": "WH"}'). Merged last, overrides dedicated flags.
CLI commands:
create— inline flags with${ENV_VAR}support,--dry-runsupportupdate— partial update: only provided fields are sentget— by--idor--name, secrets redacted in outputlist— filterable by--name,--type(comma-separated), all connections redacteddelete— by--id, handles 409 when datastores still reference ittest— test existing or with override credentials (--host,--username,--password)
Config-as-code: export and import Qualytics configuration as a hierarchical YAML folder structure for git-tracked, cross-environment deployment.
Folder structure:
qualytics-export/
connections/
prod_pg.yaml
datastores/
prod_warehouse/
_datastore.yaml
containers/
filtered_orders/
_container.yaml
computed_fields/
order_margin.yaml
checks/
orders/
notnull__order_id.yaml
Export behavior:
export_config()fetches connections, datastores, computed containers, computed fields, and quality checks for given datastore IDs- Connections are deduplicated across datastores (exported once by name)
- Secret fields (password, secret_key, etc.) are replaced with
${ENV_VAR}placeholders - Only computed containers are exported (table/view/file are discovered by sync operations)
_write_yaml()only writes when content changes — re-export produces zero git diff- ID references are replaced with name references for portability
Import behavior (dependency order):
- Connections — upsert by
name, resolve${ENV_VAR}from environment - Datastores — upsert by
name, resolveconnection_name→connection_id, link enrichment - Containers — upsert computed containers by
namewithin datastore, resolve name references to IDs - Computed fields — upsert by
namewithin container - Quality checks — reuses existing
import_checks_to_datastore()with_qualytics_check_uidupsert
Natural keys for upsert:
- Connection:
name(globally unique) - Datastore:
name(globally unique) - Container:
namewithin datastore - Computed field:
namewithin container - Quality check:
_qualytics_check_uidinadditional_metadata
CLI commands:
config export --datastore-id <id> [--output <dir>] [--include <types>]config import --input <dir> [--dry-run] [--include <types>]
--include filter: Comma-separated resource types to include: connections,datastores,containers,computed_fields,checks. Defaults to all.
Full datastore lifecycle management — create, update, get, list, delete, verify connections, and manage enrichment links.
Architecture:
api/datastores.py— 10 thin HTTP wrappers:create_datastore,update_datastore,get_datastore,list_datastores,list_all_datastores,delete_datastore,verify_connection,validate_connection,connect_enrichment,disconnect_enrichmentservices/datastores.py— business logic:get_datastore_by,get_datastore_by_name,build_create_datastore_payload,build_update_datastore_payloadcli/datastores.py— 7 CLI commands underqualytics datastores
CLI commands:
create— create with--connection-name(YAML lookup + auto-create) or--connection-id,--dry-runsupportupdate— partial update: name, connection, database, schema, tags, teams, enrichment settingsget— by--idor--namewith--format yaml|jsonlist— paginated with--name,--type,--tag,--enrichment-onlyfiltersdelete— by--idverify— test connection for an existing datastore (CI health checks)enrichment—--link <id>to connect or--unlinkto disconnect enrichment datastore
Full container lifecycle management — create computed containers, update, get, list, delete, and validate definitions.
Container types: 6 total (table, view, file, computed_table, computed_file, computed_join). Only the 3 computed types can be created/updated via CLI — non-computed types are created during sync operations.
Architecture:
api/containers.py— 9 thin HTTP wrappers:create_container,update_container,get_container,list_containers,list_all_containers,delete_container,validate_container,get_field_profiles,list_containers_listingservices/containers.py— business logic:get_table_ids,get_container_by_name,build_create_container_payload,build_update_container_payloadcli/containers.py— 8 CLI commands underqualytics containers
Polymorphic create: The --type flag discriminates between computed types, each requiring different fields:
computed_table:--datastore-id,--name,--querycomputed_file:--datastore-id,--name,--source-container-id,--select-clausecomputed_join:--name,--left-container-id,--right-container-id,--left-key-field,--right-key-field,--select-clause
Update pattern (GET-merge-PUT): Updates fetch the existing container, overlay user changes via build_update_container_payload(), and PUT the merged payload. The container_type discriminator is always preserved.
409 handling: When updating a computed container would drop fields that have associated quality checks or anomalies, the API returns 409. The CLI prints what would be dropped and fails unless --force-drop-fields is passed.
CLI commands:
create— polymorphic by--type, with--dry-runsupportupdate— GET-merge-PUT with--force-drop-fieldsfor 409 conflictsget— by--id, optional--profilesto include field profileslist— requires--datastore-id, filterable by--type,--name,--tag,--search,--archiveddelete— by--id(cascades to fields, checks, anomalies)validate— dry-run validation of computed container definitions against the APIimport— bulk import computed tables from file (.xlsx, .csv, .txt) with auto-check creationpreview— preview computed table definitions from file without importing
YAML is the default format for all CLI input/output. JSON is supported via --format json.
Key conventions:
- Default export/import files use
.yamlextension --format yaml|jsonflag on export and display commands (checks export, datastore list/get/create)- Import commands auto-detect format by file extension (
.json→ JSON, everything else → YAML) - Smart inference:
--output file.jsonwith default--format yamlinfers JSON _SafeStringLoaderprevents YAML from parsing ISO date strings asdatetimeobjectsyaml.safe_dump(sort_keys=False)preserves key order for human-readable output
from qualytics.utils import OutputFormat, load_data_file, dump_data_file, format_for_display
data = load_data_file("checks.yaml") # Auto-detects format
dump_data_file(data, "out.yaml", OutputFormat.YAML)
print(format_for_display(data, OutputFormat.JSON))Model Context Protocol server for LLM tool integrations (Claude Code, Cursor, Windsurf).
Architecture: MCP tools call the same api/ and services/ functions as the CLI, just without the Typer/Rich formatting layer. Returns raw dicts/lists for structured JSON responses.
CLI layer (typer/rich) → services/ → api/ → Qualytics API
↑
MCP layer (fastmcp) ─────────┘
35 MCP tools across 8 groups: auth, connections, datastores, containers, checks, anomalies, operations, config.
Error handling: _client() converts SystemExit → ToolError. _api_call() converts QualyticsAPIError → ToolError. LLMs see structured error messages.
Setup for Claude Code (~/.claude.json):
{
"mcpServers": {
"qualytics": {
"command": "qualytics",
"args": ["mcp", "serve"]
}
}
}| File | Purpose |
|---|---|
config.yaml |
URL, token, ssl_verify (auto-migrated from legacy config.json) |
data_checks.yaml |
Default checks export location |
data_checks_template.yaml |
Default templates export location |
errors-{date}.log |
Import operation errors |
operation-error.txt |
Operation execution errors |
logs/ |
Debug logs (containers import --debug) |
JWT tokens are validated for expiration before each operation. Expired tokens produce a warning and exit.
| Command Group | Subcommands | Description |
|---|---|---|
auth |
login, status, init |
Authentication: browser login, status display, manual token init |
anomalies |
get, list, update, archive, delete |
Anomaly management (status updates, archiving, deletion) |
checks |
create, get, list, update, delete, export, import, export-templates, import-templates |
Quality check CRUD + git-friendly export/import |
config |
export, import |
Config-as-code: export/import connections, datastores, containers, and checks as hierarchical YAML |
connections |
create, update, get, list, delete, test |
Connection CRUD with secrets management + connectivity testing |
containers |
create, update, get, list, delete, validate, import, preview |
Container CRUD + validation + bulk import |
datastores |
create, update, get, list, delete, verify, enrichment |
Datastore CRUD + connection verification + enrichment linking |
operations |
sync, profile, scan, materialize, export, get, list, abort |
Operation lifecycle (trigger, monitor, abort) |
mcp |
serve |
MCP server for Claude Code, Cursor, and other LLM tools |
schedule |
export-metadata |
Cron-based export scheduling |
init |
— | Deprecated → auth init |
show-config |
— | Deprecated → auth status |
- Backend: hatchling (PEP 517/621 compliant)
- Package manager: uv (dependency resolution, lockfile, building, publishing, versioning)
- Entry point:
qualyticsconsole script →qualytics.qualytics:app
| Package | Purpose |
|---|---|
| typer | CLI framework |
| rich | Terminal output (tables, progress bars, colors) |
| requests | HTTP client (used only in api/client.py) |
| pyjwt | JWT token validation |
| croniter | Cron expression validation |
| pyyaml | YAML serialization (config, export/import, display) |
| openpyxl | Excel file reading |
| fastmcp | MCP (Model Context Protocol) server framework (v3) |
| urllib3 | SSL warning suppression |
| Package | Purpose |
|---|---|
| ruff | Linting and formatting |
| pre-commit | Git hook automation |
| pytest | Test framework |
| pytest-cov | Coverage reporting |
Three GitHub Actions workflows work together:
Triggers on pull requests to main:
- Linting:
ruff check - Formatting:
ruff format --check - Tests:
pytestacross Python 3.10, 3.11, 3.12, 3.13, 3.14 - Pre-commit: all hooks
Triggered manually from GitHub Actions UI:
- Accepts
bumpinput:patch,minor, ormajor - Runs
uv version --bump {input} - Commits
pyproject.toml+uv.lock - Creates git tag
v{version} - Pushes to
mainwith tags (triggers publish.yml)
Triggers on v* tags:
- Builds wheel + sdist with
uv build - Publishes to PyPI via OIDC trusted publishing (no stored secrets)
- Creates GitHub Release with the tag
Manual trigger → release.yml → tag push → publish.yml → PyPI + GitHub Release
uv run pytest # Run all tests
uv run pytest -v # Verbose output
uv run pytest --cov --cov-report=term-missing # With coverage| File | Coverage |
|---|---|
test_auth.py |
Auth commands: callback server, login flow, status display, init, deprecated wrappers |
test_cli.py |
Smoke tests: CLI loads, all command groups registered |
test_mcp.py |
MCP server: tool registration, auth status, helpers, all tool groups, CLI command |
test_client.py |
QualyticsClient: URL building, SSL config, exception hierarchy, get_client factory |
test_config.py |
Config loading, saving, token validation, legacy JSON migration |
test_anomalies.py |
API layer (list, get, update, bulk update, delete, bulk delete), CLI commands (get, list, update, archive, delete), status validation, bulk operations |
test_connections.py |
API layer (create, update, get, list, list_all, delete, test), service layer (get_connection_by, build payloads), secrets (env var resolution, redaction), CLI commands (create, update, get, list, delete, test), 409 handling |
test_export_import.py |
Helpers (slugify, write_yaml, env var names), strip functions (connections, datastores, containers), import functions (connections, datastores, containers with upsert), export orchestrator (full, filtered, deduplication), import orchestrator (full, filtered), CLI commands (export, import, dry-run, error display) |
test_containers.py |
API layer (create, update, get, list, list_all, delete, validate, field_profiles, listing), service layer (get_container_by_name, build payloads), CLI commands (create, update, get, list, delete, validate), polymorphic create, 409 handling |
test_datastores.py |
API layer (create, update, get, list, list_all, delete, verify, validate, enrichment connect/disconnect), service layer (get_datastore_by, build payloads), CLI commands (create, update, get, list, delete, verify, enrichment), validation |
test_operations.py |
API layer (run, get, list, list_all, abort), service layer (polling, multi-datastore, background mode, payload construction), CLI commands (sync, profile, scan, materialize, export, get, list, abort), validation |
test_quality_checks.py |
API layer (endpoints, params, pagination), CLI commands (all 9), service import (upsert, dry-run, multi-datastore), promotion workflow, edge cases |
test_serialization.py |
Format detection, YAML/JSON load/dump, datetime preservation, display formatting |
- Fixtures in
conftest.py(e.g.,cli_runner) - Use
unittest.mock.patchfor external dependencies - Patch at the source module (e.g.,
qualytics.config.load_config, notqualytics.api.client.load_config)
| Hook | Purpose |
|---|---|
| pre-commit-hooks (v6.0.0) | Large files, JSON/TOML/YAML validation, trailing whitespace, private key detection |
| ruff-check + ruff-format (v0.15.1) | Linting and formatting |
| pyupgrade (v3.21.2) | Enforce Python 3.10+ idioms |
- Line length: 88
- Target: Python 3.10
- Lint rules: E4, E7, E9, F (pycodestyle + pyflakes)
- Quote style: double
- Import sorting: isort with
qualyticsas first-party
Use Python 3.10+ syntax everywhere. Do not use from __future__ import annotations or legacy typing imports:
| Use | Instead of |
|---|---|
str | None |
Optional[str] |
list[str] |
List[str] |
dict[str, Any] |
Dict[str, Any] |
tuple[str, ...] |
Tuple[str, ...] |
Only import from typing when needed for constructs that have no builtin equivalent (e.g., Annotated, Any, Callable, Literal).
# Setup
uv sync # Install all dependencies
uv run pre-commit install # Install git hooks
# Day-to-day
uv run qualytics --help # Run CLI
uv run pytest # Run tests
uv run ruff check . # Lint
uv run ruff format . # Format
uv run pre-commit run --all-files # All quality checks
# Build & version
uv build # Build wheel + sdist
uv version --short # Show current version- Create or edit a file in
cli/with a Typer sub-app - Use
get_client()fromapi/client.pyfor API calls — never importrequestsdirectly - Catch
QualyticsAPIErrorsubclasses for expected error conditions - Register the sub-app in
qualytics/qualytics.py - Add smoke test in
tests/test_cli.py - Run
uv run pre-commit run --all-filesbefore committing
- Add function to the appropriate
services/module - Accept
client: QualyticsClientas the first parameter - Use
client.get(),client.post(), etc. — the client handles auth, SSL, and error raising - Let exceptions propagate to the CLI layer for user-facing error messages
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /anomalies |
List anomalies (paginated, with filters) |
| GET | /anomalies/{id} |
Get a single anomaly |
| PUT | /anomalies/{id} |
Update anomaly (status, description, tags) |
| PATCH | /anomalies |
Bulk update anomalies |
| DELETE | /anomalies/{id} |
Delete/archive a single anomaly |
| DELETE | /anomalies |
Bulk delete/archive anomalies |
| GET | /quality-checks |
Fetch quality checks (paginated) |
| POST | /quality-checks |
Create quality checks |
| GET | /quality-checks/{id} |
Get a single quality check |
| PUT | /quality-checks/{id} |
Update quality checks |
| DELETE | /quality-checks/{id} |
Delete a single quality check |
| DELETE | /quality-checks |
Bulk delete quality checks |
| POST | /containers |
Create computed containers |
| PUT | /containers/{id} |
Update container (full PUT) |
| GET | /containers/{id} |
Get container by ID |
| GET | /containers |
List containers (paginated, with filters) |
| DELETE | /containers/{id} |
Delete container (cascades) |
| POST | /containers/validate |
Validate computed container definition |
| GET | /containers/{id}/field-profiles |
Get field profiles |
| GET | /containers/listing |
Lightweight container listing (non-paginated) |
| POST | /operations/run |
Trigger operations (sync, profile, scan, materialize, export) |
| GET | /operations/{id} |
Get operation detail with progress counters |
| GET | /operations |
List operations (paginated, with filters) |
| PUT | /operations/abort/{id} |
Abort a running operation (best-effort) |
| POST | /connections |
Create a connection |
| PUT | /connections/{id} |
Update a connection (partial PUT) |
| GET | /connections/{id} |
Get a single connection |
| GET | /connections |
List connections (paginated, with filters) |
| DELETE | /connections/{id} |
Delete a connection (409 if datastores reference it) |
| POST | /connections/{id}/test |
Test connection (optionally with override credentials) |
| POST | /datastores |
Create datastores |
| PUT | /datastores/{id} |
Update datastores |
| GET | /datastores/{id} |
Get datastore by ID |
| GET | /datastores |
List datastores (paginated, with filters) |
| DELETE | /datastores/{id} |
Delete datastores |
| POST | /datastores/{id}/connection |
Verify datastore connection |
| POST | /datastores/connection |
Validate connection pre-creation |
| PATCH | /datastores/{id}/enrichment/{eid} |
Link enrichment datastore |
| DELETE | /datastores/{id}/enrichment |
Unlink enrichment datastore |
| POST | /export/check-templates |
Export templates to enrichment |
All requests use Bearer token authentication via the QualyticsClient session headers:
Authorization: Bearer {jwt_token}
Content-Type: application/json
| Issue | Symptom | Solution |
|---|---|---|
| Token expired | "Your token is expired" warning | Run qualytics auth login or qualytics auth init with a new token |
| SSL errors | Certificate verification failures | Use qualytics auth init --no-verify-ssl (not recommended for production) |
| Profile not found | "Profile {name} was not found" |
Verify container exists in target datastore |
| Operation timeout | "timed out after Xs" | Increase --timeout value |
| Import conflicts | Quality check already exists | CLI automatically updates (upsert pattern) |
| Operation failures | Check ~/.qualytics/operation-error.txt |
Review error details in log file |