Skip to main content

Config-as-code

The Management API lets you treat an entire chatbot's configuration as a single desired-state document. The workflow is GitOps-style:

GET  /api/v1/chatbots/{id}/config   →   edit the document   →   POST /api/v1/chatbots/{id}/apply

You export the current config, change it (in code, in a file, in a PR), then apply the result. The server diffs your document against the live config and reconciles the difference.

1. Export the current config

curl https://www.wizchat.com/api/v1/chatbots/abc123/config \
-H "Authorization: Bearer $WIZCHAT_API_KEY"

The response is a canonical, re-appliable document:

{
"apiVersion": "wizchat/v1",
"kind": "ChatbotConfig",
"prune": true,
"spec": {
"chatbot": { "name": "Support Bot" },
"mcpServers": [ /* ... */ ],
"skills": [ /* ... */ ],
"domains": [ /* ... */ ]
}
}

getConfig requires chatbots:read plus the per-section read scopes. Sections your key cannot read are reported in _omittedSections instead of spec.

2. Edit, then dry-run

Always preview changes first. Pass ?dryRun=true to compute the plan without writing anything:

curl -X POST "https://www.wizchat.com/api/v1/chatbots/abc123/apply?dryRun=true" \
-H "Authorization: Bearer $WIZCHAT_API_KEY" \
-H "Content-Type: application/json" \
-d @config.json

A dry-run response is { "dryRun": true, "plan": [...] } — every create, update, and delete the apply would perform.

3. Apply

Drop the query flag to execute:

curl -X POST "https://www.wizchat.com/api/v1/chatbots/abc123/apply" \
-H "Authorization: Bearer $WIZCHAT_API_KEY" \
-H "Content-Type: application/json" \
-d @config.json

On full success the response is:

{
"dryRun": false,
"plan": [ /* the executed plan */ ],
"applied": [ /* ops that ran */ ],
"failed": null,
"config": { /* refreshed config document */ }
}

Prune is on by default

The array sections (mcpServers, skills, domains) are authoritative. With prune: true (the server default), any resource that exists on the chatbot but is absent from your document is deleted. Every delete is surfaced in the dry-run plan, so always dry-run before applying.

Set prune: false (on the document, or via the SDK option) for merge-only behavior — creates and updates, never deletes.

Partial failure (422)

Apply stops on the first failing operation and returns 422 Unprocessable Entity with an ApplyResult whose failed field is populated and whose applied lists the ops that succeeded before it. Apply is idempotent — fix the offending section and re-run the same document.

{
"dryRun": false,
"applied": [ /* ops that succeeded */ ],
"failed": { "op": "...", "error": { "code": "...", "message": "..." } }
}

With the SDKs

applyConfig / apply_config return an ApplyResult for both full success (200) and partial failure (422) — inspect failed rather than catching an exception for the partial case. Auth and validation errors (400/401/403/404/429) still throw.

TypeScript

import { createWizChatClient } from '@wizchat/management';

const wizchat = createWizChatClient({ apiKey: process.env.WIZCHAT_API_KEY! });

// 1. Export
const config = await wizchat.getConfig('abc123');

// 2. Edit
config.spec.chatbot.name = 'Renamed Bot';

// 3. Dry-run, then apply
const plan = await wizchat.applyConfig('abc123', config, { dryRun: true });
console.log(plan.plan);

const result = await wizchat.applyConfig('abc123', config);
if (result.failed) {
console.error('Partial failure:', result.failed);
} else {
console.log('Applied:', result.applied);
}

Python

import os
from wizchat_management import WizChatClient

with WizChatClient(api_key=os.environ["WIZCHAT_API_KEY"]) as wizchat:
# 1. Export
config = wizchat.get_config("abc123")

# 2. Edit
config.spec.chatbot.name = "Renamed Bot"

# 3. Dry-run, then apply
plan = wizchat.apply_config("abc123", config, dry_run=True)
print(plan.plan)

result = wizchat.apply_config("abc123", config) # prune defaults to True
if result.failed:
print("Partial failure:", result.failed)
else:
print("Applied:", result.applied)
tip

To keep the live config untouched for sections you don't manage, export with getConfig, change only what you need, and re-apply the whole document — the diff engine leaves unchanged sections alone.