Today we're excited to announce the Ferni Developer Platform - a comprehensive suite of APIs that let you extend voice agents with custom capabilities, integrate external services, and build sophisticated automation workflows.
What is the Developer Platform?
The Developer Platform transforms Ferni from a standalone voice AI into an extensible platform. You can now:
- Register MCP Servers - Connect external Model Context Protocol servers to give agents new tools
- Create Custom Tools - Build webhook, MCP, or prompt-based tools callable by voice
- Subscribe to Webhooks - Receive real-time events when users interact with your agents
- Track Activities - Log and query custom metrics and activities
- Build Workflows - Create multi-step automations with branching and parallel execution
- Integrate OAuth - Authenticate with external services using your own OAuth apps
Core Concepts
MCP Server Integration
The Model Context Protocol (MCP) is an open standard for connecting AI systems to external tools and data sources. With the Developer Platform, you can register your own MCP servers:
curl -X POST https://api.ferni.ai/api/v2/developers/mcp-servers \
-H "Authorization: Bearer pk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"name": "my-crm-tools",
"description": "CRM integration for customer lookups",
"transport": "http",
"endpoint": "https://my-mcp-server.example.com",
"autoConnect": true
}'
Once registered, tools from your MCP server become available to voice agents. Users can say things like "Look up customer Acme Corp" and the agent will use your MCP tools to fulfill the request.
Custom Tools
Not every tool needs a full MCP server. For simpler integrations, you can create custom tools with three execution types:
Webhook Tools - Call your HTTP endpoint when triggered:
{
"name": "create-ticket",
"displayName": "Create Support Ticket",
"type": "webhook",
"config": {
"url": "https://api.yourservice.com/tickets",
"method": "POST",
"headers": { "Authorization": "Bearer {{secrets.API_KEY}}" }
},
"parameters": {
"type": "object",
"properties": {
"title": { "type": "string" },
"priority": { "type": "string", "enum": ["low", "medium", "high"] }
}
}
}
MCP Tools - Delegate to a registered MCP server:
{
"name": "weather-lookup",
"type": "mcp",
"config": {
"serverId": "mcp_abc123",
"toolName": "get_weather"
}
}
Prompt Tools - Use LLM prompting for the response:
{
"name": "summarize-meeting",
"type": "prompt",
"config": {
"prompt": "Summarize the following meeting notes in 3 bullet points: {{input}}"
}
}
Webhook Events
Stay informed about what's happening in your agents with webhook subscriptions:
curl -X POST https://api.ferni.ai/api/v2/developers/webhooks \
-H "Authorization: Bearer pk_live_xxx" \
-d '{
"name": "Session Events",
"url": "https://your-backend.com/ferni-webhooks",
"events": [
"session.started",
"session.ended",
"tool.called",
"workflow.completed"
],
"enabled": true
}'
All webhooks are signed with HMAC-SHA256 for security. Verify signatures in your handler:
import crypto from 'crypto';
function verifyWebhook(payload: string, signature: string, secret: string): boolean {
const [timestamp, hash] = signature.split(',').map(s => s.split('=')[1]);
const expected = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${payload}`)
.digest('hex');
return hash === expected;
}
Workflow Engine
The workflow engine lets you build multi-step automations with conditions, parallel execution, and error handling:
{
"name": "Daily Standup",
"trigger": {
"type": "voice_command",
"config": { "command": "start standup" }
},
"nodes": [
{ "id": "start", "type": "start" },
{ "id": "fetch-calendar", "type": "mcp_call", "config": {
"serverId": "mcp_google",
"toolName": "calendar.getEvents",
"arguments": { "date": "today" }
}},
{ "id": "has-meetings", "type": "condition", "config": {
"expression": "fetch-calendar.result.events.length > 0"
}},
{ "id": "summarize", "type": "llm_prompt", "config": {
"prompt": "Summarize today's meetings: {{fetch-calendar.result}}"
}},
{ "id": "speak", "type": "speak", "config": {
"text": "{{summarize.result}}"
}},
{ "id": "end", "type": "end" }
],
"edges": [
{ "sourceId": "start", "targetId": "fetch-calendar" },
{ "sourceId": "fetch-calendar", "targetId": "has-meetings" },
{ "sourceId": "has-meetings", "targetId": "summarize", "condition": "true" },
{ "sourceId": "has-meetings", "targetId": "end", "condition": "false" },
{ "sourceId": "summarize", "targetId": "speak" },
{ "sourceId": "speak", "targetId": "end" }
]
}
Getting Started
1. Get API Credentials
Sign in to the Developer Console and create an API key. Keys starting with pk_live_ are for production; pk_test_ keys work in sandbox.
2. Make Your First API Call
# List your MCP servers
curl https://api.ferni.ai/api/v2/developers/mcp-servers \
-H "Authorization: Bearer pk_live_xxx"
3. Register an MCP Server
curl -X POST https://api.ferni.ai/api/v2/developers/mcp-servers \
-H "Authorization: Bearer pk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"name": "my-first-server",
"transport": "http",
"endpoint": "https://your-mcp-server.com"
}'
4. Test the Connection
curl -X POST https://api.ferni.ai/api/v2/developers/mcp-servers/mcp_xxx/test \
-H "Authorization: Bearer pk_live_xxx"
API Reference
The Developer Platform includes six main API groups:
| API | Endpoints | Description |
|---|---|---|
| MCP Servers | 7 endpoints | Register and manage external MCP servers |
| Custom Tools | 6 endpoints | Create webhook, MCP, or prompt-based tools |
| Webhooks | 7 endpoints | Subscribe to events with delivery logs |
| Activities | 6 endpoints | Track custom metrics and activities |
| Workflows | 8 endpoints | Build multi-step automations |
| OAuth | 9 endpoints | Manage external service authentication |
See the full API Reference for complete documentation.
Rate Limits
| Operation | Limit |
|---|---|
| Standard operations | 100/min |
| Read operations | 200/min |
| Write operations | 50/min |
| Expensive operations (test, execute) | 10/min |
Rate limit headers are included in every response:
X-RateLimit-Limit- Maximum requests in windowX-RateLimit-Remaining- Requests remainingX-RateLimit-Reset- Unix timestamp when limit resets
Security
- All requests require authentication via API key or Firebase token
- Secrets are encrypted at rest using AES-256-GCM
- Webhooks are signed with HMAC-SHA256
- Resource ownership is enforced - you can only access your own resources
What's Next?
We're just getting started. Coming soon:
- TypeScript SDK - Type-safe client library for Node.js
- Python SDK - Native Python client
- OpenAPI Spec - Auto-generated documentation and client generation
- Visual Workflow Editor - Build workflows in the browser
- API Explorer - Interactive API testing in the console
Resources
- API Reference - Complete endpoint documentation
- MCP Integration Guide - Deep dive on MCP
- Webhook Security - HMAC verification guide
- GitHub Examples - Sample code and templates
We can't wait to see what you build. If you have questions or feedback, reach out on Discord or Twitter.
Happy building! 🚀