Snakk AI - Voice Agent Platform API
    • HubSpot setup guide
    • Partner Developer Documentation
    • System
      • Simple health check
        GET
      • Detailed health check with dependency status
        GET
    • Tenants
      • Create new tenant (signup)
        POST
    • Agents
      • List all agents for tenant
        GET
      • Create new agent
        POST
      • Get agent details
        GET
      • Delete agent
        DELETE
      • Duplicate an agent
        POST
    • Tools
      • List tools/webhooks for agent
        GET
      • Add tool/webhook to agent
        POST
    • Calls
      • Start outbound call from database agent
        POST
      • Start outbound call with ad-hoc agent config (JSON)
        POST
      • List call history
        GET
      • Get call details
        GET
      • Diagnose recording issues
        GET
      • Call statistics
        GET
      • Fix recording data
        POST
    • Phone Numbers
      • List your phone numbers
        GET
      • Available numbers to claim
        GET
      • Claim a number from pool
        POST
      • Assign number to agent
        POST
      • Unassign number from agent
        POST
      • Release number (return to pool)
        POST
    • Statistics
      • Dashboard overview
      • Daily usage statistics
      • Monthly usage statistics
    • Subscription
      • Current subscription
      • Available plans
      • Request plan upgrade
    • Web Access
      • Generate web widget token
    • AI Tools
      • AI Prompt Generator
    • Account
      • Your account info
      • Regenerate API key
    • Platform Admin
      • Platform-wide overview (admin only)
    • Knowledge Base
      • List knowledge base files
      • Upload document to knowledge base
      • Delete knowledge base file
    • Chat Widget
      • Get chat widget config
      • Start chat session
      • Send chat message
      • Close chat session
      • List chat sessions
      • Get chat session details
      • Chat statistics
      • Get chat widget configuration
      • Update chat widget configuration
      • Close inactive sessions
      • Upload chat avatar/logo
      • Delete chat avatar/logo
      • Poll session status for human handoff
      • Poll session status (POST to avoid caching)
      • Get chat history
    • Version History
      • List agent version history
      • Get specific version details
      • Compare two versions
      • Restore agent to version
    • Workflows
      • List all workflows
      • Create workflow
      • Get workflow
      • Update workflow
      • Delete workflow
      • Publish workflow
      • Get version history
      • Rollback to version
      • Assign workflow to agent
      • Remove workflow from agent
    • Chat Operator
      • Get operator statistics
      • Get escalated chat queue
      • Get operator's active chats
      • Claim a chat from queue
      • Release a chat
      • Send message as operator
      • Update operator online status
      • Get contact requests
      • Update contact request
      • Create contact request
      • Subscribe to operator events (SSE)
      • Get all messages for a session
      • Update customer info for session
    • Chat Verification
      • Check if agent has protected tools
      • Initiate identity verification
      • Check verification status
    • Tool Logs
      • List tool call logs
      • Get single tool log
      • Get tool usage statistics
    • Schemas
      • Tenant
      • Agent
      • Call
      • ToolLog
      • AgentTool

    Partner Developer Documentation

    Partner Developer Documentation#

    Build integrations that thousands of AI voice agents can use. Once approved, your integration becomes available to all Snakk.ai customers.

    Table of Contents#

    1.
    Getting Started
    2.
    How Integrations Work
    3.
    Integration Definition Format
    4.
    Authentication
    5.
    Action Types
    6.
    Mock Mode (required)
    7.
    Submission & Review Process
    8.
    API Reference
    9.
    Best Practices
    10.
    Security Requirements
    11.
    Revenue Share

    Getting Started#

    Prerequisites#

    A Partner Account on Snakk.ai (contact partners@snakk.ai)
    Your own API for AI agents to call (or an existing SaaS API)
    Familiarity with REST APIs and JSON Schema

    From Idea to Production in 4 Steps#

    1. DEFINE     →  Write the JSON specification for your integration
    2. SUBMIT     →  POST to /api/partner/integrations
    3. REVIEW     →  Snakk team tests it (1-3 days)
    4. LIVE       →  Available to all customers ✓

    API Base URL#

    https://api.snakk.ai

    Authentication#

    All partner endpoints require your partner API key:

    How Integrations Work#

    An integration consists of:
    Provider — the service itself (e.g. "Acme CRM")
    Actions — operations the AI agent can perform (e.g. "lookup-contact", "create-deal")
    When a customer enables your integration:
    1.
    The customer connects their own account (OAuth2 or API key)
    2.
    Credentials are stored encrypted (AES-256-GCM) per customer
    3.
    The AI agent can use actions automatically during conversations
    4.
    Every action call is logged for analytics

    Three Usage Contexts#

    ContextWhenExample
    during_callAI uses it as a tool during conversation"Look up customer in CRM"
    end_of_callRuns automatically after the call"Save call summary"
    bothEither"Send SMS" (during or after)

    Integration Definition Format#

    An integration is defined as a JSON object:
    {
      "slug": "acme-crm",
      "name": "Acme CRM",
      "description": "Our popular CRM system for SMBs",
      "category": "crm",
      "auth_type": "api_key",
      "api_key_config": {
        "fields": [
          {
            "key": "api_key",
            "label": "API Key",
            "required": true,
            "secret": true
          },
          {
            "key": "subdomain",
            "label": "Subdomain (e.g. yourcompany)",
            "required": true,
            "secret": false
          }
        ]
      },
      "actions": [
        {
          "slug": "lookup-contact",
          "name": "Lookup Contact",
          "description": "Find a contact by phone, email, or name",
          "usage_context": "during_call",
          "execution_type": "http",
          "http_config": {
            "url": "https://{{subdomain}}.acme.com/api/v1/contacts/search?q={{query}}",
            "method": "GET",
            "headers": {
              "Authorization": "Bearer {{api_key}}",
              "Content-Type": "application/json"
            },
            "response_mapping": {
              "found": "$.results.length > 0",
              "contact_id": "$.results[0].id",
              "name": "$.results[0].full_name",
              "email": "$.results[0].email",
              "phone": "$.results[0].phone"
            }
          },
          "parameters_schema": {
            "type": "object",
            "properties": {
              "query": {
                "type": "string",
                "description": "Phone number, email, or name to search"
              }
            },
            "required": ["query"]
          },
          "agent_instructions": "MANDATORY: Look up the caller at the start of every conversation using the customer's phone number to identify them.",
          "mock_response": {
            "found": true,
            "contact_id": "abc123",
            "name": "Ola Nordmann",
            "email": "ola@firma.no",
            "phone": "+4712345678"
          }
        }
      ]
    }

    Field Specification#

    Provider#

    FieldTypeRequiredDescription
    slugstring✅Unique identifier (kebab-case). Auto-prefixed with partner-
    namestring✅Display name (shown to customers)
    descriptionstring✅Short description of the service
    categorystring✅See category list
    auth_typestring✅oauth2, api_key, or none
    oauth_configobject⚠️Required if oauth2
    api_key_configobject⚠️Required if api_key

    Action#

    FieldTypeRequiredDescription
    slugstring✅Unique per provider (kebab-case)
    namestring✅Display name
    descriptionstring✅Used as the description for the AI
    usage_contextstring✅during_call, end_of_call, or both
    execution_typestring✅http or flow (built_in reserved for first-party)
    http_configobject⚠️Required if http
    flow_definitionobject⚠️Required if flow
    parameters_schemaobject✅JSON Schema for input parameters
    agent_instructionsstring⚠️Recommended for during_call actions
    mock_responseobject✅Required — returned in test mode

    Categories#

    crm, accounting, calendar, booking, email, sms, communication,
    helpdesk, ecommerce, healthcare, productivity, marketing, hr, other

    Authentication#

    OAuth2#

    Used for services where the customer logs in via OAuth (Google, Microsoft, etc.).
    {
      "auth_type": "oauth2",
      "oauth_config": {
        "authorization_url": "https://acme.com/oauth/authorize",
        "token_url": "https://acme.com/oauth/token",
        "scopes": ["read", "write"],
        "userinfo_url": "https://acme.com/api/me",
        "extra_params": {
          "access_type": "offline",
          "prompt": "consent"
        }
      }
    }
    Client credentials are stored in Snakk's env vars as {SLUG_UPPER}_CLIENT_ID and {SLUG_UPPER}_CLIENT_SECRET. Send them via encrypted email to partners@snakk.ai after approval.
    Redirect URI to configure with your OAuth provider:
    https://api.snakk.ai/api/integrations/oauth/partner-{slug}/callback

    API Key#

    Used for services where the customer has an API key.
    {
      "auth_type": "api_key",
      "api_key_config": {
        "fields": [
          { "key": "api_key", "label": "API Key", "required": true, "secret": true },
          { "key": "subdomain", "label": "Subdomain", "required": true, "secret": false }
        ]
      }
    }
    Fields are rendered as a form in the Snakk UI. secret: true hides the field as a password. Values are stored encrypted and available as template variables in http_config.

    None#

    For public APIs that don't require authentication (rare).

    Action Types#

    HTTP#

    Most common — your API is called via HTTP with templated URL/headers/body:
    {
      "execution_type": "http",
      "http_config": {
        "url": "https://api.example.com/v1/resource/{{id}}",
        "method": "POST",
        "headers": {
          "Authorization": "Bearer {{api_key}}",
          "Content-Type": "application/json"
        },
        "body_template": {
          "name": "{{customer_name}}",
          "email": "{{customer_email}}",
          "metadata": {
            "source": "snakk-ai",
            "phone": "{{caller_phone}}"
          }
        },
        "response_mapping": {
          "success": "$.status == 'created'",
          "id": "$.data.id",
          "message": "$.message"
        },
        "timeout_ms": 5000
      }
    }
    Template variables:
    {{param_name}} — from agent input
    {{api_key}}, {{subdomain}} — from credentials
    {{caller_phone}} — from call context
    Response mapping uses JSONPath ($-syntax) to extract values from the response body.

    Flow#

    For complex multi-step actions (rare for partners — try HTTP first):
    {
      "execution_type": "flow",
      "flow_definition": {
        "nodes": [
          { "id": "trigger", "type": "trigger", "data": {} },
          {
            "id": "step1",
            "type": "http_request",
            "data": {
              "method": "GET",
              "url": "https://api.example.com/check/{{trigger.id}}"
            }
          },
          {
            "id": "condition1",
            "type": "condition",
            "data": { "expression": "{{step1.found}} == true" }
          },
          {
            "id": "return_success",
            "type": "return",
            "data": { "output_mapping": { "result": "{{step1.data}}" } }
          }
        ],
        "edges": [
          { "source": "trigger", "target": "step1" },
          { "source": "step1", "target": "condition1" },
          { "source": "condition1", "target": "return_success", "sourceHandle": "true" }
        ]
      }
    }
    See the Flow Builder documentation for the full node reference.

    Mock Mode (required)#

    Every action MUST include mock_response. This is returned when the customer tests the agent in the platform UI (instead of calling your real API).

    Why?#

    Customers can test the full conversation flow without booking real appointments / creating real data
    You avoid spam data from development testing
    The Snakk team can validate your integration without your credentials

    Example#

    {
      "slug": "create-contact",
      "mock_response": {
        "success": true,
        "contact_id": "mock-12345",
        "name": "Test Customer",
        "message": "Contact created (TEST MODE)"
      }
    }
    The mock response should be realistic — use the same fields and structure your real API would return.

    Submission & Review Process#

    1. Submit#

    Response:
    {
      "success": true,
      "provider_id": "uuid",
      "slug": "partner-acme-crm",
      "status": "pending_review",
      "message": "Integration submitted for review."
    }

    2. Review (1-3 business days)#

    The Snakk team verifies:
    ✅ Mock responses work
    ✅ HTTP configuration is valid
    ✅ URLs pass SSRF validation (HTTPS only, no internal IPs)
    ✅ agent_instructions are clear and helpful for the AI
    ✅ Descriptions are understandable for non-technical customers
    ✅ Data Processing Agreement (DPA) is signed

    3. Approval#

    You'll receive an email when your integration is approved. It becomes immediately available to all customers.

    4. Updates#

    To update an existing integration:
    Changes to action logic require a new review.

    API Reference#

    Partner Endpoints#

    All endpoints require X-API-Key: YOUR_PARTNER_KEY.

    POST /api/partner/integrations#

    Submit a new integration.
    Request body: See Integration Definition Format
    Response: 201 Created with provider_id and status: "pending_review"

    GET /api/partner/integrations#

    List all your integrations.
    Response:
    {
      "integrations": [
        {
          "id": "uuid",
          "slug": "partner-acme-crm",
          "name": "Acme CRM",
          "is_active": true,
          "actions": [...]
        }
      ]
    }

    PATCH /api/partner/integrations/:providerId#

    Update an existing integration.
    Request body:
    {
      "name": "Updated Name",
      "description": "New description",
      "actions": [
        {
          "id": "action-uuid",
          "name": "Updated Action",
          "description": "...",
          "parameters_schema": {...},
          "http_config": {...},
          "mock_response": {...}
        }
      ]
    }

    GET /api/partner/integrations/:providerId/stats#

    Get usage statistics for the last 30 days.
    Response:
    {
      "provider": "Acme CRM",
      "slug": "partner-acme-crm",
      "installations": 34,
      "stats": {
        "total_calls": 1247,
        "successful_calls": 1225,
        "success_rate": 98.2,
        "avg_latency_ms": 380,
        "period": "last_30_days"
      }
    }

    Best Practices#

    Descriptions for the AI#

    description and agent_instructions are used by OpenAI to determine when and how the action should be called.
    ❌ Bad:
    {
      "description": "Function for getting user data",
      "agent_instructions": "Use this function"
    }
    ✅ Good:
    {
      "description": "Look up a customer in the CRM by phone, email, or name. Returns contact details if found.",
      "agent_instructions": "MANDATORY: Call this at the START of every conversation using the caller's phone number {{customer.number}}. Do not greet the customer until you have their information. If found, use their name in the greeting."
    }

    Parameters Schema#

    Use JSON Schema with clear descriptions:
    {
      "type": "object",
      "properties": {
        "phone": {
          "type": "string",
          "description": "Customer phone number in E.164 format (e.g. +4712345678)"
        },
        "service_type": {
          "type": "string",
          "enum": ["consultation", "support", "sales"],
          "description": "Type of meeting requested"
        },
        "duration_minutes": {
          "type": "integer",
          "default": 30,
          "minimum": 15,
          "maximum": 120,
          "description": "Meeting duration in minutes"
        }
      },
      "required": ["phone", "service_type"]
    }

    Response Shapes#

    Be consistent. The AI learns the pattern:
    For lookup/read:
    {
      "found": true,
      "<entity_id>": "...",
      "...other fields"
    }
    or
    {
      "found": false,
      "message": "No customer found"
    }
    For create/update/action:
    {
      "success": true,
      "<entity_id>": "...",
      "message": "Human-readable confirmation"
    }
    or
    {
      "success": false,
      "error": "Specific error message"
    }

    Localization#

    If your service targets a specific market, you can localize:
    name and description can be in any language (these are shown to customers)
    Action name should generally stay in English (used by AI internally)
    mock_response can include localized text where appropriate

    Security Requirements#

    URL Validation (SSRF)#

    All HTTP URLs are validated:
    ✅ HTTPS only (no http://)
    ❌ No private IP ranges (10.x, 172.16-31.x, 192.168.x, 127.x, 169.254.x)
    ❌ No localhost, 0.0.0.0, or cloud metadata IPs

    Timeouts & Rate Limits#

    Per request: 5 seconds (default), 10 seconds (max, set via http_config.timeout_ms)
    Response size: 1 MB max
    Rate limiting: Per integration per customer (varies)

    Data Protection#

    All communication over HTTPS
    Credentials stored encrypted (AES-256-GCM)
    Customer data sent to your API must be protected per your DPA
    Snakk reserves the right to suspend integrations that violate security rules

    What You CANNOT Do#

    ❌ Cannot use built_in execution type (reserved for first-party)
    ❌ Cannot forward Snakk credentials to third parties
    ❌ Cannot aggregate data across customers without consent
    ❌ Cannot send PII to logging services without encryption

    Revenue Share#

    Revenue share details are negotiated individually with Snakk. Standard:
    70/30 split (partner/Snakk) for partner-driven integrations
    Monthly payouts
    Minimum payout: 500 NOK
    You invoice Snakk based on actual usage stats (available via /stats endpoint)
    For volume deals or exclusive partnerships, contact partners@snakk.ai.

    Example: Complete HubSpot-light Integration#

    Here's a full example integration you can use as a template:
    {
      "slug": "acme-crm",
      "name": "Acme CRM",
      "description": "Cloud-based CRM for sales and support teams",
      "category": "crm",
      "auth_type": "api_key",
      "api_key_config": {
        "fields": [
          { "key": "api_key", "label": "API Key", "required": true, "secret": true },
          { "key": "subdomain", "label": "Subdomain", "required": true, "secret": false }
        ]
      },
      "actions": [
        {
          "slug": "lookup-contact",
          "name": "Lookup Contact",
          "description": "Find a contact in Acme CRM by phone, email, or name",
          "usage_context": "during_call",
          "execution_type": "http",
          "http_config": {
            "url": "https://{{subdomain}}.acme.com/api/v1/contacts/search?q={{query}}",
            "method": "GET",
            "headers": {
              "Authorization": "Bearer {{api_key}}"
            },
            "response_mapping": {
              "found": "$.total > 0",
              "contact_id": "$.contacts[0].id",
              "name": "$.contacts[0].full_name",
              "email": "$.contacts[0].email",
              "phone": "$.contacts[0].phone"
            }
          },
          "parameters_schema": {
            "type": "object",
            "properties": {
              "query": { "type": "string", "description": "Phone, email, or name" }
            },
            "required": ["query"]
          },
          "agent_instructions": "MANDATORY: Look up the caller using their phone number at the START of every conversation. Use their name in the greeting if found.",
          "mock_response": {
            "found": true,
            "contact_id": "abc123",
            "name": "Ola Nordmann",
            "email": "ola@firma.no",
            "phone": "+4712345678"
          }
        },
        {
          "slug": "create-contact",
          "name": "Create Contact",
          "description": "Create a new contact in Acme CRM",
          "usage_context": "both",
          "execution_type": "http",
          "http_config": {
            "url": "https://{{subdomain}}.acme.com/api/v1/contacts",
            "method": "POST",
            "headers": {
              "Authorization": "Bearer {{api_key}}",
              "Content-Type": "application/json"
            },
            "body_template": {
              "full_name": "{{name}}",
              "email": "{{email}}",
              "phone": "{{phone}}",
              "source": "voice-agent"
            },
            "response_mapping": {
              "success": "$.id != null",
              "contact_id": "$.id",
              "message": "Contact created"
            }
          },
          "parameters_schema": {
            "type": "object",
            "properties": {
              "name": { "type": "string", "description": "Full name of the contact" },
              "email": { "type": "string", "description": "Email address" },
              "phone": { "type": "string", "description": "Phone number" }
            },
            "required": ["name"]
          },
          "agent_instructions": "Use this to create a new contact when the caller is not found in the CRM. Always confirm name and contact info before creating.",
          "mock_response": {
            "success": true,
            "contact_id": "mock-456",
            "message": "Contact created (TEST MODE)"
          }
        },
        {
          "slug": "log-call-summary",
          "name": "Log Call Summary",
          "description": "Save the call transcript and summary as a note in Acme CRM",
          "usage_context": "end_of_call",
          "execution_type": "http",
          "http_config": {
            "url": "https://{{subdomain}}.acme.com/api/v1/notes",
            "method": "POST",
            "headers": {
              "Authorization": "Bearer {{api_key}}",
              "Content-Type": "application/json"
            },
            "body_template": {
              "phone": "{{caller_phone}}",
              "subject": "Call from voice agent",
              "body": "{{summary}}\n\n---\nFull transcript:\n{{transcript}}"
            }
          },
          "parameters_schema": {
            "type": "object",
            "properties": {}
          },
          "mock_response": {
            "success": true,
            "note_id": "mock-note-789",
            "message": "Note added to contact"
          }
        }
      ]
    }

    Questions?#

    📧 Email: partners@snakk.ai
    💬 Slack: snakk-partners.slack.com
    📚 Full platform docs: doc.snakk.ai
    We can't wait to see what you build. 🚀
    Modified at 2026-04-15 01:39:20
    Previous
    HubSpot setup guide
    Next
    Simple health check
    Built with