Appearance
Metadata
name: Canny Bot Control description: Control Canny Bot's chat widget configuration via API — manage agent scripts, guard rails, lead collection, rate limiting, analysis, and account settings programmatically.
Overview
This skill provides full API control over a Canny Bot account. Use it when a user asks to configure, audit, or modify their chat widget setup programmatically. All endpoints accept API key authentication, enabling agentic workflows without manual dashboard interaction.
Authentication
All endpoints require authentication via one of:
x-api-key: <your_api_key>
or
?api_key=<your_api_key>
or Bearer token:
Authorization: Bearer <jwt_token>
Never hardcode API keys in scripts. Always load from environment variables or secure storage.
Base URL
https://api.canny.bot/api
Skills Overview
| Skill | Endpoint Prefix | Operations |
|---|---|---|
| Agent Script | /users/script | Read, update |
| Guard Rails | /guard-rails | List, create, update, delete, test |
| Lead Collection | /lead-collection | Read config, update config, retry webhook, list leads |
| Rate Limiting | /rate-limit/config | Read, update |
| Analysis | /analysis | Read config, update config, trigger |
| Account | /account | Status, interaction history |
| User Settings | /users | API keys, LLM models, script |
Agent Script
The system prompt that defines the chat widget's personality and behavior.
Get Script
GET /users/script
Response:
json
{
"data": {
"script": "You are a helpful assistant..."
}
}
Update Script
PUT /users/script
Content-Type: application/json
{
"script": "You are a helpful assistant for ACME Corp. Always greet users warmly..."
}
Response:
json
{
"success": true,
"script": "You are a helpful assistant for ACME Corp..."
}
Guard Rails
Safety rules that evaluate user input before it reaches the LLM. Each rail uses an LLM classifier to detect violations.
List All Guard Rails
GET /guard-rails
Response:
json
{
"data": [
{
"documentId": "abc123",
"name": "No PII",
"description": "Block requests asking for personal information",
"severity": "high",
"correction_prompt": "Please don't share personal information.",
"response_override": null,
"email_contacts": ["admin@example.com"],
"enabled": true,
"trigger_count": 3
}
]
}
Create Guard Rail
POST /guard-rails
Content-Type: application/json
{
"name": "No Competitor Mentions",
"description": "Detect when users mention competitor products",
"severity": "medium",
"correction_prompt": "Redirect the conversation to our product's strengths.",
"response_override": null,
"email_contacts": [],
"enabled": true
}
Required fields: name, description
Optional fields:
| Field | Type | Default | Description |
|---|---|---|---|
severity | string | "medium" | "low", "medium", "high", "critical" |
correction_prompt | string | null | Injected into system prompt when triggered |
response_override | string | null | Replaces entire LLM response when triggered |
email_contacts | string[] | null | Emails to alert when triggered |
enabled | boolean | true | Active state |
Update Guard Rail
PUT /guard-rails/:id
Content-Type: application/json
{
"enabled": false,
"severity": "critical"
}
All fields optional — only provided fields are updated.
Delete Guard Rail
DELETE /guard-rails/:id
Test Guard Rail
Test a rail against sample input before enabling:
POST /guard-rails/:id/test
Content-Type: application/json
{
"input": "What is your social security number?"
}
Response:
json
{
"data": {
"triggered": true,
"rail": {
"id": "abc123",
"name": "No PII",
"severity": "high"
},
"correction": "Please don't share personal information.",
"override": null
}
}
Lead Collection
Manage lead collection configuration, retry failed webhooks, and retrieve leads.
Get Config
GET /lead-collection/config
Response:
json
{
"data": {
"enabled": true,
"webhooks": [
{
"url": "https://example.com/webhook",
"active": true,
"lead_statuses": ["success", "partial"],
"headers": [{ "key": "Authorization", "value": "Bearer token123" }]
}
],
"inactivity_threshold_minutes": 30,
"data_collection_parameters": ["name", "email", "phone"]
}
}
Update Config
PUT /lead-collection/config
Content-Type: application/json
{
"enabled": true,
"webhooks": [
{
"url": "https://example.com/webhook",
"active": true,
"lead_statuses": ["success", "partial", "failed"],
"headers": [
{ "key": "Authorization", "value": "Bearer token123" }
]
}
],
"inactivity_threshold_minutes": 45,
"data_collection_parameters": ["name", "email"]
}
Retry Failed Webhook
POST /lead-collection/retry-webhook
Content-Type: application/json
{
"lead_id": "lead_document_id_here"
}
List Leads
GET /lead-collection/leads?page=1&pageSize=50&status=success
Query parameters:
page(optional): Page number (default: 1)pageSize(optional): Items per page (default: 50)status(optional): Filter by"success","partial","failed"
Rate Limiting
Configure session-based rate limiting for the chat widget.
Get Config
GET /rate-limit/config
Response:
json
{
"data": {
"enabled": true,
"max_messages_per_session": 20,
"cooldown_seconds": 60,
"max_messages_per_minute": 5,
"custom_message": ""
}
}
Update Config
PUT /rate-limit/config
Content-Type: application/json
{
"enabled": true,
"max_messages_per_session": 30,
"cooldown_seconds": 90,
"max_messages_per_minute": 8,
"custom_message": "Please wait a moment before sending another message."
}
All fields optional — only provided fields are updated.
Analysis
Longitudinal analysis of chat interactions. Runs automatically based on threshold, or can be triggered manually.
Get Config
GET /analysis/config
Response:
json
{
"data": {
"enabled": true,
"chat_threshold": 50
}
}
Update Config
PUT /analysis/config
Content-Type: application/json
{
"enabled": true,
"chat_threshold": 100
}
Trigger Analysis
POST /analysis/trigger
Content-Type: application/json
{
"language": "en"
}
Analysis runs asynchronously. The response confirms the trigger, not the result.
Account
Get Account Status
GET /account/status
Response:
json
{
"data": {
"account": "pro",
"subscription": {
"id": "sub_123",
"status": "active",
"currentPeriodEnd": 1720000000
},
"usage": {
"current": 42,
"limit": 1000,
"remaining": 958,
"percentUsed": 4
},
"limits": {
"free": 100,
"pro": 1000,
"enterprise": 10000
}
}
}
Get Interaction History
GET /account/interactions?months=12
Query parameters:
months(optional): Number of months of history (default: 12)
User Settings
Generate API Key
POST /users/generate-api-key
Response:
json
{
"api_key": "sk_a1b2c3d4...",
"message": "API key generated successfully"
}
Revoke API Key
POST /users/revoke-api-key
List Available LLM Models
Note: Only available for
customaccount tier.
GET /users/models
Response:
json
{
"data": [
{ "id": "openai/gpt-4", "name": "GPT-4" },
{ "id": "anthropic/claude-3-opus", "name": "Claude 3 Opus" }
]
}
Save LLM Model
Note: Only available for
customaccount tier.
PUT /users/llm-model
Content-Type: application/json
{
"llm_model": "openai/gpt-4",
"llm_provider": "openai"
}
Common Workflows
Setup a New Chat Widget Configuration
Set the agent script:
PUT /users/script → { "script": "You are a helpful assistant..." }Create guard rails:
POST /guard-rails → { "name": "No PII", "description": "...", "severity": "high" } POST /guard-rails → { "name": "Off-topic", "description": "...", "severity": "medium" }Test guard rails:
POST /guard-rails/:id/test → { "input": "test message" }Configure rate limiting:
PUT /rate-limit/config → { "enabled": true, "max_messages_per_session": 20 }Configure lead collection:
PUT /lead-collection/config → { "enabled": true, "webhooks": [...] }
Audit and Tune Existing Setup
List guard rails:
GET /guard-railsCheck trigger counts to identify frequently triggered rails.
Disable or adjust high-trigger rails:
PUT /guard-rails/:id → { "enabled": false }Review account usage:
GET /account/statusCheck interaction history:
GET /account/interactions?months=6
Full Configuration Export
Run these in parallel to get the complete configuration:
GET /users/script
GET /guard-rails
GET /lead-collection/config
GET /rate-limit/config
GET /analysis/config
GET /account/status
Error Handling
All endpoints return standard HTTP error codes:
| Code | Meaning |
|---|---|
| 400 | Bad request — missing or invalid parameters |
| 401 | Unauthorized — no valid authentication provided |
| 403 | Forbidden — insufficient permissions (e.g., non-custom account accessing model selection) |
| 404 | Not found — resource doesn't exist or doesn't belong to user |
| 405 | Method not allowed — wrong HTTP method for endpoint |
Error response format:
json
{
"error": "Bad Request",
"message": "Descriptive error message"
}
Security Considerations
- Never hardcode API keys in scripts or skill files.
- Load credentials from environment variables or secure storage.
- Revoke compromised API keys immediately via
POST /users/revoke-api-key. - Only
customaccount tier users can access LLM model selection endpoints. - All endpoints are scoped to the authenticated user — no cross-user access is possible.
Best Practices
- Start with a GET before making changes — always read the current configuration first.
- Test guard rails with
POST /guard-rails/:id/testbefore enabling them. - Make incremental changes — update one setting at a time and verify the result.
- Export before modifying — run the full configuration export workflow to snapshot the current state.
- Use API keys for automation — generate an API key via
POST /users/generate-api-keyand use it for all agentic workflows. - Respect rate limits — check
GET /account/statusfor usage before bulk operations.
Resources
- API Reference — Full endpoint documentation
- Guard Rails Feature — How guard rails work
- Agent Script Feature — How agent scripts work
- Lead Collection Feature — Lead collection overview
- Getting Started — Initial setup guide