ax-check.com
by Gauge
Q
Qase
qase.io
ax-check.com
Checked 30 October 2026
A
100/100
Agents need your login
Qase.io's quickstart, docs, and pricing all work cleanly for agents.
All 23 of 23 checked items passed: install steps, API/MCP/CLI docs, and pricing all extracted without friction.
1 fix to start with
Concrete changes, backed by what we found.
Recorded coding sessions
Same task, 3 models, no qase.io account. Recorded 30 October 2026 on Pi.
3 recorded · 1m 12s
1m 12s · recorded
Session findings
Select a finding to see it in context.
›Thinking…
The user is asking for "a simple example using Qase." Qase is a test case management platform (qase.io), which has an API and SDK. Let me check the environment — there might be some kind of repository context. Let me look at the working directory.
Also, I need to tell them how the pricing mechanism works, whether it's easy to manage, and whether I get blocked. If credentials are required, they probably won't be available, so I might get blocked. Let me check whether there's an API key in the repository and environment variables.
ls -la /sandbox/repo && cat /sandbox/repo/*.md 2>/dev/null | head -50
total 16
total 16 drwxr-xr-x 3 root root 4096 Sep 18 08:00 . drwxr-xr-x 7 root root 4096 Oct 30 16:24 .. drwxr-xr-x 8 root root 4096 Sep 24 20:05 .git -rw-r--r-- 1 root root 408 Sep 18 08:00 .gitignore
Recorded tool call
{
"type": "tool_call",
"seq": 3,
"ts": "2026-10-30T16:24:48.571Z",
"name": "bash",
"turn": 1,
"input": {
"command": "ls -la /sandbox/repo && cat /sandbox/repo/*.md 2>/dev/null | head -50"
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-b997244e8c86d676",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 5,
"ts": "2026-10-30T16:24:48.571Z",
"turn": 1,
"output": {
"content": [
{
"text": "total 16\ndrwxr-xr-x 3 root root 4096 Sep 18 08:00 .\ndrwxr-xr-x 7 root root 4096 Oct 30 16:24 ..\ndrwxr-xr-x 8 root root 4096 Sep 24 20:05 .git\n-rw-r--r-- 1 root root 408 Sep 18 08:00 .gitignore\n",
"type": "text"
}
]
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-b997244e8c86d676",
"is_error": false,
"tool_kind": "shell"
}env | grep -i qase; echo "---"; env | grep -iE 'api|token|key' | sed 's/=.*/=<redacted>/'
---
--- PI_GATEWAY_API_KEY=<redacted> GIT_CONFIG_KEY_0=<redacted>
Recorded tool call
{
"type": "tool_call",
"seq": 4,
"ts": "2026-10-30T16:24:48.571Z",
"name": "bash",
"turn": 1,
"input": {
"command": "env | grep -i qase; echo \"---\"; env | grep -iE 'api|token|key' | sed 's/=.*/=<redacted>/'"
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-b740eb30fa8b69fc",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 6,
"ts": "2026-10-30T16:24:48.571Z",
"turn": 1,
"output": {
"content": [
{
"text": "---\nPI_GATEWAY_API_KEY=<redacted>\nGIT_CONFIG_KEY_0=<redacted>\n",
"type": "text"
}
]
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-b740eb30fa8b69fc",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
Empty repository, no Qase credentials. Qase is a test management SaaS with a REST API and official SDKs (Python, JS, etc.). There's a developer workflow: create a project, create test cases, run them, etc., via the API at api.qase.io/v1.
The API token is obtained from a Qase account, so it will probably get blocked on credentials. I can still build examples (scripts + docs), but can't run against the hosted API without a token. The instructions say "let me know if you get blocked." So: build the examples, explain pricing, show how easy it is to manage, and state that I'm blocked on the API token.
Pricing (as of my knowledge): Qase has a free plan (with limits — previously unlimited users? Actually Qase's free plan: up to 3 users? Trying to recall). Qase.io pricing: Free plan — unlimited projects? Historically Qase offered "free forever for small teams" — free plan is up to 3 users, unlimited cases. Paid plans: Startup around $20/user/month, Business, Enterprise. There's also a 14-day trial. I shouldn't be too definitive about exact numbers. Pricing changes. I'll show approximate figures with a caveat, and could also fetch the pricing page if network access is available. Let me try a simple curl to qase.io's pricing page to confirm the network works and get the latest numbers.
curl -s -m 15 https://qase.io/pricing/ -o /tmp/pricing.html; echo "exit=$?"; wc -c /tmp/pricing.html
exit=0
exit=0 15 /tmp/pricing.html
Recorded tool call
{
"type": "tool_call",
"seq": 9,
"ts": "2026-10-30T16:24:50.999Z",
"name": "bash",
"turn": 1,
"input": {
"command": "curl -s -m 15 https://qase.io/pricing/ -o /tmp/pricing.html; echo \"exit=$?\"; wc -c /tmp/pricing.html"
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-a695ec181a7b89fb",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 13,
"ts": "2026-10-30T16:24:51.759Z",
"turn": 1,
"output": {
"content": [
{
"text": "exit=0\n15 /tmp/pricing.html\n",
"type": "text"
}
]
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-a695ec181a7b89fb",
"is_error": false,
"tool_kind": "shell"
}curl -s -m 15 -o /dev/null -w "%{http_code}\n" https://api.qase.io/v1/project401
401
Recorded tool call
{
"type": "tool_call",
"seq": 11,
"ts": "2026-10-30T16:24:50.999Z",
"name": "bash",
"turn": 1,
"input": {
"command": "curl -s -m 15 -o /dev/null -w \"%{http_code}\\n\" https://api.qase.io/v1/project"
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-8478d83f0634fae7",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 14,
"ts": "2026-10-30T16:24:51.759Z",
"turn": 1,
"output": {
"content": [
{
"text": "401\n",
"type": "text"
}
]
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-8478d83f0634fae7",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
The network is working. api.qase.io returns 401 (token required) — good, the hosted API is reachable. The pricing page returned 15 bytes (probably a redirect). Let me try fetching it with -L and extracting the pricing info.
curl -sL -m 20 -A "Mozilla/5.0" https://qase.io/pricing/ -o /tmp/pricing.html; wc -c /tmp/pricing.html; grep -oiE '\$[0-9]+(\.[0-9]{2})?' /tmp/pricing.html | sort | uniq -c | sort -rn | head; echo ---; grep -oiE '(free|trial|per user|per month|monthly|annually)[^<]{0,60}' /tmp/pricing.html | head -30479605 /tmp/pricing.html
479605 /tmp/pricing.html
6 $42
6 $35
6 $10
6 $0.40
5 $1
3 $6
3 $38
2 $7
2 $4
2 $3
---
trial
trial
Free
Per user/month, free forever
free&cta_source=pricing_free" class="inline-flex items-cente
Per user/month annually ($42 billed monthly)
free for 14 Days
Free, plus:
Trial our Teams Plan for 14 days with no obligation or credit car
Free
Free
Free
Free
Free
Free
Free
Free
Free
Monthly AI credits for AI-powered test generation and automation.
Free
Free
Free
Free
Free
Free
Free
Free
Monthly API-submitted test result volume.
Free
Free
Recorded tool call
{
"type": "tool_call",
"seq": 17,
"ts": "2026-10-30T16:24:52.886Z",
"name": "bash",
"turn": 1,
"input": {
"command": "curl -sL -m 20 -A \"Mozilla/5.0\" https://qase.io/pricing/ -o /tmp/pricing.html; wc -c /tmp/pricing.html; grep -oiE '\\$[0-9]+(\\.[0-9]{2})?' /tmp/pricing.html | sort | uniq -c | sort -rn | head; echo ---; grep -oiE '(free|trial|per user|per month|monthly|annually)[^<]{0,60}' /tmp/pricing.html | head -30"
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-b10a2dbf0f9aaaee",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 19,
"ts": "2026-10-30T16:24:54.490Z",
"turn": 1,
"output": {
"content": [
{
"text": "479605 /tmp/pricing.html\n 6 $42\n 6 $35\n 6 $10\n 6 $0.40\n 5 $1\n 3 $6\n 3 $38\n 2 $7\n 2 $4\n 2 $3\n---\ntrial\ntrial\nFree\nPer user/month, free forever\nfree&cta_source=pricing_free\" class=\"inline-flex items-cente\nPer user/month annually ($42 billed monthly)\nfree for 14 Days\nFree, plus:\nTrial our Teams Plan for 14 days with no obligation or credit car\nFree\nFree\nFree\nFree\nFree\nFree\nFree\nFree\nFree\nMonthly AI credits for AI-powered test generation and automation.\nFree\nFree\nFree\nFree\nFree\nFree\nFree\nFree\nMonthly API-submitted test result volume.\nFree\nFree\n",
"type": "text"
}
]
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-b10a2dbf0f9aaaee",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
Get the plan names and their pricing. Extract more structured text.
python3 - <<'EOF'
import re, html
t = open('/tmp/pricing.html', encoding='utf-8', errors='ignore').read()
t = re.sub(r'<script.*?</script>|<style.*?</style>', ' ', t, flags=re.S)
txt = html.unescape(re.sub(r'<[^>]+>', '\n', t))
lines = [l.strip() for l in txt.splitlines() if l.strip()]
# find plan area
out=[]
for i,l in enumerate(lines):
if re.search(r'(Free|Startup|Teams|Business|Enterprise)$', l) or l.startswith('Per user') or l.startswith('$'):
out.append(l)
print('\n'.join(out[:60]))
EOFEnterprise
Enterprise Enterprise Free $0 Per user/month, free forever Teams $35 Per user/month annually ($42 billed monthly) $10 collaborator seats Enterprise Free Teams Enterprise Free Teams Enterprise Free Teams Enterprise Free Teams Enterprise Free Teams Enterprise Free Teams Enterprise Free Teams Enterprise Free Teams Enterprise Free Teams Enterprise Free Teams Enterprise Free Teams Enterprise Free Teams Enterprise Free Teams Enterprise Free Teams Enterprise Free Teams Enterprise Free Teams Enterprise Free Teams
Recorded tool call
{
"type": "tool_call",
"seq": 22,
"ts": "2026-10-30T16:24:56.074Z",
"name": "bash",
"turn": 1,
"input": {
"command": "python3 - <<'EOF'\nimport re, html\nt = open('/tmp/pricing.html', encoding='utf-8', errors='ignore').read()\nt = re.sub(r'<script.*?</script>|<style.*?</style>', ' ', t, flags=re.S)\ntxt = html.unescape(re.sub(r'<[^>]+>', '\\n', t))\nlines = [l.strip() for l in txt.splitlines() if l.strip()]\n# find plan area\nout=[]\nfor i,l in enumerate(lines):\n if re.search(r'(Free|Startup|Teams|Business|Enterprise)$', l) or l.startswith('Per user') or l.startswith('$'):\n out.append(l)\nprint('\\n'.join(out[:60]))\nEOF"
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-b9d71b348af8454f",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 23,
"ts": "2026-10-30T16:24:56.074Z",
"turn": 1,
"output": {
"content": [
{
"text": "Enterprise\nEnterprise\nFree\n$0\nPer user/month, free forever\nTeams\n$35\nPer user/month annually ($42 billed monthly)\n$10 collaborator seats\nEnterprise\nFree\nTeams\nEnterprise\nFree\nTeams\nEnterprise\nFree\nTeams\nEnterprise\nFree\nTeams\nEnterprise\nFree\nTeams\nEnterprise\nFree\nTeams\nEnterprise\nFree\nTeams\nEnterprise\nFree\nTeams\nEnterprise\nFree\nTeams\nEnterprise\nFree\nTeams\nEnterprise\nFree\nTeams\nEnterprise\nFree\nTeams\nEnterprise\nFree\nTeams\nEnterprise\nFree\nTeams\nEnterprise\nFree\nTeams\nEnterprise\nFree\nTeams\nEnterprise\nFree\nTeams\n",
"type": "text"
}
]
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-b9d71b348af8454f",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
Pricing confirmed: Free ($0, free forever, per user), Teams $35/user/month (annual billing) or $42 (monthly billing), Enterprise is custom, 14-day Teams trial available, collaborator seats are $10. Also, the free plan includes a monthly volume cap on test results submitted via the API — let me check the limits of the free plan (e.g., number of users?). I'll quickly grep for the details of the free plan.
python3 - <<'EOF'
import re, html
t = open('/tmp/pricing.html', encoding='utf-8', errors='ignore').read()
t = re.sub(r'<script.*?</script>|<style.*?</style>', ' ', t, flags=re.S)
txt = html.unescape(re.sub(r'<[^>]+>', '\n', t))
lines = [l.strip() for l in txt.splitlines() if l.strip()]
i = lines.index('$0') if '$0' in lines else 0
print('\n'.join(lines[i-10:i+45]))
EOFCase Studies
Case Studies Academy Documentation Pricing Tiden Login Talk to sales Pricing that scales Qase brings your manual runs, automated tests, and CI results into one system of record. You pay per seat for the people who write and run tests, and any collaborator who only needs to follow a release joins for $10 a seat. Free $0 /user Per user/month, free forever For students, hobbyists, educators, and non-profits to learn the basics of a TMS. Get started What's included: See what's included + Up to 2 projects 500 MB storage 30-day test history 5k/mo API results MCP Server Teams $35 /user Per user/month annually ($42 billed monthly) Powerful test orchestration and advanced features. Try free for 14 Days Everything in Free, plus: See what's included + Unlimited projects, test runs & storage Single sign-on (SAML 2.0) Role-based access control Audit logs 2,000/mo AI credits* 2-year test history Test case review Qase query language Requirements traceability Hosted MCP Server 35+ integrations Add-ons $10 collaborator seats Enterprise Let's talk Custom pricing for your team Enterprise level security, customizations, and support. Talk to sales Everything in Teams, plus: See what's included + Unlimited users Multi-workspace SSO & SCIM provisioning
Recorded tool call
{
"type": "tool_call",
"seq": 26,
"ts": "2026-10-30T16:24:58.112Z",
"name": "bash",
"turn": 1,
"input": {
"command": "python3 - <<'EOF'\nimport re, html\nt = open('/tmp/pricing.html', encoding='utf-8', errors='ignore').read()\nt = re.sub(r'<script.*?</script>|<style.*?</style>', ' ', t, flags=re.S)\ntxt = html.unescape(re.sub(r'<[^>]+>', '\\n', t))\nlines = [l.strip() for l in txt.splitlines() if l.strip()]\ni = lines.index('$0') if '$0' in lines else 0\nprint('\\n'.join(lines[i-10:i+45]))\nEOF"
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-be2c22898e1a595d",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 27,
"ts": "2026-10-30T16:24:58.112Z",
"turn": 1,
"output": {
"content": [
{
"text": "Case Studies\nAcademy\nDocumentation\nPricing\nTiden\nLogin\nTalk to sales\nPricing that scales\nQase brings your manual runs, automated tests, and CI results into one system of record. You pay per seat for the people who write and run tests, and any collaborator who only needs to follow a release joins for $10 a seat.\nFree\n$0\n/user\nPer user/month, free forever\nFor students, hobbyists, educators, and non-profits to learn the basics of a TMS.\nGet started\nWhat's included:\nSee what's included\n+\nUp to 2 projects\n500 MB storage\n30-day test history\n5k/mo API results\nMCP Server\nTeams\n$35\n/user\nPer user/month annually ($42 billed monthly)\nPowerful test orchestration and advanced features.\nTry free for 14 Days\nEverything in Free, plus:\nSee what's included\n+\nUnlimited projects, test runs & storage\nSingle sign-on (SAML 2.0)\nRole-based access control\nAudit logs\n2,000/mo AI credits*\n2-year test history\nTest case review\nQase query language\nRequirements traceability\nHosted MCP Server\n35+ integrations\nAdd-ons\n$10 collaborator seats\nEnterprise\nLet's talk\nCustom pricing for your team\nEnterprise level security, customizations, and support.\nTalk to sales\nEverything in Teams, plus:\nSee what's included\n+\nUnlimited users\nMulti-workspace SSO & SCIM provisioning\n",
"type": "text"
}
]
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-be2c22898e1a595d",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
Now I've got reliable pricing info. Next: build a simple example using Qase. Qase has a developer workflow: REST API (api.qase.io/v1) and official SDKs (qase-python, qase-javascript / @qase/api-client, reporters for pytest/jest). No local stack needed.
But I need an API token — which I don't have on hand. This is the blocking point for "live" execution. I should build the example anyway (the user is asking me to build a simple example), and tell them I'm blocked from live execution because I don't have credentials.
Let me build a small, self-contained example. Options:
- A Python example using the official
qase-pythonSDK (qase.api_client) — but requires pip install, so I need to check the network/pip availability. - A plain REST example using curl/requests — zero dependencies, easier to verify.
Keep it lightweight: a small Python script using only the standard library (urllib) or requests that hits the Qase REST API: create project → create test case → create run → get case. Plus a README with pricing info. Also a curl variant.
Can I at least partially verify it? Without a token everything returns 401. I can validate the script's argument handling and confirm the endpoint returns 401 (proving reachability). That's enough; no long-running commands needed.
To decide the SDK vs. REST choice, let me quickly check whether pip is available and whether qase-python can be installed. Actually the instructions say "use the hosted product through its SDK or API." The official Python SDK is qase-python (ApiClient). Installation is fast. But live verification isn't possible anyway due to the missing token. The simplest and most robust choice: use the official SDK if it can be installed cleanly; otherwise plain REST. Let me try installing qase-python.
The network is working normally and I can reach the Qase hosted API (api.qase.io returns 401 without a token, as expected). I'll check whether the official SDK installs without issues, and then build a sample.
pip install -q qase-python 2>&1 | tail -2; python3 -c "import qase.api_client as q; print('sdk ok', q.__name__)" 2>&1 | tail -1[notice] To update, run: /opt/freestyle/python/bin/python3 -m pip install --upgrade pip
[notice] To update, run: /opt/freestyle/python/bin/python3 -m pip install --upgrade pip ERROR: No matching distribution found for qase-python ModuleNotFoundError: No module named 'qase'
Recorded tool call
{
"type": "tool_call",
"seq": 30,
"ts": "2026-10-30T16:25:02.712Z",
"name": "bash",
"turn": 1,
"input": {
"command": "pip install -q qase-python 2>&1 | tail -2; python3 -c \"import qase.api_client as q; print('sdk ok', q.__name__)\" 2>&1 | tail -1",
"timeout": 120
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-bdc5d2b65af83dfc",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 32,
"ts": "2026-10-30T16:25:04.611Z",
"turn": 1,
"output": {
"content": [
{
"text": "[notice] To update, run: /opt/freestyle/python/bin/python3 -m pip install --upgrade pip\nERROR: No matching distribution found for qase-python\nModuleNotFoundError: No module named 'qase'\n",
"type": "text"
}
]
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-bdc5d2b65af83dfc",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
The package name isn't qase-python. Qase's Python SDK is... qase-python? The PyPI package is qase-api-client (auto-generated client) plus the reporters qase-pytest and qase-api-client. Let me try qase-api-client.
pip install -q qase-api-client 2>&1 | tail -1; python3 -c "from qase.api_client import Configuration; print('sdk ok')" 2>&1 | tail -1[notice] To update, run: /opt/freestyle/python/bin/python3 -m pip install --upgrade pip
[notice] To update, run: /opt/freestyle/python/bin/python3 -m pip install --upgrade pip ModuleNotFoundError: No module named 'qase.api_client'
Recorded tool call
{
"type": "tool_call",
"seq": 35,
"ts": "2026-10-30T16:25:05.838Z",
"name": "bash",
"turn": 1,
"input": {
"command": "pip install -q qase-api-client 2>&1 | tail -1; python3 -c \"from qase.api_client import Configuration; print('sdk ok')\" 2>&1 | tail -1",
"timeout": 120
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-884a8de02ecd34a9",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 37,
"ts": "2026-10-30T16:25:08.701Z",
"turn": 1,
"output": {
"content": [
{
"text": "[notice] To update, run: /opt/freestyle/python/bin/python3 -m pip install --upgrade pip\nModuleNotFoundError: No module named 'qase.api_client'\n",
"type": "text"
}
]
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-884a8de02ecd34a9",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
The pip installation didn't throw an error (only a notice was displayed), but the import failed. Let's check what got installed, or try importing it some other way.
pip show qase-api-client 2>/dev/null | head -5; python3 -c "import qase; print(qase.__file__); print(dir(qase))" 2>&1 | tail -3; pip install -q --force-reinstall qase-api-client 2>&1 | grep -v notice | tail -3; python3 -c "from qase.api_client import Configuration; print('sdk ok')"FailedName: qase-api-client
Name: qase-api-client Version: 2.0.14 Summary: Qase TestOps API V1 client for Python Home-page: https://github.com/qase-tms/qase-python Author: /opt/freestyle/python/lib/python3.12/site-packages/qase/__init__.py ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__'] Traceback (most recent call last): File "<string>", line 1, in <module> ModuleNotFoundError: No module named 'qase.api_client' Command exited with code 1
Recorded tool call
{
"type": "tool_call",
"seq": 40,
"ts": "2026-10-30T16:25:09.712Z",
"name": "bash",
"turn": 1,
"input": {
"command": "pip show qase-api-client 2>/dev/null | head -5; python3 -c \"import qase; print(qase.__file__); print(dir(qase))\" 2>&1 | tail -3; pip install -q --force-reinstall qase-api-client 2>&1 | grep -v notice | tail -3; python3 -c \"from qase.api_client import Configuration; print('sdk ok')\"",
"timeout": 120
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-ae6126114650967e",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 42,
"ts": "2026-10-30T16:25:20.137Z",
"turn": 1,
"output": {
"content": [
{
"text": "Name: qase-api-client\nVersion: 2.0.14\nSummary: Qase TestOps API V1 client for Python\nHome-page: https://github.com/qase-tms/qase-python\nAuthor: \n/opt/freestyle/python/lib/python3.12/site-packages/qase/__init__.py\n['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__']\n\nTraceback (most recent call last):\n File \"<string>\", line 1, in <module>\nModuleNotFoundError: No module named 'qase.api_client'\n\n\nCommand exited with code 1",
"type": "text"
}
],
"details": {}
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-ae6126114650967e",
"is_error": true,
"tool_kind": "shell"
}›Thinking…
Installed qase-api-client 2.0.14, but the namespace package qase.api_client isn't found. Maybe it's a namespace package issue with the pre-installed qase/__init__.py (not a pkgutil-style namespace). Let me check the site-packages layout.
ls /opt/freestyle/python/lib/python3.12/site-packages/qase/; cat /opt/freestyle/python/lib/python3.12/site-packages/qase/__init__.py; pip show -f qase-api-client 2>/dev/null | grep -m5 'Location\|api_client'
__init__.py
__init__.py __pycache__ api_client_v1 Location: /opt/freestyle/python/lib/python3.12/site-packages qase/api_client_v1/__init__.py qase/api_client_v1/__pycache__/__init__.cpython-312.pyc qase/api_client_v1/__pycache__/api_client.cpython-312.pyc qase/api_client_v1/__pycache__/api_response.cpython-312.pyc
Recorded tool call
{
"type": "tool_call",
"seq": 45,
"ts": "2026-10-30T16:25:21.671Z",
"name": "bash",
"turn": 1,
"input": {
"command": "ls /opt/freestyle/python/lib/python3.12/site-packages/qase/; cat /opt/freestyle/python/lib/python3.12/site-packages/qase/__init__.py; pip show -f qase-api-client 2>/dev/null | grep -m5 'Location\\|api_client'"
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-b75ac76ea160391a",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 46,
"ts": "2026-10-30T16:25:21.981Z",
"turn": 1,
"output": {
"content": [
{
"text": "__init__.py\n__pycache__\napi_client_v1\nLocation: /opt/freestyle/python/lib/python3.12/site-packages\n qase/api_client_v1/__init__.py\n qase/api_client_v1/__pycache__/__init__.cpython-312.pyc\n qase/api_client_v1/__pycache__/api_client.cpython-312.pyc\n qase/api_client_v1/__pycache__/api_response.cpython-312.pyc\n",
"type": "text"
}
]
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-b75ac76ea160391a",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
SDK v2 uses qase.api_client_v1. Let's verify the import and look up the correct usage names (ApiClient, ProjectsApi, CasesApi, RunsApi).
python3 - <<'EOF' from qase.api_client_v1 import ApiClient, Configuration from qase.api_client_v1.api import ProjectsApi, CasesApi, RunsApi import qase.api_client_v1 as m models = [n for n in dir(m) if 'CaseCreate' in n or 'RunCreate' in n or 'ProjectCreate' in n] print(models) import inspect print([p for p in inspect.signature(CasesApi.case_create).parameters]) print([p for p in inspect.signature(RunsApi.run_create).parameters]) EOF
Failed['ProjectCreate', 'RunCreate', 'RunCreateCloudRunConfig', 'TestCaseCreate']
['ProjectCreate', 'RunCreate', 'RunCreateCloudRunConfig', 'TestCaseCreate'] Traceback (most recent call last): File "<stdin>", line 7, in <module> AttributeError: type object 'CasesApi' has no attribute 'case_create' Command exited with code 1
Recorded tool call
{
"type": "tool_call",
"seq": 49,
"ts": "2026-10-30T16:25:23.474Z",
"name": "bash",
"turn": 1,
"input": {
"command": "python3 - <<'EOF'\nfrom qase.api_client_v1 import ApiClient, Configuration\nfrom qase.api_client_v1.api import ProjectsApi, CasesApi, RunsApi\nimport qase.api_client_v1 as m\nmodels = [n for n in dir(m) if 'CaseCreate' in n or 'RunCreate' in n or 'ProjectCreate' in n]\nprint(models)\nimport inspect\nprint([p for p in inspect.signature(CasesApi.case_create).parameters])\nprint([p for p in inspect.signature(RunsApi.run_create).parameters])\nEOF"
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-8028872035e52ef1",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 50,
"ts": "2026-10-30T16:25:25.049Z",
"turn": 1,
"output": {
"content": [
{
"text": "['ProjectCreate', 'RunCreate', 'RunCreateCloudRunConfig', 'TestCaseCreate']\nTraceback (most recent call last):\n File \"<stdin>\", line 7, in <module>\nAttributeError: type object 'CasesApi' has no attribute 'case_create'\n\n\nCommand exited with code 1",
"type": "text"
}
],
"details": {}
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-8028872035e52ef1",
"is_error": true,
"tool_kind": "shell"
}›Thinking…
The SDK can be imported without issues. The method names are different, so I'll look up the actual method names.
python3 - <<'EOF'
from qase.api_client_v1.api import ProjectsApi, CasesApi, RunsApi
for cls in (ProjectsApi, CasesApi, RunsApi):
print(cls.__name__, [m for m in dir(cls) if not m.startswith('_') and 'create' in m or m.startswith(('get','delete','update')) and not m.startswith('_')][:12])
import inspect
print('case_create?' , [m for m in dir(CasesApi) if 'create' in m])
print(inspect.signature(CasesApi.create_case) if hasattr(CasesApi,'create_case') else '')
EOFProjectsApi ['create_project', 'create_project_with_http_info', 'create_project_without_preload_content', 'delete_project', 'delete_project_with_http_info', 'de
ProjectsApi ['create_project', 'create_project_with_http_info', 'create_project_without_preload_content', 'delete_project', 'delete_project_with_http_info', 'delete_project_without_preload_content', 'get_project', 'get_project_with_http_info', 'get_project_without_preload_content', 'get_projects', 'get_projects_with_http_info', 'get_projects_without_preload_content'] CasesApi ['create_case', 'create_case_with_http_info', 'create_case_without_preload_content', 'delete_case', 'delete_case_with_http_info', 'delete_case_without_preload_content', 'get_case', 'get_case_with_http_info', 'get_case_without_preload_content', 'get_cases', 'get_cases_with_http_info', 'get_cases_without_preload_content'] RunsApi ['create_run', 'create_run_with_http_info', 'create_run_without_preload_content', 'delete_run', 'delete_run_with_http_info', 'delete_run_without_preload_content', 'get_run', 'get_run_with_http_info', 'get_run_without_preload_content', 'get_runs', 'get_runs_with_http_info', 'get_runs_without_preload_content'] case_create? ['_create_case_serialize', 'create_case', 'create_case_with_http_info', 'create_case_without_preload_content'] (self, code: Annotated[str, FieldInfo(annotation=NoneType, required=True, description='Code of project, where to search entities.', metadata=[Strict(strict=True), MinLen(min_length=2), MaxLen(max_length=10)])], test_case_create: qase.api_client_v1.models.test_case_create.TestCaseCreate, _request_timeout: Union[NoneType, Annotated[float, Strict(strict=True), FieldInfo(annotation=NoneType, required=True, metadata=[Gt(gt=0)])], Tuple[Annotated[float, Strict(strict=True), FieldInfo(annotation=NoneType, required=True, metadata=[Gt(gt=0)])], Annotated[float, Strict(strict=True), FieldInfo(annotation=NoneType, required=True, metadata=[Gt(gt=0)])]]] = None, _request_auth: Optional[Dict[Annotated[str, Strict(strict=True)], Any]] = None, _content_type: Optional[Annotated[str, Strict(strict=True)]] = None, _headers: Optional[Dict[Annotated[str, Strict(strict=True)], Any]] = None, _host_index: Annotated[int, Strict(strict=True), FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0), Le(le=0)])] = 0) -> qase.api_client_v1.models.id_response.IdResponse
Recorded tool call
{
"type": "tool_call",
"seq": 53,
"ts": "2026-10-30T16:25:26.331Z",
"name": "bash",
"turn": 1,
"input": {
"command": "python3 - <<'EOF'\nfrom qase.api_client_v1.api import ProjectsApi, CasesApi, RunsApi\nfor cls in (ProjectsApi, CasesApi, RunsApi):\n print(cls.__name__, [m for m in dir(cls) if not m.startswith('_') and 'create' in m or m.startswith(('get','delete','update')) and not m.startswith('_')][:12])\nimport inspect\nprint('case_create?' , [m for m in dir(CasesApi) if 'create' in m])\nprint(inspect.signature(CasesApi.create_case) if hasattr(CasesApi,'create_case') else '')\nEOF"
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-b815f3e055ca56f6",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 54,
"ts": "2026-10-30T16:25:27.875Z",
"turn": 1,
"output": {
"content": [
{
"text": "ProjectsApi ['create_project', 'create_project_with_http_info', 'create_project_without_preload_content', 'delete_project', 'delete_project_with_http_info', 'delete_project_without_preload_content', 'get_project', 'get_project_with_http_info', 'get_project_without_preload_content', 'get_projects', 'get_projects_with_http_info', 'get_projects_without_preload_content']\nCasesApi ['create_case', 'create_case_with_http_info', 'create_case_without_preload_content', 'delete_case', 'delete_case_with_http_info', 'delete_case_without_preload_content', 'get_case', 'get_case_with_http_info', 'get_case_without_preload_content', 'get_cases', 'get_cases_with_http_info', 'get_cases_without_preload_content']\nRunsApi ['create_run', 'create_run_with_http_info', 'create_run_without_preload_content', 'delete_run', 'delete_run_with_http_info', 'delete_run_without_preload_content', 'get_run', 'get_run_with_http_info', 'get_run_without_preload_content', 'get_runs', 'get_runs_with_http_info', 'get_runs_without_preload_content']\ncase_create? ['_create_case_serialize', 'create_case', 'create_case_with_http_info', 'create_case_without_preload_content']\n(self, code: Annotated[str, FieldInfo(annotation=NoneType, required=True, description='Code of project, where to search entities.', metadata=[Strict(strict=True), MinLen(min_length=2), MaxLen(max_length=10)])], test_case_create: qase.api_client_v1.models.test_case_create.TestCaseCreate, _request_timeout: Union[NoneType, Annotated[float, Strict(strict=True), FieldInfo(annotation=NoneType, required=True, metadata=[Gt(gt=0)])], Tuple[Annotated[float, Strict(strict=True), FieldInfo(annotation=NoneType, required=True, metadata=[Gt(gt=0)])], Annotated[float, Strict(strict=True), FieldInfo(annotation=NoneType, required=True, metadata=[Gt(gt=0)])]]] = None, _request_auth: Optional[Dict[Annotated[str, Strict(strict=True)], Any]] = None, _content_type: Optional[Annotated[str, Strict(strict=True)]] = None, _headers: Optional[Dict[Annotated[str, Strict(strict=True)], Any]] = None, _host_index: Annotated[int, Strict(strict=True), FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0), Le(le=0)])] = 0) -> qase.api_client_v1.models.id_response.IdResponse\n",
"type": "text"
}
]
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-b815f3e055ca56f6",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
SDK confirmed. Next, write sample scripts:
qase_example.py: reads QASE_API_TOKEN from an environment variable, creates a project (or uses an existing QASE_PROJECT_CODE), creates test cases, creates a run including those cases, and displays links. Add--dry-run? Keep it simple: guard against missing token with a clear message.
Check the required fields of the model: ProjectCreate(title, code), TestCaseCreate(title), RunCreate(title, cases?). Let me quickly check the required fields of RunCreate and TestCaseCreate. Also, the fields of ProjectCreate include code (2-10 characters), title, and description.
After that, write a README.md including pricing, setup, and usage instructions. Try running without a token → expect a clear error message to appear (blocked). Also, verify that the script reaches the API with a fake token → should get a 401 back, which proves connectivity. This is a quick call, not something long-running.
The SDK is fine (the package is qase-api-client, and the module is qase.api_client_v1). Next, I'll verify the required model fields and create a sample.
python3 - <<'EOF'
from qase.api_client_v1 import ProjectCreate, TestCaseCreate, RunCreate, Configuration
for m in (ProjectCreate, TestCaseCreate, RunCreate):
req = [k for k,v in m.model_fields.items() if v.is_required()]
print(m.__name__, 'required:', req)
print(Configuration.get_default_copy().host)
EOFProjectCreate required: ['title', 'code']
ProjectCreate required: ['title', 'code'] TestCaseCreate required: ['title'] RunCreate required: ['title'] https://api.qase.io/v1
Recorded tool call
{
"type": "tool_call",
"seq": 57,
"ts": "2026-10-30T16:25:30.430Z",
"name": "bash",
"turn": 1,
"input": {
"command": "python3 - <<'EOF'\nfrom qase.api_client_v1 import ProjectCreate, TestCaseCreate, RunCreate, Configuration\nfor m in (ProjectCreate, TestCaseCreate, RunCreate):\n req = [k for k,v in m.model_fields.items() if v.is_required()]\n print(m.__name__, 'required:', req)\nprint(Configuration.get_default_copy().host)\nEOF"
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-aa58019cd6797e61",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 58,
"ts": "2026-10-30T16:25:31.984Z",
"turn": 1,
"output": {
"content": [
{
"text": "ProjectCreate required: ['title', 'code']\nTestCaseCreate required: ['title']\nRunCreate required: ['title']\nhttps://api.qase.io/v1\n",
"type": "text"
}
]
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-aa58019cd6797e61",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
Qase's developer workflow is a hosted REST API + SDK. No local stack needed. Create the following files:
- qase_example.py — end-to-end example: project → test case → run, cleanup optional.
- README.md — overview, pricing, setup, usage instructions.
Make sure the script exits cleanly if no token is provided. Then test with a dummy token to confirm it reaches the API and receives a 401 (proving that the code path works up until authentication). This is a short single HTTP call, so it's fine.
Qase does have a genuine developer-facing workflow: a hosted REST API (https://api.qase.io/v1) and an official SDK — no local stack needed. I've confirmed the Python SDK (qase-api-client). Currently building a sample.
File edits
1 file
Writtenqase_example.pyView changes
/sandbox/repo/qase_example.py
Written content · previous contents were not recorded
#!/usr/bin/env python3"""Minimal end-to-end Qase example using the official Python SDK.Flow: create project -> create test case -> create test run containing that case.Requires:pip install qase-api-clientexport QASE_API_TOKEN=<your token> # Qase web app -> Settings -> API tokensOptionally:export QASE_PROJECT_CODE=DEMO # reuse an existing project instead of creating one"""import osimport sysfrom qase.api_client_v1 import (ApiClient,Configuration,ProjectCreate,RunCreate,TestCaseCreate,)from qase.api_client_v1.api import CasesApi, ProjectsApi, RunsApiTOKEN = os.environ.get("QASE_API_TOKEN")PROJECT_CODE = os.environ.get("QASE_PROJECT_CODE", "").upper()def main() -> int:if not TOKEN:print("QASE_API_TOKEN is not set.", file=sys.stderr)print("Create one at https://app.qase.io (Settings -> API tokens) and export it.",file=sys.stderr)return 1config = Configuration()config.api_key["TokenAuth"] = TOKENwith ApiClient(config) as client:projects, cases, runs = ProjectsApi(client), CasesApi(client), RunsApi(client)# 1. Project (skip if QASE_PROJECT_CODE points at an existing one)code = PROJECT_CODE or "PYDEMO"if PROJECT_CODE:projects.get_project(code) # raises if it doesn't existprint(f"Using existing project {code}")else:projects.create_project(ProjectCreate(title="Python SDK Demo", code=code,description="Created by qase_example.py"))print(f"Created project {code}")# 2. Test casecase_id = cases.create_case(code,TestCaseCreate(title="Login with valid credentials",description="Verify a user can sign in with a valid email/password.",preconditions="A test account exists.",steps=None,),).result.idprint(f"Created test case #{case_id}")# 3. Test run containing the caserun_id = runs.create_run(code,RunCreate(title="Smoke run from SDK example", cases=[case_id]),).result.idprint(f"Created test run #{run_id}")print(f"\nDone. View it at: https://app.qase.io/project/{code}/runs/{run_id}")return 0if __name__ == "__main__":sys.exit(main())
Source: write · chatcmpl-tool-9196412e5e0ff3ea
Recorded tool call
{
"type": "tool_call",
"seq": 61,
"ts": "2026-10-30T16:25:36.352Z",
"name": "write",
"turn": 1,
"input": {
"path": "/sandbox/repo/qase_example.py",
"content": "#!/usr/bin/env python3\n\"\"\"Minimal end-to-end Qase example using the official Python SDK.\n\nFlow: create project -> create test case -> create test run containing that case.\n\nRequires:\n pip install qase-api-client\n export QASE_API_TOKEN=<your token> # Qase web app -> Settings -> API tokens\n\nOptionally:\n export QASE_PROJECT_CODE=DEMO # reuse an existing project instead of creating one\n\"\"\"\n\nimport os\nimport sys\n\nfrom qase.api_client_v1 import (\n ApiClient,\n Configuration,\n ProjectCreate,\n RunCreate,\n TestCaseCreate,\n)\nfrom qase.api_client_v1.api import CasesApi, ProjectsApi, RunsApi\n\nTOKEN = os.environ.get(\"QASE_API_TOKEN\")\nPROJECT_CODE = os.environ.get(\"QASE_PROJECT_CODE\", \"\").upper()\n\n\ndef main() -> int:\n if not TOKEN:\n print(\"QASE_API_TOKEN is not set.\", file=sys.stderr)\n print(\"Create one at https://app.qase.io (Settings -> API tokens) and export it.\",\n file=sys.stderr)\n return 1\n\n config = Configuration()\n config.api_key[\"TokenAuth\"] = TOKEN\n\n with ApiClient(config) as client:\n projects, cases, runs = ProjectsApi(client), CasesApi(client), RunsApi(client)\n\n # 1. Project (skip if QASE_PROJECT_CODE points at an existing one)\n code = PROJECT_CODE or \"PYDEMO\"\n if PROJECT_CODE:\n projects.get_project(code) # raises if it doesn't exist\n print(f\"Using existing project {code}\")\n else:\n projects.create_project(\n ProjectCreate(title=\"Python SDK Demo\", code=code,\n description=\"Created by qase_example.py\")\n )\n print(f\"Created project {code}\")\n\n # 2. Test case\n case_id = cases.create_case(\n code,\n TestCaseCreate(\n title=\"Login with valid credentials\",\n description=\"Verify a user can sign in with a valid email/password.\",\n preconditions=\"A test account exists.\",\n steps=None,\n ),\n ).result.id\n print(f\"Created test case #{case_id}\")\n\n # 3. Test run containing the case\n run_id = runs.create_run(\n code,\n RunCreate(title=\"Smoke run from SDK example\", cases=[case_id]),\n ).result.id\n print(f\"Created test run #{run_id}\")\n\n print(f\"\\nDone. View it at: https://app.qase.io/project/{code}/runs/{run_id}\")\n return 0\n\n\nif __name__ == \"__main__\":\n sys.exit(main())\n"
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-9196412e5e0ff3ea",
"tool_kind": "file_edit"
}Recorded tool result
{
"type": "tool_result",
"seq": 62,
"ts": "2026-10-30T16:25:36.352Z",
"turn": 1,
"output": {
"content": [
{
"text": "Successfully wrote 2469 bytes to /sandbox/repo/qase_example.py",
"type": "text"
}
]
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-9196412e5e0ff3ea",
"is_error": false,
"tool_kind": "file_edit"
}›Thinking…
Check the signature of create_case: the steps parameter — is it required for TestCaseCreate? Only title is required. steps=None might be fine, but passing steps=None explicitly could fail validation? Usually it's fine. Check the create_case call and do a dry check of the model construction locally (no network needed): constructing a TestCaseCreate object with steps=None. Also verify the response path .result.id — create_case returns an IdResponse that has a result field with an id. Let me test the object construction.
cd /sandbox/repo && python3 - <<'EOF'
from qase.api_client_v1 import TestCaseCreate, RunCreate, ProjectCreate, IdResponse
tc = TestCaseCreate(title="Login", description="d", preconditions="p", steps=None)
rc = RunCreate(title="Smoke", cases=[1])
pc = ProjectCreate(title="T", code="PYDEMO", description="d")
print("models ok")
import inspect; print([f for f in IdResponse.model_fields])
EOF
python3 -c "import ast; ast.parse(open('/sandbox/repo/qase_example.py').read()); print('syntax ok')"models ok
models ok ['status', 'result'] syntax ok
Recorded tool call
{
"type": "tool_call",
"seq": 65,
"ts": "2026-10-30T16:25:38.382Z",
"name": "bash",
"turn": 1,
"input": {
"command": "cd /sandbox/repo && python3 - <<'EOF'\nfrom qase.api_client_v1 import TestCaseCreate, RunCreate, ProjectCreate, IdResponse\ntc = TestCaseCreate(title=\"Login\", description=\"d\", preconditions=\"p\", steps=None)\nrc = RunCreate(title=\"Smoke\", cases=[1])\npc = ProjectCreate(title=\"T\", code=\"PYDEMO\", description=\"d\")\nprint(\"models ok\")\nimport inspect; print([f for f in IdResponse.model_fields])\nEOF\npython3 -c \"import ast; ast.parse(open('/sandbox/repo/qase_example.py').read()); print('syntax ok')\""
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-86129b9a21213c34",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 66,
"ts": "2026-10-30T16:25:39.984Z",
"turn": 1,
"output": {
"content": [
{
"text": "models ok\n['status', 'result']\nsyntax ok\n",
"type": "text"
}
]
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-86129b9a21213c34",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
The model constructs without issues, and IdResponse.result.id exists. Next, testing with a fake token — a single quick HTTP call, expecting a 401, which proves that the code path reaches the hosted API. Should I set QASE_PROJECT_CODE to skip project creation? No — with a fake token, the first call (create_project) will 401 anyway. Run it and catch the exception to demonstrate the behavior. Also, test the path without a token.
cd /sandbox/repo && python3 qase_example.py; echo "exit(no token)=$?"; echo ---; QASE_API_TOKEN=dummy python3 qase_example.py 2>&1 | tail -3;
QASE_API_TOKEN is not set.
QASE_API_TOKEN is not set.
Create one at https://app.qase.io (Settings -> API tokens) and export it.
exit(no token)=1
---
HTTP response headers: HTTPHeaderDict({'Date': 'Fri, 30 Oct 2026 16:25:43 GMT', 'Content-Type': 'application/json', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Cache-Control': 'no-cache, private', 'X-RateLimit-Limit': '1000', 'X-RateLimit-Remaining': '999', 'RateLimit': '"token";r=999;t=60', 'RateLimit-Policy': '"token";q=1000;w=60', 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains'})
HTTP response body: {"error":"Unauthenticated."}
Recorded tool call
{
"type": "tool_call",
"seq": 69,
"ts": "2026-10-30T16:25:41.568Z",
"name": "bash",
"turn": 1,
"input": {
"command": "cd /sandbox/repo && python3 qase_example.py; echo \"exit(no token)=$?\"; echo ---; QASE_API_TOKEN=dummy python3 qase_example.py 2>&1 | tail -3; ",
"timeout": 60
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-a5dfdf1a23857d30",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 70,
"ts": "2026-10-30T16:25:44.649Z",
"turn": 1,
"output": {
"content": [
{
"text": "QASE_API_TOKEN is not set.\nCreate one at https://app.qase.io (Settings -> API tokens) and export it.\nexit(no token)=1\n---\nHTTP response headers: HTTPHeaderDict({'Date': 'Fri, 30 Oct 2026 16:25:43 GMT', 'Content-Type': 'application/json', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Cache-Control': 'no-cache, private', 'X-RateLimit-Limit': '1000', 'X-RateLimit-Remaining': '999', 'RateLimit': '\"token\";r=999;t=60', 'RateLimit-Policy': '\"token\";q=1000;w=60', 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains'})\nHTTP response body: {\"error\":\"Unauthenticated.\"}\n\n",
"type": "text"
}
]
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-a5dfdf1a23857d30",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
I was able to verify it works. With a dummy token, the API call path executes all the way through to the hosted API, and (as expected) a 401 is returned. Next, I'll write a README that includes pricing and usage instructions, then wrap things up with the following content: pricing, how easy it is to manage, and the blocker (a real API token is required — I can't sign up on the user's behalf).
File edits
1 file
WrittenREADME.mdView changes
/sandbox/repo/README.md
Written content · previous contents were not recorded
# Qase SDK ExampleMinimal end-to-end example against the **hosted** Qase API (no local services):create a project → create a test case → create a test run containing that case.## Setup```bashpip install qase-api-clientexport QASE_API_TOKEN=<your token> # app.qase.io -> Settings -> API tokens```Optional: `export QASE_PROJECT_CODE=DEMO` to reuse an existing projectinstead of creating a new one.## Run```bashpython3 qase_example.py```Example output:```Created project PYDEMOCreated test case #1Created test run #1Done. View it at: https://app.qase.io/project/PYDEMO/runs/1```## Notes- Base URL: `https://api.qase.io/v1`; auth via the `TokenAuth` API key header.- Rate limit observed from response headers: 1000 requests/min per token.- Free tier allows 5k API-submitted test results/month and up to 2 projects.
Source: write · chatcmpl-tool-b39e8cada8b8c12a
Recorded tool call
{
"type": "tool_call",
"seq": 73,
"ts": "2026-10-30T16:25:46.371Z",
"name": "write",
"turn": 1,
"input": {
"path": "/sandbox/repo/README.md",
"content": "# Qase SDK Example\n\nMinimal end-to-end example against the **hosted** Qase API (no local services):\ncreate a project → create a test case → create a test run containing that case.\n\n## Setup\n\n```bash\npip install qase-api-client\nexport QASE_API_TOKEN=<your token> # app.qase.io -> Settings -> API tokens\n```\n\nOptional: `export QASE_PROJECT_CODE=DEMO` to reuse an existing project\ninstead of creating a new one.\n\n## Run\n\n```bash\npython3 qase_example.py\n```\n\nExample output:\n\n```\nCreated project PYDEMO\nCreated test case #1\nCreated test run #1\n\nDone. View it at: https://app.qase.io/project/PYDEMO/runs/1\n```\n\n## Notes\n\n- Base URL: `https://api.qase.io/v1`; auth via the `TokenAuth` API key header.\n- Rate limit observed from response headers: 1000 requests/min per token.\n- Free tier allows 5k API-submitted test results/month and up to 2 projects.\n"
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-b39e8cada8b8c12a",
"tool_kind": "file_edit"
}Recorded tool result
{
"type": "tool_result",
"seq": 74,
"ts": "2026-10-30T16:25:46.371Z",
"turn": 1,
"output": {
"content": [
{
"text": "Successfully wrote 848 bytes to /sandbox/repo/README.md",
"type": "text"
}
]
},
"run_id": "cmvv6ncir0gs60ipx5qtaraxz",
"tool_id": "chatcmpl-tool-b39e8cada8b8c12a",
"is_error": false,
"tool_kind": "file_edit"
}›Thinking…
Done. To summarize: what I built, pricing (live-fetched from qase.io/pricing today), how easy it is to manage, and the blocker (I need a real token — I'm blocked from completing a live run). Keep it concise.
Done. Here's the summary:
What I built
/sandbox/repo/qase_example.py— end-to-end example using the official Python SDK (qase-api-client, moduleqase.api_client_v1): creates a project → test case → test run, all against the hosted API (https://api.qase.io/v1). No local stack, nothing long-running./sandbox/repo/README.md— setup + usage.
Verified as far as possible without credentials: SDK imports cleanly, models construct correctly, and running with a dummy token reaches the live hosted API and gets the expected 401 {"error":"Unauthenticated."} — so the code path works end-to-end up to auth.
Pricing (pulled live from qase.io/pricing today)
- Free — $0/user/month, forever: up to 2 projects, 500 MB storage, 30-day test history, 5k API-submitted results/month.
- Teams — $35/user/month billed annually ($42 monthly): unlimited projects/runs/storage, SSO, RBAC, Qase query language, 35+ integrations; 14-day free trial.
- Enterprise — custom pricing.
- Add-on: $10 collaborator seats (view-only folks who just follow releases).
Easy for me to manage?
Yes. Clean REST API + generated SDKs, simple token auth, generous rate limit (I saw 1000 req/min in the response headers), and predictable JSON errors. The free tier is plenty for automated demos like this one.
Blocked?
One thing: I need a real QASE_API_TOKEN to do an actual live run (project/case/run creation). I can't sign up for an account on your behalf. Grab a token at app.qase.io → Settings → API tokens, export QASE_API_TOKEN=..., and rerun python3 qase_example.py — everything else is ready to go.
AX Fundamentals
23 checks. Open an area for details.
This check is a quick preview. Test more tasks and models with Gauge Agents.
Test your product with Gauge Agents