Files
APIClient-Agent/README.md
Anand Shukla 01662f7e0e Initial release — APIClient - Agent v2.0.0
AI-first API testing desktop client built with Python + PyQt6.

Features:
- Multi-tab HTTP request editor with params/headers/body/auth/tests
- KeyValueTable with per-row enable/disable checkboxes and 36px rows
- Format JSON button, syntax highlighting, pre-request & test scripts
- Collections, environments, history, import/export (Postman v2.1, cURL)
- OpenAPI 3.x / Swagger 2.0 local parser (no AI tokens)
- EKIKA Odoo API Framework generator — JSON-API, REST JSON, GraphQL,
  Custom REST JSON with all auth types (instant, no AI tokens)
- Persistent AI chat sidebar (Claude-powered co-pilot) with streaming,
  context-aware suggestions, and one-click Apply to request editor
- AI collection generator from any docs URL or pasted spec
- WebSocket client, Mock server, Collection runner, Code generator
- Dark/light theme engine (global QSS, object-name selectors)
- SSL error detection with actionable hints
- MIT License

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 17:38:57 +05:30

392 lines
14 KiB
Markdown

# APIClient - Agent
> **AI-first API testing desktop client** — built with Python + PyQt6.
> Specialised for the [EKIKA Odoo API Framework](https://apps.odoo.com/apps/modules/19.0/api_framework), but works with any REST, GraphQL, or WebSocket API.
---
## Features
### Core API Testing
- **Multi-tab request editor** — work on multiple requests simultaneously, drag to reorder
- **All HTTP methods** — GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
- **Smart params & headers table** — per-row enable/disable checkboxes, 36 px comfortable rows, auto-expanding blank row
- **Body editor** — raw JSON/XML/text with syntax highlighting, **Format JSON** button, `application/vnd.api+json` support
- **Auth panel** — Bearer Token, Basic Auth, API Key (header or query)
- **Pre-request scripts** — Python executed before each request; access `pm.environment.get/set`
- **Test scripts** — assertions auto-run after every response; `pm.test(...)` / `expect(...)` DSL
- **Response viewer** — syntax-highlighted body, headers table, test results, search, copy, save
- **WebSocket client** — connect, send, receive, log messages
- **Mock server** — local HTTP mock with configurable routes
### Collections & Environments
- **Collections sidebar** — import/export Postman Collection v2.1 JSON, cURL
- **Environment variables** — `{{base_url}}`, `{{api_key}}`, etc. resolved at send time; per-environment values
- **Collection runner** — run all requests in a collection, view pass/fail results
- **History** — every sent request automatically saved
### AI Co-pilot (Claude-powered)
- **Persistent AI chat sidebar** — toggle with the `✦ AI` button or `Ctrl+Shift+A`
- **Full context awareness** — AI sees your current request (method, URL, headers, body, params, test scripts) and the last response (status, body, errors); secrets are automatically redacted
- **Streaming responses** — tokens stream in real time
- **One-click Apply** — AI suggestions come with **Apply Body**, **Apply Params**, **Apply Headers**, **Apply Test Script** buttons that set the values directly in the request editor
- **Multi-turn conversation** — full history maintained per session; Clear to reset
- **Quick actions** — Analyze, Fix Error, Gen Body, Write Tests, Auth Help, Explain Response
- **EKIKA Odoo collection generator** — generate complete collections for JSON-API, REST JSON, GraphQL, and Custom REST JSON without spending AI tokens; supports all auth types
### EKIKA Odoo API Framework specialisation
- Generates full CRUD + Execute / Export / Report / Fields / Access-Rights endpoints per model
- Auth types: API Key (`x-api-key`), Basic Auth, User Credentials, OAuth2, JWT, Public
- Correct JSON-API body format out of the box: `{"data": {"type": "sale.order", "attributes": {...}}}`
- Automatic environment creation with `base_url`, `api_key`, tokens
---
## Installation
### Requirements
- Python 3.11+
- Linux, macOS, or Windows
```bash
git clone https://git.ekika.co/EKIKA.co/APIClient-Agent.git
cd APIClient-Agent
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
python main.py
```
### requirements.txt
```
PyQt6>=6.6.0
httpx>=0.27.0
websockets>=12.0
anthropic>=0.25.0
pyyaml>=6.0
pyinstaller>=6.0.0
```
---
## Quick Start
### 1 — Send your first request
1. Launch the app: `python main.py`
2. Type a URL in the bar, e.g. `https://jsonplaceholder.typicode.com/todos/1`
3. Press **Send** (or `Ctrl+Enter`)
4. See the JSON response with syntax highlighting in the bottom panel
### 2 — Use environment variables
1. Click **Manage****New Environment** → name it `My API`
2. Add variables:
```
base_url = https://api.example.com
api_key = your-secret-key
```
3. Select the environment in the top bar
4. In the URL bar, type `{{base_url}}/v1/users`
5. In Headers, add `Authorization: Bearer {{api_key}}`
6. Variables are resolved automatically at send time
### 3 — Import a collection
**From Postman export:**
1. `File → Import…`
2. Paste Postman Collection v2.1 JSON or drop the file
**From cURL:**
```
File → Import… → paste:
curl -X POST https://api.example.com/v1/orders \
-H "Content-Type: application/json" \
-d '{"product_id": 42, "qty": 1}'
```
**From OpenAPI spec:**
1. `Tools → AI Assistant → Import from Docs`
2. Paste the OpenAPI JSON/YAML URL — parsed instantly, no AI tokens used
---
## EKIKA Odoo API Framework — Complete Example
### Generate a collection in 30 seconds
1. Open **Tools → AI Assistant** (or click `✦ AI` → `AI Assistant` in the menu)
2. Select the **EKIKA Odoo API** tab
3. Fill in:
| Field | Example |
|---|---|
| Instance URL | `https://mycompany.odoo.com` |
| API Endpoint | `/user-jsonapi-apikey` |
| API Kind | `JSON-API` |
| Auth Type | `API Key` |
| API Key | `EwKCljvZoHXsaGlxxvCHt1h4SvWLpuWW` |
| Models | `sale.order, res.partner, account.move` |
| Operations | ✓ List, Get, Create, Update, Delete |
4. Click **Generate Collection** — preview appears instantly
5. Click **Import Both** — collection + environment are saved
This generates the following requests for each model with zero AI tokens:
```
GET {{base_url}}/user-jsonapi-apikey/sale.order
GET {{base_url}}/user-jsonapi-apikey/sale.order/{{id}}
POST {{base_url}}/user-jsonapi-apikey/sale.order
PATCH {{base_url}}/user-jsonapi-apikey/sale.order/{{id}}
DELETE {{base_url}}/user-jsonapi-apikey/sale.order/{{id}}
```
### Sending a JSON-API request
The generated **Create sale.order** request body:
```json
{
"data": {
"type": "sale.order",
"attributes": {
"name": "New Order"
}
}
}
```
Headers sent automatically:
```
x-api-key: EwKCljvZoHXsaGlxxvCHt1h4SvWLpuWW
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
```
### Filtering and pagination (List endpoint)
The **List sale.order** request includes query params:
```
page[number] = 1
page[size] = 10
fields[sale.order] = id,name,display_name,partner_id
sort = -id
```
To filter by customer, open the AI chat sidebar and ask:
> *"Add a filter param to get only sale orders for partner ID 7"*
AI responds with an apply block you can apply in one click.
### GraphQL example
Select **API Kind: GraphQL**. The generator creates:
**List sale.order (GraphQL)**
```json
{
"query": "query {\n sale_order(\n filter: \"\"\n pageSize: 10\n pageNumber: 1\n ) {\n id\n name\n display_name\n }\n}"
}
```
**Create sale.order (GraphQL)**
```json
{
"query": "mutation {\n create_sale_order(\n attributes: {\n name: \"New Record\"\n }\n ) {\n id\n name\n }\n}"
}
```
---
## AI Chat Co-pilot — Example Session
Click **✦ AI** in the top bar to open the sidebar. The AI automatically knows what request you have open and the last response.
### Debugging a 401 error
```
You: I'm getting 401 Unauthorized on all my Odoo API requests.
AI: A 401 on the EKIKA JSON-API endpoint means the x-api-key header is
missing, empty, or incorrect.
Checklist:
1. Confirm your environment has api_key set (Tools → Environments)
2. Confirm the request Headers tab includes x-api-key: {{api_key}}
3. In Odoo, verify the API key is still active under your user's
API Framework settings
Here are the correct headers to apply:
┌─ apply:headers ──────────────────────────────────┐
│ x-api-key: {{api_key}} │
│ Accept: application/vnd.api+json │
└──────────────────────────────────────────────────┘
[ Apply Headers to Request ]
```
Click **Apply Headers to Request** — headers are set immediately and the Headers tab opens.
### Generating a body for a complex model
```
You: Generate a body to create an invoice (account.move) for partner ID 14,
with one line for product ID 7, quantity 3, price 150.
AI: Here is a JSON-API compliant body for creating an account.move:
┌─ apply:body ─────────────────────────────────────┐
│ { │
│ "data": { │
│ "type": "account.move", │
│ "attributes": { │
│ "move_type": "out_invoice", │
│ "partner_id": 14, │
│ "invoice_line_ids": [[0, 0, { │
│ "product_id": 7, │
│ "quantity": 3, │
│ "price_unit": 150.0 │
│ }]] │
│ } │
│ } │
│ } │
└──────────────────────────────────────────────────┘
[ Apply Body to Request ]
```
### Writing test scripts
```
You: Write tests to verify a successful JSON-API list response.
AI: ┌─ apply:test ─────────────────────────────────────┐
│ pm.test('Status 200', lambda: │
│ pm.response.to_have_status(200)) │
│ pm.test('Has data array', lambda: │
│ expect(pm.response.json()).to_have_key('data'))│
│ pm.test('Data is list', lambda: │
│ expect(pm.response.json()['data']).to_be_list())│
│ pm.test('Response time < 2s', lambda: │
│ expect(pm.response.response_time).to_be_below(2000))│
└──────────────────────────────────────────────────┘
[ Apply Test Script to Request ]
```
---
## Keyboard Shortcuts
| Shortcut | Action |
|---|---|
| `Ctrl+Enter` | Send request |
| `Ctrl+T` | New tab |
| `Ctrl+W` | Close tab |
| `Ctrl+S` | Save to collection |
| `Ctrl+F` | Search requests |
| `Ctrl+E` | Manage environments |
| `Ctrl+Shift+A` | Toggle AI chat sidebar |
| `Ctrl+Shift+F` | Format JSON body |
| `Escape` | Cancel in-flight request |
| `Ctrl+Q` | Quit |
---
## Project Structure
```
APIClient-Agent/
├── main.py # Entry point
├── requirements.txt
├── LICENSE
├── app/
│ ├── models.py # HttpRequest, HttpResponse, Environment
│ ├── core/
│ │ ├── storage.py # SQLite persistence (collections, environments, history)
│ │ ├── http_client.py # httpx-based request engine, variable resolution
│ │ ├── ai_client.py # Claude API — collection generation from docs
│ │ ├── ai_chat.py # Claude API — multi-turn conversational co-pilot
│ │ ├── openapi_parser.py # OpenAPI 3.x / Swagger 2.0 local parser
│ │ ├── ekika_odoo_generator.py# EKIKA Odoo framework collection generator
│ │ ├── test_runner.py # pm.test / expect assertion engine
│ │ ├── mock_server.py # Local HTTP mock server
│ │ ├── code_gen.py # Code generation (curl, Python, JS, etc.)
│ │ ├── exporter.py # Postman Collection v2.1 export
│ │ └── importer.py # Postman Collection / cURL import
│ └── ui/
│ ├── main_window.py # Main window, splitter layout, env bar
│ ├── theme.py # Central QSS stylesheet engine (dark/light)
│ ├── request_panel.py # URL bar, params/headers/body/auth/tests editor
│ ├── response_panel.py # Response viewer with status badge
│ ├── tabs_manager.py # Multi-tab request manager
│ ├── sidebar.py # Collections tree sidebar
│ ├── ai_panel.py # AI Assistant dialog (collection generator)
│ ├── ai_chat_panel.py # AI chat sidebar (co-pilot)
│ ├── environment_dialog.py # Environment manager
│ ├── collection_runner.py # Collection runner
│ ├── websocket_panel.py # WebSocket client
│ ├── mock_server_panel.py # Mock server UI
│ ├── import_dialog.py # Import dialog
│ ├── code_gen_dialog.py # Code generation dialog
│ ├── search_dialog.py # Request search
│ └── highlighter.py # JSON syntax highlighter
```
---
## Configuration
Settings are stored in an SQLite database at `~/.apiclient_agent/data.db` (created automatically).
### Anthropic API Key (for AI features)
1. Get a key at [console.anthropic.com](https://console.anthropic.com)
2. In the app: `Tools → AI Assistant → Settings tab`
3. Paste the key and click **Save API Key**
The key is stored locally in the SQLite database only — never transmitted except to the Anthropic API.
---
## SSL / TLS Notes
Some servers (especially demo/development instances) use self-signed certificates or wildcard certificates that don't match the exact hostname. If you see:
```
SSL certificate error — could not connect to https://...
Tip: disable SSL verification in the request Settings tab.
```
Open the **Settings** tab in the request editor and uncheck **Verify SSL certificate**.
---
## Building a Standalone Executable
```bash
pyinstaller --onefile --windowed \
--name "APIClient-Agent" \
--add-data "app:app" \
main.py
```
The executable is produced in `dist/APIClient-Agent`.
---
## Contributing
1. Fork the repository
2. Create a feature branch: `git checkout -b feature/my-feature`
3. Commit your changes: `git commit -m "Add my feature"`
4. Push and open a pull request
Please keep UI styling in `theme.py` using `setObjectName()` selectors — never inline `setStyleSheet()` for static colors.
---
## License
[MIT License](LICENSE) — Copyright (c) 2026 EKIKA.co