Skip to content
On this page

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

SkillEndpoint PrefixOperations
Agent Script/users/scriptRead, update
Guard Rails/guard-railsList, create, update, delete, test
Lead Collection/lead-collectionRead config, update config, retry webhook, list leads
Rate Limiting/rate-limit/configRead, update
Analysis/analysisRead config, update config, trigger
Account/accountStatus, interaction history
User Settings/usersAPI 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:

FieldTypeDefaultDescription
severitystring"medium""low", "medium", "high", "critical"
correction_promptstringnullInjected into system prompt when triggered
response_overridestringnullReplaces entire LLM response when triggered
email_contactsstring[]nullEmails to alert when triggered
enabledbooleantrueActive 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 custom account 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 custom account 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

  1. Set the agent script:

    PUT /users/script → { "script": "You are a helpful assistant..." }
    
  2. Create guard rails:

    POST /guard-rails → { "name": "No PII", "description": "...", "severity": "high" }
    POST /guard-rails → { "name": "Off-topic", "description": "...", "severity": "medium" }
    
  3. Test guard rails:

    POST /guard-rails/:id/test → { "input": "test message" }
    
  4. Configure rate limiting:

    PUT /rate-limit/config → { "enabled": true, "max_messages_per_session": 20 }
    
  5. Configure lead collection:

    PUT /lead-collection/config → { "enabled": true, "webhooks": [...] }
    

Audit and Tune Existing Setup

  1. List guard rails:

    GET /guard-rails
    
  2. Check trigger counts to identify frequently triggered rails.

  3. Disable or adjust high-trigger rails:

    PUT /guard-rails/:id → { "enabled": false }
    
  4. Review account usage:

    GET /account/status
    
  5. Check 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:

CodeMeaning
400Bad request — missing or invalid parameters
401Unauthorized — no valid authentication provided
403Forbidden — insufficient permissions (e.g., non-custom account accessing model selection)
404Not found — resource doesn't exist or doesn't belong to user
405Method 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 custom account 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/test before 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-key and use it for all agentic workflows.
  • Respect rate limits — check GET /account/status for usage before bulk operations.

Resources